我正在编写一些使用c++进行数值计算的代码。我需要非常仔细地编写代码,以帮助编译器生成良好的指令。然后,对于带有-O3标志的g++ 9.2,我发现一些奇怪的事情。我不是汇编专家,所以我需要有人帮助我或指出我做错了什么。

完整代码可在https://godbolt.org/z/fyuYtq中找到。我将关键代码段复制并粘贴到此处

void sum_twopointer(Elem *p1, Elem *p2, ptrdiff_t stride, ptrdiff_t start, ptrdiff_t end) {

    Elem sm = 0;
    for(auto i = start;i != end; ++i) {
        p1[0] = p2[0] + p2[0];
        p1 += stride;
        p2 += stride;
    }

}

它使用g++ -O3编译。 g++的版本是9.2。汇编代码是
sum_twopointer(double*, double*, long, long, long):
  cmp rcx, r8
  je .L32
  lea r9, [0+rdx*8]
  xor eax, eax
  cmp rdx, 1
  jne .L36
.L34:
  movsd xmm0, QWORD PTR [rsi+rax]
  add rcx, 1
  addsd xmm0, xmm0
  movsd QWORD PTR [rdi+rax], xmm0
  add rax, r9
  cmp r8, rcx
  jne .L34
.L32:
  ret
.L36:
  movsd xmm0, QWORD PTR [rsi+rax]
  add rcx, 1
  addsd xmm0, xmm0
  movsd QWORD PTR [rdi+rax], xmm0
  add rax, r9
  cmp r8, rcx
  jne .L36
  ret

据我了解,编译器正在尝试对跨步仅为1的特殊情况进行一些优化,以便为跨步== 1的情况创建一个新分支,但是它不会做任何进一步的事情。请注意,.L34之后的代码与.L36 之后的代码完全相同。

我为此做了一些基准测试。下面列出了stride = 1和stride = 2的性能。代码在那里https://gist.github.com/lhprojects/dac3a9fcf15bd5b1ec365ba6a87c679d
g++ -O2
---------------------------------------------------------------
Benchmark                     Time             CPU   Iterations
---------------------------------------------------------------
BM_twopointer/8192/1       3743 ns         3742 ns       185062      stride=1
BM_twopointer/8192/2       1980 ns         1980 ns       328523      stride=2

g++ -O3
---------------------------------------------------------------
Benchmark                     Time             CPU   Iterations
---------------------------------------------------------------
BM_twopointer/8192/1       5006 ns         5001 ns       120725      stride=1
BM_twopointer/8192/2       2043 ns         2041 ns       333914      stride=2

无论如何,对于stride = 1,与-O2相比,-O3的性能会变差。我想知道我的代码发生了什么。我是否在c++中触发了一些未定义的行为?或者简单地说,g++中的代码优化存在缺陷。 (对不起,如果我的英语写作让您感到非常困惑。)

最佳答案

我相信编译器需要知道p1和p2不会重叠...将它们声明为__restrict指针应该允许编译器实际使用simd指令。对我来说,这会为stride == 1创建一个特例似乎很奇怪,但是对于这些知识却什么也没做。

关于c++ - g++ -O3为循环创建奇怪的指令,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59486612/

10-10 13:39