草庐IT

c++ - 为什么缓存行仅适用于模拟化?

coder 2024-02-25 原文

我正在学习 simd 指令和内存缓存。 我写了一个简单的测试来比较标量和 SIMDized sqrt 计算:

#include <time.h>
#include <iostream>
using namespace std;

#include <cmath>
#include "xmmintrin.h"

#include <stdlib.h>


const int N = 16;

const int NIter = 10000;

float a[N][N] __attribute__((aligned(16)));
float b[N][N] __attribute__((aligned(16)));
float b_simd[N][N] __attribute__((aligned(16)));

int main() {

    // fill classes by random numbers
  for( int i = 0; i < N; i++ ) {
    for( int j = 0; j < N; j++ ) {
      a[i][j] = double(rand())/double(RAND_MAX);
    }
  } 

    // Scalar
  clock_t t = clock();
  for( int ii = 0; ii < NIter; ii++ )
    for( int i = 0; i < N; i++ ) {
      for( int j = 0; j < N; j++ ) {
        b[i][j] = sqrt(a[i][j]);
      }
    }
  double t1 = clock() - t;
  t1 /= CLOCKS_PER_SEC;

    // SIMD
  t = clock();
  for( int ii = 0; ii < NIter; ii++ )
    for( int i = 0; i < N; i++ ) {
      for( int j = 0; j < N; j += 4 ) {
          __m128 &a2 = reinterpret_cast<__m128&>(a[i][j]);
          __m128 &b2 = reinterpret_cast<__m128&>(b_simd[i][j]);
          b2 = _mm_sqrt_ps(a2);
      }
    }
  double t2 = clock() - t;
  t2 /= CLOCKS_PER_SEC;

  cout << "Time scalar: " << t1 << " s " << endl;
  cout << "Time SIMD:   " << t2 << " s, speed up " << t1/t2 << endl;

  return 1;
}

使用给定的代码,我得到:

Time scalar: 0.884565 s 
Time SIMD:   0.000264 s, speed up 3350.62

如果我将矩阵大小 N 从 16 更改为 20,则标量和 SIMD 的结果具有可比性:

Time scalar: 1.37275 s 
Time SIMD:   0.188165 s, speed up 7.29547

当 N == 1 时:

Time scalar: 0.00341 s 

