循环排序和-ftree-vectorize

时间:2018-03-09 12:28:29

标签: c loops vectorization

我有四个嵌套for循环,如下所示:

const size_t nMax = 300 ; double acc = 0 ;

for( size_t i=0 ; i<nMax ; i++ ) {
   for( size_t j=0 ; j<nMax ; j++ ) {
      for( size_t k=0 ; k<nMax ; k++ ) {
         for( size_t l=k ; l<nMax ; l++ ) {
            acc += 1.0 ;
         }
      }
   }
}
printf( "Accumulator is %f\n", acc ) ;

使用gcc(版本5.4.0)和-O3进行编译,代码在5.188秒内完成。现在,如果我重新排序循环

const size_t nMax = 300 ; double acc = 0 ;

for( size_t k=0 ; k<nMax ; k++ ) {
   for( size_t l=k ; l<nMax ; l++ ) {
      for( size_t i=0 ; i<nMax ; i++ ) {
         for( size_t j=0 ; j<nMax ; j++ ) {
            acc += 1.0 ;
         }
      }
   }
}
printf( "Accumulator is %f\n", acc ) ;

再次使用-O3进行编译,代码运行时间为3.500秒。我不确定为什么会这样:我在第二个代码段得到它,l上的循环检查外部循环的值,开始条件nMax * nMax次的频率低于第一个代码段,但似乎不太可能(?)这会产生如此显着的性能损失。

使用-O2进行编译会使两个代码在相同的时间内执行(大约5.2秒),因此我设法追踪-ftree-vectorize作为可与{{1}一起使用的标记恢复性能差异。

为什么-O2可以优化第二个代码段而不是第一个?

修改

使用-ftree-vectorize添加了代码的汇编版本。我对汇编程序一无所知,所以不能真正声称理解很多。这是第一个(慢)段:

gcc -O2 -ftree-vectorize

和第二个(快速)版本:

    .file   "code_one.c"
    .section    .rodata.str1.1,"aMS",@progbits,1
.LC2:
    .string "Accumulator is %f\n"
    .section    .text.unlikely,"ax",@progbits
.LCOLDB3:
    .section    .text.startup,"ax",@progbits
.LHOTB3:
    .p2align 4,,15
    .globl  main
    .type   main, @function
main:
.LFB38:
    .cfi_startproc
    pxor    %xmm0, %xmm0
    xorl    %ecx, %ecx
    movapd  .LC1(%rip), %xmm1
.L2:
    movq    %rcx, %rsi
.L8:
    movhpd  .LC0(%rip), %xmm0
    xorl    %edx, %edx
    .p2align 4,,10
    .p2align 3
.L6:
    movl    $300, %eax
    .p2align 4,,10
    .p2align 3
.L3:
    subq    $1, %rax
    addpd   %xmm1, %xmm0
    jne .L3
    addl    $1, %edx
    cmpl    $150, %edx
    jne .L6
    movdqa  %xmm0, %xmm2
    addq    $1, %rsi
    cmpq    $300, %rsi
    psrldq  $8, %xmm2
    addpd   %xmm2, %xmm0
    jne .L8
    addq    $1, %rcx
    cmpq    $300, %rcx
    jne .L2
    subq    $8, %rsp
    .cfi_def_cfa_offset 16
    movl    $.LC2, %esi
    movl    $1, %edi
    movl    $1, %eax
    call    __printf_chk
    xorl    %eax, %eax
    addq    $8, %rsp
    .cfi_def_cfa_offset 8
    ret
    .cfi_endproc
.LFE38:
    .size   main, .-main
    .section    .text.unlikely
.LCOLDE3:
    .section    .text.startup
.LHOTE3:
    .section    .rodata.cst8,"aM",@progbits,8
    .align 8
.LC0:
    .long   0
    .long   0
    .section    .rodata.cst16,"aM",@progbits,16
    .align 16
.LC1:
    .long   0
    .long   1072693248
    .long   0
    .long   1072693248
    .ident  "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609"
    .section    .note.GNU-stack,"",@progbits

0 个答案:

没有答案