【问题标题】:What's more costly on current CPUs: arithmetic operations or conditionals?当前 CPU 的成本更高:算术运算还是条件?
【发布时间】:2013-01-25 05:37:20
【问题描述】:

20-30 年前,除法等算术运算是 CPU 成本最高的运算之一。在一段重复调用的代码中保存一个部门是显着的性能提升。但是今天的 CPU 具有快速的算术运算,并且由于它们大量使用instruction pipelining,因此条件可能会破坏高效执行。如果我想优化代码以提高速度,我应该更喜欢算术运算而不是条件吗?

示例 1

假设我们要实现以 n 为模的运算。什么会更好:

int c = a + b;
result = (c >= n) ? (c - n) : c;

result = (a + b) % n;

?

示例 2

假设我们将 24 位有符号数字转换为 32 位。什么会更好:

int32_t x = ...;
result = (x & 0x800000) ? (x | 0xff000000) : x;

result = (x << 8) >> 8;

?

【问题讨论】:

  • 致“让编译器处理它”的人群:我挑战你找到一个编译器,它会为给定 int a = rand() % n, b = rand() % n; 的示例 #1 生成相同的代码

标签: performance cpu conditional-statements arithmetic-expressions


【解决方案1】:

编译器的作者和构建硬件的人已经挑选并腌制了所有低调的果实。如果你是那种需要问这种问题的人,你不可能手动优化任何东西。

虽然在 20 年前,相对称职的程序员可以通过下降到汇编来进行一些优化,但现在它是专家的领域,专门研究目标架构;此外,优化不仅需要了解程序,还需要了解它将处理的数据。一切都归结为启发式、不同条件下的测试等。

简单的性能问题不再有简单的答案。

【讨论】:

  • 他不是在这里写汇编。
  • @BenVoigt:但我的回答仍然成立。
  • 仅适用于真正底层的东西。用较低复杂度替换算法仍然是一个非常理想的优化,编译器还不能为你做。条件有效的优化是程序员必须参与的另一个难点,无论是手动优化还是手动标记前置条件。
  • @BenVoigt:是的,你是对的,但是 - 鉴于问题 - 要点是无关紧要的。问题的答案是:“无法判断,不知道确切的 cpu,结果将用于代码、编译器、月相等的方式”。即使是最简单的吊装也会改变结果。
【解决方案2】:

如果你想优化速度,你应该告诉你的编译器优化速度。现代编译器通常会在这方面胜过您。

出于这个原因,我有时会惊讶地将汇编代码与原始源代码关联起来。

针对可读性优化您的源代码,并让编译器做它最擅长的事情。

【讨论】:

  • 只有当你没有编译器没有的信息时。许多优化仅对有限范围的输入有效。如果您知道满足约束而编译器不满足,则需要自己进行优化。编译器编写者有时根本不会花时间在这种转换上,仅仅是因为它们不是普遍可用的。
【解决方案3】:

我希望在示例 #1 中,第一个会表现得更好。编译器可能会应用一些小技巧来避免分支。但是您正在利用编译器极不可能推断出的知识:即总和始终在[0:2*n-2] 范围内,因此一个减法就足够了。

例如 #2,第二种方式在现代 CPU 上速度更快,并且更易于遵循。在任何一个版本中,明智的评论都是合适的。 (看到编译器将第一个版本转换为第二个版本,我不会感到惊讶。)

【讨论】:

    猜你喜欢
    • 2011-02-22
    • 1970-01-01
    • 2023-03-10
    • 2018-11-26
    • 1970-01-01
    • 2010-09-05
    • 2015-02-06
    • 2015-08-19
    • 1970-01-01
    相关资源
    最近更新 更多