16 个 float = 64 个字节正好是一个缓存行。因此,a 矩阵的一行安装在缓存行中,我得到了 1000 倍的 SIMDized 循环加速因子,并且没有加速到 N = 1 的标量循环。(N = 1 的标量循环执行大约 16 * 16 = 比 N=16 快 256 倍,这是在没有缓存行的情况下可以预期的结果。

这怎么可能?




如果有帮助,我已经为 N=16 生成了 asm 代码。 我不懂汇编程序,我在这里只能看到循环看起来是在 SIMD 中展开的,但我不明白为什么要产生 1000 倍的差异如此残酷。

标量程序:

#include <time.h>
#include <iostream>
using namespace std;

#include <cmath>
#include "xmmintrin.h"

#include <stdlib.h> // rand


const int N = 16; // matrix size.

const int NIter = 1000000;

float a[N][N] __attribute__((aligned(16)));
float b[N][N] __attribute__((aligned(16)));
float b_simd[N][N] __attribute__((aligned(16)));

int main() {

  for( int ii = 0; ii < NIter; ii++ )
    for( int i = 0; i < N; i++ ) {
      for( int j = 0; j < N; j++ ) {
        b[i][j] = sqrt(a[i][j]);
      }
    }

  return 1;
}

给出下一个汇编代码:

        .section __TEXT,__text_startup,regular,pure_instructions
        .align 4
        .globl _main
_main:
LFB1625:
        pushq   %r13
LCFI0:
        movl    $1000000, %r13d
        pushq   %r12
LCFI1:
        pushq   %rbp
LCFI2:
        pushq   %rbx
LCFI3:
        pushq   %rcx
LCFI4:
        .align 4
L2:
        leaq    _a(%rip), %rbx
        movl    $16, %r12d
        leaq    _b(%rip), %rbp
        .align 4
L35:
        sqrtss  (%rbx), %xmm0
        ucomiss %xmm0, %xmm0
        jp      L39
L3:
        movss   %xmm0, 0(%rbp)
        sqrtss  4(%rbx), %xmm0
        ucomiss %xmm0, %xmm0
        jp      L40
L5:
        movss   %xmm0, 4(%rbp)
        sqrtss  8(%rbx), %xmm0
        ucomiss %xmm0, %xmm0
        jp      L41
L7:
        movss   %xmm0, 8(%rbp)
        sqrtss  12(%rbx), %xmm0
        ucomiss %xmm0, %xmm0
        jp      L42
L9:
        movss   %xmm0, 12(%rbp)
        sqrtss  16(%rbx), %xmm0
        ucomiss %xmm0, %xmm0
        jp      L43
L11:
        movss   %xmm0, 16(%rbp)
        sqrtss  20(%rbx), %xmm0
        ucomiss %xmm0, %xmm0
        jp      L44
L13:
        movss   %xmm0, 20(%rbp)
        sqrtss  24(%rbx), %xmm0
        ucomiss %xmm0, %xmm0
        jp      L45
L15:
        movss   %xmm0, 24(%rbp)
        sqrtss  28(%rbx), %xmm0
        ucomiss %xmm0, %xmm0
        jp      L46
L17:
        movss   %xmm0, 28(%rbp)
        sqrtss  32(%rbx), %xmm0
        ucomiss %xmm0, %xmm0
        jp      L47
L19:
        movss   %xmm0, 32(%rbp)
        sqrtss  36(%rbx), %xmm0
        ucomiss %xmm0, %xmm0
        jp      L48
L21:
        movss   %xmm0, 36(%rbp)
        sqrtss  40(%rbx), %xmm0
        ucomiss %xmm0, %xmm0
        jp      L49
L23:
        movss   %xmm0, 40(%rbp)
        sqrtss  44(%rbx), %xmm0
        ucomiss %xmm0, %xmm0
        jp      L50
L25:
        movss   %xmm0, 44(%rbp)
        sqrtss  48(%rbx), %xmm0
        ucomiss %xmm0, %xmm0
        jp      L51
L27:
        movss   %xmm0, 48(%rbp)
        sqrtss  52(%rbx), %xmm0
        ucomiss %xmm0, %xmm0
        jp      L52
L29:
        movss   %xmm0, 52(%rbp)
        sqrtss  56(%rbx), %xmm0
        ucomiss %xmm0, %xmm0
        jp      L53
L31:
        movss   %xmm0, 56(%rbp)
        sqrtss  60(%rbx), %xmm0
        ucomiss %xmm0, %xmm0
        jp      L54
L33:
        movss   %xmm0, 60(%rbp)
        addq    $64, %rbx
        addq    $64, %rbp
        subl    $1, %r12d
        jne     L35
        subl    $1, %r13d
        jne     L2
        popq    %rdx
LCFI5:
        movl    $1, %eax
        popq    %rbx
LCFI6:
        popq    %rbp
LCFI7:
        popq    %r12
LCFI8:
        popq    %r13
LCFI9:
        ret
L54:
LCFI10:
        movss   60(%rbx), %xmm0
        call    _sqrtf
        jmp     L33
L46:
        movss   28(%rbx), %xmm0
        call    _sqrtf
        .p2align 4,,3
        jmp     L17
L45:
        movss   24(%rbx), %xmm0
        call    _sqrtf
        .p2align 4,,3
        jmp     L15
L44:
        movss   20(%rbx), %xmm0
        call    _sqrtf
        .p2align 4,,3
        jmp     L13
L43:
        movss   16(%rbx), %xmm0
        call    _sqrtf
        .p2align 4,,3
        jmp     L11
L42:
        movss   12(%rbx), %xmm0
        call    _sqrtf
        .p2align 4,,3
        jmp     L9
L41:
        movss   8(%rbx), %xmm0
        call    _sqrtf
        .p2align 4,,3
        jmp     L7
L40:
        movss   4(%rbx), %xmm0
        call    _sqrtf
        .p2align 4,,3
        jmp     L5
L39:
        movss   (%rbx), %xmm0
        call    _sqrtf
        .p2align 4,,4
        jmp     L3
L50:
        movss   44(%rbx), %xmm0
        call    _sqrtf
        .p2align 4,,3
        jmp     L25
L49:
        movss   40(%rbx), %xmm0
        call    _sqrtf
        .p2align 4,,3
        jmp     L23
L48:
        movss   36(%rbx), %xmm0
        call    _sqrtf
        .p2align 4,,3
        jmp     L21
L47:
        movss   32(%rbx), %xmm0
        call    _sqrtf
        .p2align 4,,3
        jmp     L19
L52:
        movss   52(%rbx), %xmm0
        call    _sqrtf
        .p2align 4,,3
        jmp     L29
L51:
        movss   48(%rbx), %xmm0
        call    _sqrtf
        .p2align 4,,3
        jmp     L27
L53:
        movss   56(%rbx), %xmm0
        call    _sqrtf
        .p2align 4,,3
        jmp     L31
LFE1625:
        .align 4
__GLOBAL__sub_I_test.cpp:
LFB1627:
        leaq    __ZStL8__ioinit(%rip), %rdi
        subq    $8, %rsp
LCFI11:
        call    __ZNSt8ios_base4InitC1Ev
        movq    ___dso_handle@GOTPCREL(%rip), %rdx
        leaq    __ZStL8__ioinit(%rip), %rsi
        movq    __ZNSt8ios_base4InitD1Ev@GOTPCREL(%rip), %rdi
        addq    $8, %rsp
LCFI12:
        jmp     ___cxa_atexit
LFE1627:
        .mod_init_func
        .align 3
        .quad   __GLOBAL__sub_I_test.cpp
        .globl _b_simd
        .zerofill __DATA,__pu_bss4,_b_simd,1024,4
        .globl _b
        .zerofill __DATA,__pu_bss4,_b,1024,4
        .globl _a
        .zerofill __DATA,__pu_bss4,_a,1024,4
        .static_data
__ZStL8__ioinit:
        .space  1
        .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
EH_frame1:
        .set L$set$0,LECIE1-LSCIE1
        .long L$set$0
LSCIE1:
        .long   0
        .byte   0x1
        .ascii "zR\0"
        .byte   0x1
        .byte   0x78
        .byte   0x10
        .byte   0x1
        .byte   0x10
        .byte   0xc
        .byte   0x7
        .byte   0x8
        .byte   0x90
        .byte   0x1
        .align 3
LECIE1:
LSFDE1:
        .set L$set$1,LEFDE1-LASFDE1
        .long L$set$1
LASFDE1:
        .long   LASFDE1-EH_frame1
        .quad   LFB1625-.
        .set L$set$2,LFE1625-LFB1625
        .quad L$set$2
        .byte   0
        .byte   0x4
        .set L$set$3,LCFI0-LFB1625
        .long L$set$3
        .byte   0xe
        .byte   0x10
        .byte   0x8d
        .byte   0x2
        .byte   0x4
        .set L$set$4,LCFI1-LCFI0
        .long L$set$4
        .byte   0xe
        .byte   0x18
        .byte   0x8c
        .byte   0x3
        .byte   0x4
        .set L$set$5,LCFI2-LCFI1
        .long L$set$5
        .byte   0xe
        .byte   0x20
        .byte   0x86
        .byte   0x4
        .byte   0x4
        .set L$set$6,LCFI3-LCFI2
        .long L$set$6
        .byte   0xe
        .byte   0x28
        .byte   0x83
        .byte   0x5
        .byte   0x4
        .set L$set$7,LCFI4-LCFI3
        .long L$set$7
        .byte   0xe
        .byte   0x30
        .byte   0x4
        .set L$set$8,LCFI5-LCFI4
        .long L$set$8
        .byte   0xa
        .byte   0xe
        .byte   0x28
        .byte   0x4
        .set L$set$9,LCFI6-LCFI5
        .long L$set$9
        .byte   0xe
        .byte   0x20
        .byte   0x4
        .set L$set$10,LCFI7-LCFI6
        .long L$set$10
        .byte   0xe
        .byte   0x18
        .byte   0x4
        .set L$set$11,LCFI8-LCFI7
        .long L$set$11
        .byte   0xe
        .byte   0x10
        .byte   0x4
        .set L$set$12,LCFI9-LCFI8
        .long L$set$12
        .byte   0xe
        .byte   0x8
        .byte   0x4
        .set L$set$13,LCFI10-LCFI9
        .long L$set$13
        .byte   0xb
        .align 3
LEFDE1:
LSFDE3:
        .set L$set$14,LEFDE3-LASFDE3
        .long L$set$14
LASFDE3:
        .long   LASFDE3-EH_frame1
        .quad   LFB1627-.
        .set L$set$15,LFE1627-LFB1627
        .quad L$set$15
        .byte   0
        .byte   0x4
        .set L$set$16,LCFI11-LFB1627
        .long L$set$16
        .byte   0xe
        .byte   0x10
        .byte   0x4
        .set L$set$17,LCFI12-LCFI11
        .long L$set$17
        .byte   0xe
        .byte   0x8
        .align 3
LEFDE3:
        .constructor
        .destructor
        .align 1
        .subsections_via_symbols

SIMD 程序:

#include <time.h>
#include <iostream>
using namespace std;

#include <cmath>
#include "xmmintrin.h"

#include <stdlib.h> // rand


const int N = 16; // matrix size.

const int NIter = 1000000;

float a[N][N] __attribute__((aligned(16)));
float b[N][N] __attribute__((aligned(16)));
float b_simd[N][N] __attribute__((aligned(16)));

int main() {

  for( int ii = 0; ii < NIter; ii++ )
    for( int i = 0; i < N; i++ ) {
      for( int j = 0; j < N; j += 4 ) {
          __m128 &a2 = reinterpret_cast<__m128&>(a[i][j]);
          __m128 &b2 = reinterpret_cast<__m128&>(b_simd[i][j]);
          b2 = _mm_sqrt_ps(a2);
      }
    }

  return 1;
}

给出下一个汇编代码:

        .section __TEXT,__text_startup,regular,pure_instructions
        .align 4
        .globl _main
_main:
LFB1625:
        subq    $672, %rsp
LCFI0:
        movl    $1000000, %eax
        sqrtps  240+_a(%rip), %xmm0
        sqrtps  _a(%rip), %xmm15
        sqrtps  16+_a(%rip), %xmm14
        movaps  %xmm0, -120(%rsp)
        sqrtps  256+_a(%rip), %xmm0
        sqrtps  32+_a(%rip), %xmm13
        sqrtps  48+_a(%rip), %xmm12
        movaps  %xmm0, 600(%rsp)
        sqrtps  272+_a(%rip), %xmm0
        sqrtps  64+_a(%rip), %xmm11
        sqrtps  80+_a(%rip), %xmm10
        movaps  %xmm0, 584(%rsp)
        sqrtps  288+_a(%rip), %xmm0
        sqrtps  96+_a(%rip), %xmm9
        sqrtps  112+_a(%rip), %xmm8
        movaps  %xmm0, 568(%rsp)
        sqrtps  304+_a(%rip), %xmm0
        sqrtps  128+_a(%rip), %xmm7
        sqrtps  144+_a(%rip), %xmm6
        movaps  %xmm0, 552(%rsp)
        sqrtps  320+_a(%rip), %xmm0
        sqrtps  160+_a(%rip), %xmm5
        sqrtps  176+_a(%rip), %xmm4
        movaps  %xmm0, 536(%rsp)
        sqrtps  336+_a(%rip), %xmm0
        sqrtps  192+_a(%rip), %xmm3
        sqrtps  208+_a(%rip), %xmm2
        movaps  %xmm0, 520(%rsp)
        sqrtps  352+_a(%rip), %xmm0
        sqrtps  224+_a(%rip), %xmm1
        movaps  %xmm0, 504(%rsp)
        sqrtps  368+_a(%rip), %xmm0
        movaps  %xmm0, 488(%rsp)
        sqrtps  384+_a(%rip), %xmm0
        movaps  %xmm0, 472(%rsp)
        sqrtps  400+_a(%rip), %xmm0
        movaps  %xmm0, 456(%rsp)
        sqrtps  416+_a(%rip), %xmm0
        movaps  %xmm0, 440(%rsp)
        sqrtps  432+_a(%rip), %xmm0
        movaps  %xmm0, 424(%rsp)
        sqrtps  448+_a(%rip), %xmm0
        movaps  %xmm0, 408(%rsp)
        sqrtps  464+_a(%rip), %xmm0
        movaps  %xmm0, 392(%rsp)
        sqrtps  480+_a(%rip), %xmm0
        movaps  %xmm0, 376(%rsp)
        sqrtps  496+_a(%rip), %xmm0
        movaps  %xmm0, 360(%rsp)
        sqrtps  512+_a(%rip), %xmm0
        movaps  %xmm0, 344(%rsp)
        sqrtps  528+_a(%rip), %xmm0
        movaps  %xmm0, 328(%rsp)
        sqrtps  544+_a(%rip), %xmm0
        movaps  %xmm0, 312(%rsp)
        sqrtps  560+_a(%rip), %xmm0
        movaps  %xmm0, 296(%rsp)
        sqrtps  576+_a(%rip), %xmm0
        movaps  %xmm0, 280(%rsp)
        sqrtps  592+_a(%rip), %xmm0
        movaps  %xmm0, 264(%rsp)
        sqrtps  608+_a(%rip), %xmm0
        movaps  %xmm0, 248(%rsp)
        sqrtps  624+_a(%rip), %xmm0
        movaps  %xmm0, 232(%rsp)
        sqrtps  640+_a(%rip), %xmm0
        movaps  %xmm0, 216(%rsp)
        sqrtps  656+_a(%rip), %xmm0
        movaps  %xmm0, 200(%rsp)
        sqrtps  672+_a(%rip), %xmm0
        movaps  %xmm0, 184(%rsp)
        sqrtps  688+_a(%rip), %xmm0
        movaps  %xmm0, 168(%rsp)
        sqrtps  704+_a(%rip), %xmm0
        movaps  %xmm0, 152(%rsp)
        sqrtps  720+_a(%rip), %xmm0
        movaps  %xmm0, 136(%rsp)
        sqrtps  736+_a(%rip), %xmm0
        movaps  %xmm0, 120(%rsp)
        sqrtps  752+_a(%rip), %xmm0
        movaps  %xmm0, 104(%rsp)
        sqrtps  768+_a(%rip), %xmm0
        movaps  %xmm0, 88(%rsp)
        sqrtps  784+_a(%rip), %xmm0
        movaps  %xmm0, 72(%rsp)
        sqrtps  800+_a(%rip), %xmm0
        movaps  %xmm0, 56(%rsp)
        sqrtps  816+_a(%rip), %xmm0
        movaps  %xmm0, 40(%rsp)
        sqrtps  832+_a(%rip), %xmm0
        movaps  %xmm0, 24(%rsp)
        sqrtps  848+_a(%rip), %xmm0
        movaps  %xmm0, 8(%rsp)
        sqrtps  864+_a(%rip), %xmm0
        movaps  %xmm0, -8(%rsp)
        sqrtps  880+_a(%rip), %xmm0
        movaps  %xmm0, -24(%rsp)
        sqrtps  896+_a(%rip), %xmm0
        movaps  %xmm0, -40(%rsp)
        sqrtps  912+_a(%rip), %xmm0
        movaps  %xmm0, -56(%rsp)
        sqrtps  928+_a(%rip), %xmm0
        movaps  %xmm0, -72(%rsp)
        sqrtps  944+_a(%rip), %xmm0
        movaps  %xmm0, -88(%rsp)
        sqrtps  960+_a(%rip), %xmm0
        movaps  %xmm0, -104(%rsp)
        sqrtps  976+_a(%rip), %xmm0
        movaps  %xmm0, 616(%rsp)
        sqrtps  992+_a(%rip), %xmm0
        movaps  %xmm0, 632(%rsp)
        sqrtps  1008+_a(%rip), %xmm0
        movaps  %xmm0, 648(%rsp)
        movaps  -120(%rsp), %xmm0
        .align 4
L2:
        subl    $1, %eax
        jne     L2
        movaps  %xmm0, 240+_b_simd(%rip)
        movaps  600(%rsp), %xmm0
        movl    $1, %eax
        movaps  %xmm15, _b_simd(%rip)
        movaps  %xmm0, 256+_b_simd(%rip)
        movaps  584(%rsp), %xmm0
        movaps  %xmm14, 16+_b_simd(%rip)
        movaps  %xmm0, 272+_b_simd(%rip)
        movaps  568(%rsp), %xmm0
        movaps  %xmm13, 32+_b_simd(%rip)
        movaps  %xmm0, 288+_b_simd(%rip)
        movaps  552(%rsp), %xmm0
        movaps  %xmm12, 48+_b_simd(%rip)
        movaps  %xmm0, 304+_b_simd(%rip)
        movaps  536(%rsp), %xmm0
        movaps  %xmm11, 64+_b_simd(%rip)
        movaps  %xmm0, 320+_b_simd(%rip)
        movaps  520(%rsp), %xmm0
        movaps  %xmm10, 80+_b_simd(%rip)
        movaps  %xmm0, 336+_b_simd(%rip)
        movaps  504(%rsp), %xmm0
        movaps  %xmm9, 96+_b_simd(%rip)
        movaps  %xmm0, 352+_b_simd(%rip)
        movaps  488(%rsp), %xmm0
        movaps  %xmm8, 112+_b_simd(%rip)
        movaps  %xmm0, 368+_b_simd(%rip)
        movaps  472(%rsp), %xmm0
        movaps  %xmm7, 128+_b_simd(%rip)
        movaps  %xmm6, 144+_b_simd(%rip)
        movaps  %xmm5, 160+_b_simd(%rip)
        movaps  %xmm4, 176+_b_simd(%rip)
        movaps  %xmm3, 192+_b_simd(%rip)
        movaps  %xmm2, 208+_b_simd(%rip)
        movaps  %xmm1, 224+_b_simd(%rip)
        movaps  %xmm0, 384+_b_simd(%rip)
        movaps  456(%rsp), %xmm0
        movaps  %xmm0, 400+_b_simd(%rip)
        movaps  440(%rsp), %xmm0
        movaps  %xmm0, 416+_b_simd(%rip)
        movaps  424(%rsp), %xmm0
        movaps  %xmm0, 432+_b_simd(%rip)
        movaps  408(%rsp), %xmm0
        movaps  %xmm0, 448+_b_simd(%rip)
        movaps  392(%rsp), %xmm0
        movaps  %xmm0, 464+_b_simd(%rip)
        movaps  376(%rsp), %xmm0
        movaps  %xmm0, 480+_b_simd(%rip)
        movaps  360(%rsp), %xmm0
        movaps  %xmm0, 496+_b_simd(%rip)
        movaps  344(%rsp), %xmm0
        movaps  %xmm0, 512+_b_simd(%rip)
        movaps  328(%rsp), %xmm0
        movaps  %xmm0, 528+_b_simd(%rip)
        movaps  312(%rsp), %xmm0
        movaps  %xmm0, 544+_b_simd(%rip)
        movaps  296(%rsp), %xmm0
        movaps  %xmm0, 560+_b_simd(%rip)
        movaps  280(%rsp), %xmm0
        movaps  %xmm0, 576+_b_simd(%rip)
        movaps  264(%rsp), %xmm0
        movaps  %xmm0, 592+_b_simd(%rip)
        movaps  248(%rsp), %xmm0
        movaps  %xmm0, 608+_b_simd(%rip)
        movaps  232(%rsp), %xmm0
        movaps  %xmm0, 624+_b_simd(%rip)
        movaps  216(%rsp), %xmm0
        movaps  %xmm0, 640+_b_simd(%rip)
        movaps  200(%rsp), %xmm0
        movaps  %xmm0, 656+_b_simd(%rip)
        movaps  184(%rsp), %xmm0
        movaps  %xmm0, 672+_b_simd(%rip)
        movaps  168(%rsp), %xmm0
        movaps  %xmm0, 688+_b_simd(%rip)
        movaps  152(%rsp), %xmm0
        movaps  %xmm0, 704+_b_simd(%rip)
        movaps  136(%rsp), %xmm0
        movaps  %xmm0, 720+_b_simd(%rip)
        movaps  120(%rsp), %xmm0
        movaps  %xmm0, 736+_b_simd(%rip)
        movaps  104(%rsp), %xmm0
        movaps  %xmm0, 752+_b_simd(%rip)
        movaps  88(%rsp), %xmm0
        movaps  %xmm0, 768+_b_simd(%rip)
        movaps  72(%rsp), %xmm0
        movaps  %xmm0, 784+_b_simd(%rip)
        movaps  56(%rsp), %xmm0
        movaps  %xmm0, 800+_b_simd(%rip)
        movaps  40(%rsp), %xmm0
        movaps  %xmm0, 816+_b_simd(%rip)
        movaps  24(%rsp), %xmm0
        movaps  %xmm0, 832+_b_simd(%rip)
        movaps  8(%rsp), %xmm0
        movaps  %xmm0, 848+_b_simd(%rip)
        movaps  -8(%rsp), %xmm0
        movaps  %xmm0, 864+_b_simd(%rip)
        movaps  -24(%rsp), %xmm0
        movaps  %xmm0, 880+_b_simd(%rip)
        movaps  -40(%rsp), %xmm0
        movaps  %xmm0, 896+_b_simd(%rip)
        movaps  -56(%rsp), %xmm0
        movaps  %xmm0, 912+_b_simd(%rip)
        movaps  -72(%rsp), %xmm0
        movaps  %xmm0, 928+_b_simd(%rip)
        movaps  -88(%rsp), %xmm0
        movaps  %xmm0, 944+_b_simd(%rip)
        movaps  -104(%rsp), %xmm0
        movaps  %xmm0, 960+_b_simd(%rip)
        movaps  616(%rsp), %xmm0
        movaps  %xmm0, 976+_b_simd(%rip)
        movaps  632(%rsp), %xmm0
        movaps  %xmm0, 992+_b_simd(%rip)
        movaps  648(%rsp), %xmm0
        movaps  %xmm0, 1008+_b_simd(%rip)
        addq    $672, %rsp
LCFI1:
        ret
LFE1625:
        .align 4
__GLOBAL__sub_I_test.cpp:
LFB1627:
        leaq    __ZStL8__ioinit(%rip), %rdi
        subq    $8, %rsp
LCFI2:
        call    __ZNSt8ios_base4InitC1Ev
        movq    ___dso_handle@GOTPCREL(%rip), %rdx
        leaq    __ZStL8__ioinit(%rip), %rsi
        movq    __ZNSt8ios_base4InitD1Ev@GOTPCREL(%rip), %rdi
        addq    $8, %rsp
LCFI3:
        jmp     ___cxa_atexit
LFE1627:
        .mod_init_func
        .align 3
        .quad   __GLOBAL__sub_I_test.cpp
        .globl _b_simd
        .zerofill __DATA,__pu_bss4,_b_simd,1024,4
        .globl _b
        .zerofill __DATA,__pu_bss4,_b,1024,4
        .globl _a
        .zerofill __DATA,__pu_bss4,_a,1024,4
        .static_data
__ZStL8__ioinit:
        .space  1
        .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
EH_frame1:
        .set L$set$0,LECIE1-LSCIE1
        .long L$set$0
LSCIE1:
        .long   0
        .byte   0x1
        .ascii "zR\0"
        .byte   0x1
        .byte   0x78
        .byte   0x10
        .byte   0x1
        .byte   0x10
        .byte   0xc
        .byte   0x7
        .byte   0x8
        .byte   0x90
        .byte   0x1
        .align 3
LECIE1:
LSFDE1:
        .set L$set$1,LEFDE1-LASFDE1
        .long L$set$1
LASFDE1:
        .long   LASFDE1-EH_frame1
        .quad   LFB1625-.
        .set L$set$2,LFE1625-LFB1625
        .quad L$set$2
        .byte   0
        .byte   0x4
        .set L$set$3,LCFI0-LFB1625
        .long L$set$3
        .byte   0xe
        .byte   0xa8,0x5
        .byte   0x4
        .set L$set$4,LCFI1-LCFI0
        .long L$set$4
        .byte   0xe
        .byte   0x8
        .align 3
LEFDE1:
LSFDE3:
        .set L$set$5,LEFDE3-LASFDE3
        .long L$set$5
LASFDE3:
        .long   LASFDE3-EH_frame1
        .quad   LFB1627-.
        .set L$set$6,LFE1627-LFB1627
        .quad L$set$6
        .byte   0
        .byte   0x4
        .set L$set$7,LCFI2-LFB1627
        .long L$set$7
        .byte   0xe
        .byte   0x10
        .byte   0x4
        .set L$set$8,LCFI3-LCFI2
        .long L$set$8
        .byte   0xe
        .byte   0x8
        .align 3
LEFDE3:
        .constructor
        .destructor
        .align 1
        .subsections_via_symbols

最佳答案

您是否检查过您的编译器实际上是为标量平方根发出单个汇编指令,而不是调用库函数?这可以在不引用内存访问行为的情况下解释大部分差异。

关于c++ - 为什么缓存行仅适用于模拟化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19495873/

有关c++ - 为什么缓存行仅适用于模拟化?的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  3. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  4. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  5. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  6. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  7. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  8. ruby - 如何模拟 Net::HTTP::Post? - 2

    是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou

  9. ruby - ruby 中的 TOPLEVEL_BINDING 是什么? - 2

    它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput

  10. ruby - Infinity 和 NaN 的类型是什么? - 2

    我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串

随机推荐