c++ - 为什么编译器要为这个循环的每次迭代写入一个成员变量到内存中?

标签 c++ optimization g++ clang clang++

第一个版本通过将值从内存移动到局部变量来进行优化。第二个版本没有。

我原以为编译器可能会选择在这里进行 localValue 优化,而不是为循环的每次迭代从内存中读取和写入值。为什么不呢?

class Example
{
    public:
        void processSamples(float * x, int num) 
        {
            float localValue = v1;

            for (int i = 0; i < num; ++i)
            {
                x[i] = x[i] + localValue;
                localValue = 0.5 * x[i];
            }

            v1 = localValue;
        }

        void processSamples2(float * x, int num)
        {

            for (int i = 0; i < num; ++i)
            {
                x[i] = x[i] + v1;
                v1 = 0.5 * x[i];
            }

        }

    float v1;
};

processSamples 汇编成这样的代码:

.L4:
  addss xmm0, DWORD PTR [rax]
  movss DWORD PTR [rax], xmm0
  mulss xmm0, xmm1
  add rax, 4
  cmp rax, rcx
  jne .L4

processSamples2 对此:

.L5:
  movss xmm0, DWORD PTR [rax]
  addss xmm0, DWORD PTR example[rip]
  movss DWORD PTR [rax], xmm0
  mulss xmm0, xmm1
  movss DWORD PTR example[rip], xmm0
  add rax, 4
  cmp rax, rdx
  jne .L5

因为编译器不必担心线程(v1 不是原子的)。难道它不能假设没有其他东西会查看这个值并在循环旋转时继续将它保存在寄存器中吗?

参见 https://godbolt.org/g/RiF3B4用于完整的汇编和一系列可供选择的编译器!

最佳答案

因为aliasing : v1 是一个成员变量,可能是x 指向它。因此,对 x 元素的写入之一可能会更改 v1

在 C99 中,您可以在指针类型的函数参数上使用 restrict 关键字来通知编译器它不会为函数范围内的任何其他内容设置别名。一些 C++ 编译器也支持它,尽管它不是标准的。 (从我的一条评论中复制。)

关于c++ - 为什么编译器要为这个循环的每次迭代写入一个成员变量到内存中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46770638/

相关文章:

c# - 空间域卷积代码的性能

c++ - 共享库和 libpthread.so 的 g++ 问题

c++ - 使用c++11的std::thread,什么时候修改全局变量是线程安全的?

c++ - 解析包含多行条目的日志文件

.net - 密封类真的提供性能优势吗?

c++ - 在 ReSharper C++ 中完成 'XML Doc Comment'

python - 如何在两个字典中找到匹配值的字典键?

gcc - "gcc -x c"和 "gcc -x c++"汇编输出的区别

c++ - 如何在不同线程中使用 std::mutex?

c++ - 我的算法只将第一个字写入文件?