为啥缓存行仅适用于 simdization?

Posted

技术标签:

【中文标题】为啥缓存行仅适用于 simdization?【英文标题】:Why cache line works for simdization only?为什么缓存行仅适用于 simdization? 【发布时间】:2013-10-21 13:28:10 【问题描述】:

我正在学习 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 个浮点数 = 64 个字节正好是一个高速缓存行。因此,a 矩阵的一行适合缓存行,SIMDized 循环的速度提高了 1000 倍,而标量循环没有加速到 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

【问题讨论】:

0.000264 这样的测量似乎很容易受到噪音的影响:例如,我的平台无法可靠地测量小于 1/18 秒的时间。也许您应该增加迭代次数以获得更可靠的测量结果。 N=1 的 SIMD 代码测量值无效:代码假定 N 可以被 4 整除。 anatolyg, 1. 0.2 ms 非噪声,精度为 1 mus,重复测量检查统计误差。但这与我的问题无关——关键是 N=16 的 Time SIMD 非常小。 2.我没有说N=1的Time SIMD有效。 【参考方案1】:

您是否检查过您的编译器实际上是为标量平方根发出一条汇编指令,而不是调用库函数?这可以解释大部分差异,而无需提及内存访问行为。

【讨论】:

如何查看?我在 asm 代码中看到使用了“sqrtss”指令,这是否证明了你的问题?

以上是关于为啥缓存行仅适用于 simdization?的主要内容,如果未能解决你的问题,请参考以下文章

适用于不同类型资源的理想 HTTP 缓存控制标头

PHP 适用于可变从属页面的简易Kohana缓存

为啥启用 NEON SIMDization 时 Android 会崩溃?信号 11 (SIGSEGV),代码 1 (SEGV_MAPERR)

apache_conf .htaccess文件适用于Vanish缓存

记离线缓存(manifest)一大坑,断定其只适用于静态网站或离线应用

记离线缓存(manifest)一大坑,断定其只适用于静态网站或离线应用