如何使优化器正确地将变量放入寄存器中
How do I make the optimizer to properly put variables into registers?
>我有一个简单的函数,它通过引用接受两个变量:
void foo(int*& it2,
bit_reader<big_endian_tag>& reader2)
{
for(/* ... */)
{
*it2++ = boo(reader2.next());
// it2++ => 0x14001d890 add qword ptr [r12], 0x4
}
}
这里的问题是,对于it2
和reader2
优化器使计算机在循环期间写入内存而不是寄存器。
但是,以下代码在循环期间将变量正确放入寄存器中,但在循环之前和之后以不必要的副本的形式产生额外的开销:
void foo2(int*& it2,
bit_reader<big_endian_tag>& reader2)
{
auto reader = reader2;
auto it = it2;
for(/* ... */)
{
*it++ = boo(reader.next());
// it++ => 0x14001d890 add r15, 0x4
}
reader2 = reader;
it2 = it;
}
例如
如何使第一个示例生成与第二个示例相同的代码,但没有额外的副本?
问题是编译器无法证明it2
函数内没有变化。(嗯,它可以,但这远远超出了普通C++编译器的预期功能。
它如何知道boo(reader2.next());
不会更改值?考虑:
int* i = 0;
struct foo
{
int myInt;
int blah() { i = &myInt; return 5; }
};
void bar(int*& ptr, const foo& f)
{
*ptr = f.blah(); // changes value of ptr!
}
int otherInt;
i = &otherInt;
bar(i, foo());
这不会为otherInt
分配任何内容,而在转换后,它将:
void bar(int*& ptr, const foo& f)
{
int* ptrCopy = ptr;
*ptrCopy = f.blah(); // changes ptr, but not ptrCopy
}
因此,除非编译器能够证明行为相同,否则它无法进行优化。
C99 用 restrict
关键字解决了这个问题,但C++没有等效项。不过,大多数C++编译器中都存在扩展,例如 __restrict__
或 __restrict
.
要以标准C++执行此操作,您只需明确并自己制作副本
好吧,你不能。
通过非常量引用传递参数时,会要求编译器更新原始变量。因此,它必须将新值写入内存。
这一切都是为了优化"内存层次结构",直接在寄存器上完成计算是最快的,这就是为什么你真的想从内存中获取东西并将其复制到寄存器中,然后再计算任何内容,然后将结果复制回您需要的内存位置。通过直接在寄存器上计算所获得的性能通常会抵消在寄存器中加载和保存内存的成本。
你如何确保你把东西从内存中获取到寄存器中?例如
size_t size;
double* arr;
for (int i = 0; i < size - 1; ++i) {
double a = arr[i]; // copy to register
double b = arr[i + 1]; // copy to register
b = a*b + b; // make sure flop computation is done in registers
arr[i] = b; // copy back to memory
}
相关文章:
- 有没有办法强制C++编译器将变量存储在寄存器中?
- "变量":函数中函数作用域不允许初始化的自动或寄存器变量'naked'
- 是否可以在 GCC 中使用带有 C++17 的显式寄存器变量?
- 告诉编译器我希望变量始终存储在寄存器中的正确方法是什么
- 什么是有效的寄存器变量类型
- 物理寄存器和英特尔SIMD变量之间的关系
- 指向寄存器变量的指针
- 如何使优化器正确地将变量放入寄存器中
- 将EAX寄存器存储在变量中
- 如何从汇编寄存器中获取字符串并将其存储在C++中的变量中
- 是阻塞xmm/ymm寄存器的静态/静态本地SSE/AVX变量
- 为LLVM中的变量使用特定的寄存器
- 访问SSE寄存器变量
- C和C++中寄存器变量的地址
- GDB - 获取寄存器的变量名称
- 通过引用传递寄存器变量
- c++局部变量和寄存器
- 在c++中,成员变量(属性)可以驻留在寄存器中吗?
- 在C++中使用寄存器变量可以做多少坏事
- 为什么我可以取寄存器变量的地址