JCx*_*JCx 13 c++ optimization g++
尽管存在__restrict关键字,但将成员变量移动到局部变量会减少此循环中的写入次数.这是使用GCC -O3.Clang和MSVC在两种情况下都优化写入. [注意,由于这个问题已经发布,我们观察到将__restrict添加到调用函数会导致GCC也将商店移出循环.请参阅下面的godbolt链接和评论]
class X
{
public:
void process(float * __restrict d, int size)
{
for (int i = 0; i < size; ++i)
{
d[i] = v * c + d[i];
v = d[i];
}
}
void processFaster(float * __restrict d, int size)
{
float lv = v;
for (int i = 0; i < size; ++i)
{
d[i] = lv * c + d[i];
lv = d[i];
}
v = lv;
}
float c{0.0f};
float v{0.0f};
};
Run Code Online (Sandbox Code Playgroud)
使用gcc -O3,第一个内部循环看起来像:
.L3:
mulss xmm0, xmm1
add rdi, 4
addss xmm0, DWORD PTR [rdi-4]
movss DWORD PTR [rdi-4], xmm0
cmp rax, rdi
movss DWORD PTR x[rip+4], xmm0 ;<<< the extra store
jne .L3
.L1:
rep ret
Run Code Online (Sandbox Code Playgroud)
第二个在这里:
.L8:
mulss xmm0, xmm1
add rdi, 4
addss xmm0, DWORD PTR [rdi-4]
movss DWORD PTR [rdi-4], xmm0
cmp rdi, rax
jne .L8
.L7:
movss DWORD PTR x[rip+4], xmm0
ret
Run Code Online (Sandbox Code Playgroud)
有关完整代码,请参阅https://godbolt.org/g/a9nCP2.
为什么编译器不在这里执行lv优化?
我假设每个循环的3次内存访问比2更差(假设大小不是一个小数字),虽然我还没有测量过.
我做出这个假设是对的吗?
我认为两种情况下的可观察行为应该是相同的.
这似乎是由于函数__restrict上缺少限定符引起的f_original。 __restrict是 GCC 扩展;目前尚不清楚它在 C++ 中的表现如何。也许这是一个编译器错误(错过了优化),在内联后它似乎消失了。