c – 为什么缓存行仅适用于simdization?
发布时间:2020-12-16 07:06:13 所属栏目:百科 来源:网络整理
导读:我正在学习simd指令和内存缓存. 我已经编写了一个简单的测试来比较标量和SIMDized sqrt计算: #include time.h#include iostreamusing namespace std;#include cmath#include "xmmintrin.h"#include stdlib.hconst int N = 16;const int NIter = 10000;float
我正在学习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个字节正好是一个缓存行.因此,矩阵中的一行安装在高速缓存行中,对于SIMDized循环,我得到1000倍的加速因子,并且标量循环没有加速到N = 1.(N = 1的标量循环执行大约16 * 16 = N = 16时快256倍,这是没有高速缓存行的预期. 这怎么可能? 如果它有助于我生成N = 16的asm代码. 标量程序: #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; } 给下一个asm代码: .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 jp L40 L5: movss %xmm0,4(%rbp) sqrtss 8(%rbx),%xmm0 jp L41 L7: movss %xmm0,8(%rbp) sqrtss 12(%rbx),%xmm0 jp L42 L9: movss %xmm0,12(%rbp) sqrtss 16(%rbx),%xmm0 jp L43 L11: movss %xmm0,16(%rbp) sqrtss 20(%rbx),%xmm0 jp L44 L13: movss %xmm0,20(%rbp) sqrtss 24(%rbx),%xmm0 jp L45 L15: movss %xmm0,24(%rbp) sqrtss 28(%rbx),%xmm0 jp L46 L17: movss %xmm0,28(%rbp) sqrtss 32(%rbx),%xmm0 jp L47 L19: movss %xmm0,32(%rbp) sqrtss 36(%rbx),%xmm0 jp L48 L21: movss %xmm0,36(%rbp) sqrtss 40(%rbx),%xmm0 jp L49 L23: movss %xmm0,40(%rbp) sqrtss 44(%rbx),%xmm0 jp L50 L25: movss %xmm0,44(%rbp) sqrtss 48(%rbx),%xmm0 jp L51 L27: movss %xmm0,48(%rbp) sqrtss 52(%rbx),%xmm0 jp L52 L29: movss %xmm0,52(%rbp) sqrtss 56(%rbx),%xmm0 jp L53 L31: movss %xmm0,56(%rbp) sqrtss 60(%rbx),%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),3 jmp L15 L44: movss 20(%rbx),3 jmp L13 L43: movss 16(%rbx),3 jmp L11 L42: movss 12(%rbx),3 jmp L9 L41: movss 8(%rbx),3 jmp L7 L40: movss 4(%rbx),3 jmp L5 L39: movss (%rbx),4 jmp L3 L50: movss 44(%rbx),3 jmp L25 L49: movss 40(%rbx),3 jmp L23 L48: movss 36(%rbx),3 jmp L21 L47: movss 32(%rbx),3 jmp L19 L52: movss 52(%rbx),3 jmp L29 L51: movss 48(%rbx),3 jmp L27 L53: movss 56(%rbx),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,_b,4 .globl _a .zerofill __DATA,_a,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 " .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; } 给下一个asm代码: .section __TEXT,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),472(%rsp) sqrtps 400+_a(%rip),456(%rsp) sqrtps 416+_a(%rip),440(%rsp) sqrtps 432+_a(%rip),424(%rsp) sqrtps 448+_a(%rip),408(%rsp) sqrtps 464+_a(%rip),392(%rsp) sqrtps 480+_a(%rip),376(%rsp) sqrtps 496+_a(%rip),360(%rsp) sqrtps 512+_a(%rip),344(%rsp) sqrtps 528+_a(%rip),328(%rsp) sqrtps 544+_a(%rip),312(%rsp) sqrtps 560+_a(%rip),296(%rsp) sqrtps 576+_a(%rip),280(%rsp) sqrtps 592+_a(%rip),264(%rsp) sqrtps 608+_a(%rip),248(%rsp) sqrtps 624+_a(%rip),232(%rsp) sqrtps 640+_a(%rip),216(%rsp) sqrtps 656+_a(%rip),200(%rsp) sqrtps 672+_a(%rip),184(%rsp) sqrtps 688+_a(%rip),168(%rsp) sqrtps 704+_a(%rip),152(%rsp) sqrtps 720+_a(%rip),136(%rsp) sqrtps 736+_a(%rip),120(%rsp) sqrtps 752+_a(%rip),104(%rsp) sqrtps 768+_a(%rip),88(%rsp) sqrtps 784+_a(%rip),72(%rsp) sqrtps 800+_a(%rip),56(%rsp) sqrtps 816+_a(%rip),40(%rsp) sqrtps 832+_a(%rip),24(%rsp) sqrtps 848+_a(%rip),8(%rsp) sqrtps 864+_a(%rip),-8(%rsp) sqrtps 880+_a(%rip),-24(%rsp) sqrtps 896+_a(%rip),-40(%rsp) sqrtps 912+_a(%rip),-56(%rsp) sqrtps 928+_a(%rip),-72(%rsp) sqrtps 944+_a(%rip),-88(%rsp) sqrtps 960+_a(%rip),-104(%rsp) sqrtps 976+_a(%rip),616(%rsp) sqrtps 992+_a(%rip),632(%rsp) sqrtps 1008+_a(%rip),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),400+_b_simd(%rip) movaps 440(%rsp),416+_b_simd(%rip) movaps 424(%rsp),432+_b_simd(%rip) movaps 408(%rsp),448+_b_simd(%rip) movaps 392(%rsp),464+_b_simd(%rip) movaps 376(%rsp),480+_b_simd(%rip) movaps 360(%rsp),496+_b_simd(%rip) movaps 344(%rsp),512+_b_simd(%rip) movaps 328(%rsp),528+_b_simd(%rip) movaps 312(%rsp),544+_b_simd(%rip) movaps 296(%rsp),560+_b_simd(%rip) movaps 280(%rsp),576+_b_simd(%rip) movaps 264(%rsp),592+_b_simd(%rip) movaps 248(%rsp),608+_b_simd(%rip) movaps 232(%rsp),624+_b_simd(%rip) movaps 216(%rsp),640+_b_simd(%rip) movaps 200(%rsp),656+_b_simd(%rip) movaps 184(%rsp),672+_b_simd(%rip) movaps 168(%rsp),688+_b_simd(%rip) movaps 152(%rsp),704+_b_simd(%rip) movaps 136(%rsp),720+_b_simd(%rip) movaps 120(%rsp),736+_b_simd(%rip) movaps 104(%rsp),752+_b_simd(%rip) movaps 88(%rsp),768+_b_simd(%rip) movaps 72(%rsp),784+_b_simd(%rip) movaps 56(%rsp),800+_b_simd(%rip) movaps 40(%rsp),816+_b_simd(%rip) movaps 24(%rsp),832+_b_simd(%rip) movaps 8(%rsp),848+_b_simd(%rip) movaps -8(%rsp),864+_b_simd(%rip) movaps -24(%rsp),880+_b_simd(%rip) movaps -40(%rsp),896+_b_simd(%rip) movaps -56(%rsp),912+_b_simd(%rip) movaps -72(%rsp),928+_b_simd(%rip) movaps -88(%rsp),944+_b_simd(%rip) movaps -104(%rsp),960+_b_simd(%rip) movaps 616(%rsp),976+_b_simd(%rip) movaps 632(%rsp),992+_b_simd(%rip) movaps 648(%rsp),1008+_b_simd(%rip) addq $672,%rsp LCFI1: ret LFE1625: .align 4 __GLOBAL__sub_I_test.cpp: LFB1627: leaq __ZStL8__ioinit(%rip),%rsp LCFI2: call __ZNSt8ios_base4InitC1Ev movq ___dso_handle@GOTPCREL(%rip),%rsp LCFI3: jmp ___cxa_atexit LFE1627: .mod_init_func .align 3 .quad __GLOBAL__sub_I_test.cpp .globl _b_simd .zerofill __DATA,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 解决方法
您是否检查过您的编译器实际上是为标量平方根发出单个汇编指令,而不是调用库函数?这可以解释很多差异,没有引用内存访问行为.
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |