【问题标题】:C speed of comparison: Equals "==" vs Bitwise and "&"C 比较速度:等于 "==" vs Bitwise 和 "&"
【发布时间】:2020-05-10 12:32:09
【问题描述】:

假设我有一个整数,它是 2 的幂,例如。 1024:

int a = 1 << 10; //works with any power of 2 no.

现在我想检查另一个整数b 是否与a 相同。哪个更快/更好(尤其是在弱嵌入式系统上):

if (b == a) {}

if (b & a) {}

?

对不起,如果这是一个菜鸟问题,但无法使用搜索找到答案。

编辑:感谢您提供许多有见地的答案。我只能选择其中一个,但都欢迎。

【问题讨论】:

  • 您想使用==,因为b &amp; a 将测试任何您拥有1 的任何对应位的任何位集为真。使用适当的比较编写代码并让编译器处理优化。见:Replacing “==” with bitwise operators
  • 将 a 定义为 1&lt;&lt;n 保证它只设置了 1 位。我经常阅读这个建议“让编译器决定”。但对我来说,当我想更好地了解内部运作时,这个建议有点不满意。感谢您的链接。
  • 我明白你在说什么,是的,2 的幂只会设置一个位 - 但同样适用 - 使用 == 并让编译器优化。编译器将优化为cmp,然后使用sete 在可能的情况下提供返回。
  • a &amp; b 不会做你想做的事,但a ^ b(否定)会。
  • 这取决于编译器的质量以及目标 CPU 如何实现相关汇编语言的规范(每种指令的时钟周期数),所以我必须更具体。

标签: c if-statement bitwise-and equals-operator


【解决方案1】:

这些操作甚至不等价,因为当ab 都是0 时,a &amp; b 将是false。 所以我建议表达你想要的语义(即a == b)并让编译器进行优化。

如果您随后测量您当时有性能问题,那么您可以开始分析/优化...

【讨论】:

  • 公平地说,0 不是 2 的幂。虽然这些陈述不等价是绝对正确的,但它们在技术上可能等同于 2 的幂。话虽如此,我同意你的观点。
  • @Roguebantha, a &amp; b 并不总是适用于即使 a 是 2 的幂。例如,考虑 a=1&lt;&lt;10; b=(1&lt;&lt;10)|1;
  • 同意,但是,(1
  • @Roguebantha,OP 从未说过 b 是 2 的幂。
  • 这是一个公平的观点!我以为他的意思是他们俩都是,但是就问题的措辞而言,是的,我的假设肯定是错误的。
【解决方案2】:

简短的回答是 - 这取决于您要比较的内容类型。但是,在这种情况下,我假设您正在将两个变量相互比较(而不是变量和立即数等)

This website,虽然比较老,但研究了 x86 平台上不同指令占用了多少时钟周期。我们在这里感兴趣的两条指令是“AND”指令和“CMP”指令(编译器分别用于 & 和 ==)。在这里我们可以看到,这两条指令都需要大约 1/3 个周期——也就是说,你平均可以在 1 个周期内执行其中的 3 个。将此与“DIV”指令(在 1996 年)执行 23 个周期进行比较。

但是,这忽略了一个重要的细节。 “AND”指令不足以完成您正在寻找的行为。事实上,在 x86_64 上的简要编译表明,对于“&”版本,您需要一个“AND”和一个“TEST”指令,而“==”只使用“CMP”指令。因为所有这些指令在 IPC 中都是等价的,所以“==”实际上会稍微快一些……截至 1996 年。

如今,处理器在裸机层优化得非常好,以至于您不太可能注意到差异。也就是说,如果您想确定地看到...只需编写一个测试程序并自己找出来。

如上所述,即使您有 2 的幂,这些指令仍然不等价,因为它不适用于 0。嗯...我想从技术上讲,零不是 0 的幂2. :) 但是,如果您想旋转它,请使用“==”。

【讨论】:

    【解决方案3】:

    X86 CPU 根据任何操作的结果与零的比较来设置一个标志。

    对于==,您的编译器将使用专用的比较指令或减法,在两种情况下都设置此标志。然后,if() 通过一个以该位为条件的跳转来实现。

    对于&amp;,使用了另一条指令,即逻辑位和指令。这也适当地设置了标志。所以,再一次,下一条指令将是条件分支。

    所以,问题归结为:减法和按位加指令之间是否存在性能差异?在任何健全的架构上,答案都是“否”。两条指令使用相同的 ALU,都设置相同的标志,并且此 ALU 通常设计为在单个时钟周期内执行减法。


    底线:编写可读的代码,不要尝试对无法优化的部分进行微优化。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-06
      • 2011-10-21
      • 1970-01-01
      • 2019-03-07
      • 1970-01-01
      • 1970-01-01
      • 2011-02-20
      • 2016-06-25
      相关资源
      最近更新 更多