【问题标题】:Can I control register allocation in g++?我可以在 g++ 中控制寄存器分配吗?
【发布时间】:2009-02-11 01:07:43
【问题描述】:

我拥有高度优化的 C++ 部分,即使在远离热点的地方进行微小的更改也可能会影响高达 20% 的性能。经过更深入的调查,结果证明(可能)在热点中使用的寄存器略有不同。 我可以使用 always_inline 属性控制内联,但是我可以控制寄存器分配吗?

【问题讨论】:

  • 你会碰巧受限于 32 位 x86 吗?因为 64 位 x86 有更多的寄存器(我认为大约 16 个?)并且不应该有这样的问题......
  • 我尝试了64,但结果发现它更慢。我找不到原因。

标签: optimization gcc g++ inline cpu-registers


【解决方案1】:

如果你真的想搞乱寄存器分配,那么你可以强制 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 指出的那样,编译器不会强制使用寄存器来存储变量。只有在使用变量时才强制使用寄存器。例如。如果变量无法通过优化通过,则不会使用它。该寄存器也可以用于其他变量。

【讨论】:

  • 实际上,语法是“在与 test_integer 混淆时使用此寄存器”。它不强制 EBX 为 test_integer。相反,它强制 test_integer 为 EBX。 (至少从我从文档中收集到的内容。)我认为您应该在回答中更清楚地说明这一点。
  • 良好的链接。内联 asm 不是一种选择。热点太大了。
  • Lukasz,如果你不想使用内联汇编器,你也可以取一个性能良好的编译目标代码,反汇编它并使用生成的 asm 代码。
  • 我完全喜欢你说的方式,使用内联汇编器。每次我们想做一些非常棒的事情时,我们都必须在文明中退后一步,嗯? :P
【解决方案2】:

一般来说,所有现代编译器都会忽略 register 关键字。唯一的例外是(相对)最近添加的错误,如果您尝试获取已用 register 关键字标记的变量的地址。

我也经历过这种痛苦,最终找到解决它的唯一真正方法是查看输出程序集以尝试确定导致 gcc 加深的原因。您还可以做其他事情,但这取决于您的代码正在尝试做什么。我在一个非常大的函数中工作,其中包含大量计算的 goto 混乱,其中微小的(看似无害的)变化可能会导致灾难性的性能损失。如果你正在做类似的事情,你可以做一些事情来尝试缓解这个问题,但细节有点恶心,所以我会放弃在这里讨论它们,除非它真的相关。

【讨论】:

  • afaik goto 会严重影响编译器的优化能力,这可能会导致有趣的输出。
  • 是的,但是对于解释器来说,计算的 goto 是非常有用的,因为你正在有效地编写一系列 goto(标准解释器是 while(1) switch(...){pile of code},或者statementNode->execute(..)(其中 execute 是一个虚函数)。
  • @Calyth:常规 goto 不会损害优化——编译器必须对中断/继续和内联函数中的返回语句执行基本相同的操作。另一方面,计算 goto 会降低流水线 CPU 上的优化机会和执行速度。
  • 实际上,常规 goto 可能会损害优化,因为它们以一种不一定对优化器友好的方式干扰更高级别的行为(但琐碎的 goto 可以很容易地在内部转换为更容易优化的替代方案)。
  • 另外,对于流水线 CPU,计算的 goto 不一定更慢或更差。这完全取决于用例。在我上面提到的情况下(解释器),由于与分支预测器的更好交互,计算 goto 对于管道来说比替代方案要好得多。
【解决方案3】:

这取决于您使用的处理器。或者我应该说,是的,您可以使用 register 关键字,但除非您使用没有管道和单核的简单处理器,否则这是不受欢迎的。如今,GCC 在寄存器分配方面可以做得比您做得更好。相信它。

【讨论】:

  • 他的结果表明在这种情况下它是不可信的。他在不同的构建中获得了 20% 的性能波动!
猜你喜欢
  • 1970-01-01
  • 2011-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多