加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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代码.
我不知道汇编程序,我在这里可以看到循环看起来在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;
}

给下一个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

解决方法

您是否检查过您的编译器实际上是为标量平方根发出单个汇编指令,而不是调用库函数?这可以解释很多差异,没有引用内存访问行为.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读