为什么编译器会为此循环的每次迭代将成员变量写入内存
Why does the compiler write a member variable to memory for each iteration of this loop?
第一个版本通过将值从内存移动到局部变量来进行优化。 第二个版本没有。
我预计编译器无论如何都会选择在这里进行 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
过程样本2到这个:
.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!
由于别名:v1
是一个成员变量,可能是x
指向它。因此,对x
元素的写入之一可能会更改v1
。
在 C99 中,可以在指针类型的函数参数上使用 limit 关键字来通知编译器它不会为函数范围内的任何其他内容添加别名。一些C++编译器也支持它,尽管它不是标准的。 (摘自我的一条评论。
相关文章:
- "迭代器"和"const_iterator"不是 STL 容器的必需成员?
- 如何将迭代器调用转发给类的私有成员?
- 成员函数中的迭代器出现问题
- 迭代嵌套映射与范围为循环:没有名为"first"的成员
- 如何在C++中仅获取容器内类成员的迭代器
- 成员函数不能为集合迭代器和const_iterator的输入重载(但可以为其他 STL 迭代器重载)
- 有一个可迭代的容器,其中的成员在编译时是已知的
- 为什么向量的.at()成员函数返回引用而不是迭代器
- 将列表迭代器存储为成员
- 使用迭代器成员函数是否仅适用于某些向量类型"empty()"?
- C++ 向量::使用类对象迭代器擦除不擦除向量成员
- 树不维护递归迭代器成员
- 如何将迭代器变量声明为私有成员变量
- 我如何从循环内部使用迭代器的函数内部的getter中检索特定的成员
- C :我可以将成员变量的迭代器带入班级之一
- 通过向量中的对象的数据成员迭代
- 如何使用C STD :: SET中的迭代器访问成员功能
- C 模板功能在任何集合成员字段上迭代
- C++:将成员容器的迭代器接口转发到类接口
- 如何从 std 容器的迭代器为成员元素创建迭代器