2

我有一个像这样的内部循环

for(i=0 ;i<n;i++){
 x[0] += A[i] * z[0];
 x[1] += A[i] * z[1];
 x[2] += A[i] * z[2];
 x[3] += A[i] * z[3];
}

编译器可以轻松地将内部 4 条指令转换为 SSE 指令。当前的编译器会这样做吗?如果他们做了我必须做些什么来强制编译器这样做?

4

2 回答 2

4

根据您提供的内容,这无法向量化,因为指针可能会相互别名,即数组可能与orx重叠。Az

帮助编译器的一种简单方法是声明x__restrict. 另一种方法是像这样重写它:

for(i=0 ;i<n;i++)
{
 float Ai=A[i];
 float z0=z[0], z1=z[1], z2=z[2], z3=z[3];
 x[0] += Ai * z0;
 x[1] += Ai * z1;
 x[2] += Ai * z2;
 x[3] += Ai * z3;
}

我从来没有真正尝试过让编译器自动矢量化代码,所以我不知道这是否会做到。即使它没有被矢量化,它也应该更快,因为加载和存储可以更有效地排序并且不会导致加载命中存储。

如果您有比编译器更多的信息(例如,您的指针是否是 16 字节对齐的),并且应该能够利用它来发挥您的优势(例如使用对齐的负载)。请注意,我并不是说您应该始终尝试击败编译器,只有当您知道的比它多时。

进一步阅读:

于 2011-07-06T05:16:26.003 回答
0

默认情况下,ICC 为 SSE2 自动矢量化以下代码片段:

void foo(float *__restrict__ x, float *__restrict__ A, float *__restrict__ z, int n){
for(int i=0;i<n;i++){
 x[0] += A[i] * z[0];
 x[1] += A[i] * z[1];
 x[2] += A[i] * z[2];
 x[3] += A[i] * z[3];
}
return;
}

通过使用restrict关键字,内存别名假设被忽略。生成的矢量化报告为:

$ icpc test.cc -c -vec-report2 -S
test.cc(2): (col. 1) remark: PERMUTED LOOP WAS VECTORIZED
test.cc(3): (col. 2) remark: loop was not vectorized: not inner loop

要确认是否生成了SSE指令,打开ASM生成的(test.s),你会发现如下指令:

..B1.13:                        # Preds ..B1.13 ..B1.12
        movaps    (%rsi,%r15,4), %xmm10                         #3.10
        movaps    16(%rsi,%r15,4), %xmm11                       #3.10
        mulps     %xmm0, %xmm10                                 #3.17
        mulps     %xmm0, %xmm11                                 #3.17
        addps     %xmm10, %xmm9                                 #3.2
        addps     %xmm11, %xmm6                                 #3.2
        movaps    32(%rsi,%r15,4), %xmm12                       #3.10
        movaps    48(%rsi,%r15,4), %xmm13                       #3.10
        movaps    64(%rsi,%r15,4), %xmm14                       #3.10
        movaps    80(%rsi,%r15,4), %xmm15                       #3.10
        movaps    96(%rsi,%r15,4), %xmm10                       #3.10
        movaps    112(%rsi,%r15,4), %xmm11                      #3.10
        addq      $32, %r15                                     #2.1
        mulps     %xmm0, %xmm12                                 #3.17
        cmpq      %r13, %r15                                    #2.1
        mulps     %xmm0, %xmm13                                 #3.17
        mulps     %xmm0, %xmm14                                 #3.17
        addps     %xmm12, %xmm5                                 #3.2
        mulps     %xmm0, %xmm15                                 #3.17
        addps     %xmm13, %xmm4                                 #3.2
        mulps     %xmm0, %xmm10                                 #3.17
        addps     %xmm14, %xmm7                                 #3.2
        mulps     %xmm0, %xmm11                                 #3.17
        addps     %xmm15, %xmm3                                 #3.2
        addps     %xmm10, %xmm2                                 #3.2
        addps     %xmm11, %xmm1                                 #3.2
        jb        ..B1.13       # Prob 75%                      #2.1
                                # LOE rax rdx rsi r8 r9 r10 r13 r15 ecx ebp edi r11d r14d bl xmm0 xmm1 xmm2 xmm3 xmm4 xmm5 xmm6 xmm7 xmm8 xmm9
..B1.14:                        # Preds ..B1.13
        addps     %xmm6, %xmm9                                  #3.2
        addps     %xmm4, %xmm5                                  #3.2
        addps     %xmm3, %xmm7                                  #3.2
        addps     %xmm1, %xmm2                                  #3.2
        addps     %xmm5, %xmm9                                  #3.2
        addps     %xmm2, %xmm7                                  #3.2
        lea       1(%r14), %r12d                                #2.1
        cmpl      %r12d, %ecx                                   #2.1
        addps     %xmm7, %xmm9                                  #3.2
        jb        ..B1.25       # Prob 50%                      #2.1
于 2014-05-07T17:18:54.380 回答