【问题标题】:Is a (common) CPU faster at computing low values than great ones? [duplicate](普通)CPU 在计算低值时是否比高值更快? [复制]
【发布时间】:2018-03-27 16:29:17
【问题描述】:

问题就这么简单: 将两个低值与一个常见的基本运算(如加法、除法、模数、位移位等)组合起来会比相同的值更大的运算更快吗?

据我所知,这需要 CPU 跟踪最重要的位(我认为这不太可能),但业务中可能还有其他问题。

我之所以特别问,是因为我经常看到一些 Java 的基本类的 hashCode() 方法(例如 StringList)中使用了相当低的质数(例如 31),这令人惊讶,因为更大的值会很可能会导致更多的传播(这对于散列函数来说通常是一件好事)。

【问题讨论】:

  • AFAIK 处理器不关心某个变量类型中的值,在 Java 的哈希码中使用 31 背后的原因在提议的欺骗中得到了很好的解释。
  • 对于除法和取模(实际除法和取模,左操作数不变,它们不算数),实际上是的,也许,这取决于。它们是值很重要的极少数操作中的两个。
  • 这不是重复的,因为我只是引用 hashCode() 函数。我以前知道这篇文章,并且很清楚那里指出的某些相关情况。但是,我的实际问题,CPU 是否可以更快地处理低值,当然没有在那里回答,这使我自己的问题合法化。
  • 也可以:x * 31 非常有效地计算为x << 5 - x。但是,x * 65,53765,537 作为第 4 个fermat number 是素数)的计算速度与x << 16 + x 一样快,据我所知,这会导致更好的扩散。
  • 65,537 等较大数字的问题是需要大于 16 位的可变大小。 Java 可以针对包括 16 位架构的嵌入式处理器。所以目标架构字长也可能是一个考虑因素。

标签: java performance cpu computation


【解决方案1】:

算术

我不认为有很多流水线处理器(即除了最小的几乎所有处理器),简单的算术指令的成本会随着寄存器或内存操作数的值而变化。这将使管道的设计更加复杂,并且在实践中可能适得其反。

我可以想象一个非常复杂的指令(至少是一个除法)与流水线长度相比可能需要很多周期,因为它可能会引入等待状态。 Agner Fog 写道,“在 AMD 处理器上是正确的,但在 Intel 处理器上则不然。”

如果一个操作不能在一条指令中计算,例如大于本机整数宽度的数字相乘,则实现很可能包含一个“快速路径”,例如两个操作数的上半部分为零。一个常见的例子是 MSVC 使用的 x86 32 位架构上的 64 位乘法。一些较小的处理器没有除法指令,有时甚至没有乘法指令。对于较小的操作数,用于计算这些操作的程序集可能会更早终止。这种影响在较小的架构上会更明显。

立即值编码

对于立即数(常量),这可能会有所不同。例如,有 RISC 处理器允许在 load/add-immediate 指令中最多编码 16 位立即数,并且需要两个操作来通过 load-upper-immediate + add-immediate 加载 32 位字,或者必须加载常量从程序内存中。

在 CISC 处理器中,较大的立即数可能会占用更多内存,这可能会减少每个周期可获取的指令数量,或增加缓存未命中的数量。

在这种情况下,较小的常数可能比较大的常数便宜。

我不确定编码差异对 Java 是否同样重要,因为大多数代码至少最初将作为 Java 字节码分发,尽管启用 JIT 的 JVM 会将代码转换为机器代码,并且某些库类可能已经预编译实施。我对 Java 字节码的了解还不够,无法确定常量大小对它的影响。根据我的阅读,在我看来,大多数常量通常是通过常量池中的索引加载的,而不是直接编码在字节码流中,所以我认为这里不会有很大的差异,如果有的话。

强度降低优化

对于非常昂贵的操作(相对于处理器而言),编译器和程序员经常使用技巧将硬计算替换为对常数有效的更简单的计算,例如在提到的乘法示例中,乘法被移位替换并且减法/加法。

在给出的示例中(乘以 31 与乘以 65,537),我预计不会有差异。对于其他数字会有差异,但它不会与数字的大小完全相关。常数除法通常也被神秘的乘法和移位序列所取代。

例如查看 gcc 如何翻译division by 13

在 x86 处理器上,一些小常数乘法可以用load-effective-address 指令代替,但仅限于某些常数。

总而言之,我希望这种效果在很大程度上取决于处理器架构和要执行的操作。由于 Java 应该几乎可以在任何地方运行,我认为库作者希望他们的代码能够在包括小型嵌入式处理器在内的各种处理器上高效运行,其中操作数大小将发挥更大的作用。

【讨论】:

    猜你喜欢
    • 2018-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-11
    • 2011-06-14
    • 2014-08-08
    • 2014-01-07
    • 1970-01-01
    相关资源
    最近更新 更多