我对 C++ 进行了高度优化,即使在远离热点的地方进行微小的更改,也可以将性能提高 20%。经过更深入的调查,结果证明(可能)在热点中使用的寄存器略有不同。我可以使用 always_inline 属性控制内联,但我可以控制寄存器分配吗?
3 回答
如果您真的想弄乱寄存器分配,那么您可以强制 GCC 在某些寄存器中分配局部和全局变量。
您可以使用如下的特殊变量声明来执行此操作:
register int test_integer asm ("EBX");
也适用于其他架构,只需将 EBX 替换为目标特定的寄存器名称。
有关这方面的更多信息,我建议您查看 gcc 文档:
http://gcc.gnu.org/onlinedocs/gcc-4.3.3/gcc/Local-Reg-Vars.html
然而,我的建议是不要弄乱寄存器分配,除非你有很好的理由。如果您自己分配一些寄存器,则分配器可以使用的寄存器较少,您最终可能会得到一个比您开始使用的代码更糟糕的代码。
如果您的函数对性能至关重要,您可以在编译之间获得 20% 的性能差异,那么在 inline-assembler 中编写该东西可能是个好主意。
编辑:正如 strager 指出的那样,编译器不会被迫将寄存器用于变量。只有在使用变量时才强制使用寄存器。例如,如果变量无法通过优化通过,则不会使用它。该寄存器也可以用于其他变量。
一般来说,所有现代编译器都会忽略 register 关键字。唯一的例外是(相对)最近添加的错误,如果您尝试获取已用 register 关键字标记的变量的地址。
我也经历过这种痛苦,最终找到解决它的唯一真正方法是查看输出程序集以尝试确定导致 gcc 加深的原因。您还可以做其他事情,但这取决于您的代码正在尝试做什么。我在一个非常大的函数中工作,其中包含大量计算的 goto 混乱,其中微小的(看似无害的)变化可能会导致灾难性的性能损失。如果你正在做类似的事情,你可以做一些事情来尝试缓解这个问题,但是细节有点恶心,所以我会放弃在这里讨论它们,除非它真的相关。
这取决于您使用的处理器。或者我应该说,是的,您可以使用 register 关键字,但除非您使用没有管道和单核的简单处理器,否则这是不受欢迎的。如今,GCC 在寄存器分配方面可以做得比您做得更好。相信它。