寄存器短缺:溢出与运行时的真相

Register deprivation: spills and runtime under forced register scarcity

寄存器短缺:溢出与运行时的真相

作者通过 gcc 强制预留寄存器,测试了九个内核在寄存器稀缺下的表现。实验发现,减少寄存器确实增加了溢出次数,但静态溢出计数与运行时间下降的相关性极弱。SipHash 内核在溢出增加 23 次的情况下,运行速度反而微升;而 FIR filter 每次溢出带来的性能损耗高达 2.2%。这表明溢出是否影响性能,关键在于它是否位于关键依赖路径上。此外,针对整数内核预留 XMM 寄存器的代价远低于预留 GP 寄存器,反之亦然。这项研究揭示了编译器优化中寄存器分配与性能之间复杂的非线性关系。

静态溢出计数与运行时间下降的相关性极弱,一次额外溢出的成本从 0% 到 2.2% 不等,差异高达 30 倍。
  1. nyrikki

    IMHO,这可能是因为超严格的调用约定或寄存器预算限制,导致编译器通常不得不写入显式的 MOV 指令或栈 PUSH/POP 指令来腾出空间。

    由于现代 CPU 拥有数百个隐藏的物理寄存器,CPU 的寄存器重命名(Register Renaming)单元会检测到这些强制的栈移动指令,意识到它们只是在复用相同的局部变量,于是依然将它们映射到隐藏的硬件寄存器上。CPU 本质上是在硬件寄存器层面执行这些“栈溢出”操作,使得编译器糟糕的寄存器限制几乎完全无害。

    尤其是 siphash 的结果让我觉得情况正是如此。

    不幸的是,我认为作为普通用户并没有办法观察到这一点。

  2. Scene_Cast2

    我想知道 CPU 的寄存器重映射对这些结果有多大影响。另外,他们是在一台古老的 CPU 上运行的,不过我不确定这是否重要。

  3. derdi

    如果不展示任何汇编代码,这简直毫无意义。siphash 的内层循环长什么样?它用到了多少 GPR?溢出(spills)发生在哪里?perf 对此有什么说法?

同日更多故事

2026-08-01