You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

为何无符号整数A除以<constant-int>比有符号整数更快?

为什么无符号整数除以常量的运算速度比有符号整数更快?

这个问题问到点子上了!本质原因是CPU对有符号和无符号整数除法的硬件实现逻辑差异,尤其是有符号数需要处理负数的特殊情况,带来了额外的运算开销。下面分几个核心点解释:

1. 舍入规则的额外修正开销

C规定有符号整数除法要遵循向零舍入的规则(比如-5 / 2结果是-2),但大多数CPU的硬件除法指令(比如x86的IDIV)默认是向负无穷舍入-5 / 2会得到-3)。这就导致编译器必须在生成的代码中额外添加指令,把硬件计算的结果修正为符合C标准的向零舍入值——比如判断结果是否为负,如果是,就加上除数来调整。这些额外的判断和运算步骤,直接拖慢了有符号除法的速度。

而无符号整数除法不存在这个问题:因为结果永远是非负的,硬件指令(比如x86的DIV)的自然向下舍入完全符合C++的规则,不需要任何修正。

2. 符号位的额外处理步骤

有符号整数的除法需要额外处理符号:

  • 首先要判断被除数和除数的符号是否相同,来决定结果的符号;
  • 然后计算两个数绝对值的除法;
  • 最后给结果加上正确的符号。

这一系列操作需要用到异或(判断符号是否相同)、条件跳转或条件移动指令,而无符号整数没有符号位的顾虑,直接进行除法运算即可,省去了这些额外步骤。

3. 2的幂次除法的极致差异

当除数是2的幂时,这种速度差异会被放大到最明显:

  • 无符号除法可以直接用逻辑右移>>)指令完成,这是CPU的单周期指令,速度极快;
  • 有符号除法如果是2的幂,比如-5 / 2,直接用算术右移会得到-3(不符合向零舍入的要求),所以编译器必须生成额外代码:先判断被除数是否为负,如果是,就先给被除数加上除数-1再右移。这多出来的条件判断和加法操作,和无符号的单步右移比起来,速度差距非常显著。

举个实际的例子:在x86平台上,无符号常量除法可能只需要1-2条指令,而有符号版本可能需要4-5条甚至更多,其中还包含条件分支——分支预测失败的话还会带来额外的性能损耗。

内容的提问来源于stack exchange,提问作者bergercookie

火山引擎 最新活动