C 比较速度:等于“==” vs Bitwise 和“&”
C speed of comparison: Equals "==" vs Bitwise and "&"
假设我有一个整数,它是 2 的幂,例如。 1024:
int a = 1 << 10; //works with any power of 2 no.
现在我想检查另一个整数 b
是否与 a
相同。这是 faster/better(尤其是在弱嵌入式系统上):
if (b == a) {}
或
if (b & a) {}
?
抱歉,如果这是一个菜鸟问题,但无法通过搜索找到答案。
编辑:感谢许多有见地的回答。我只能 select 其中之一,但欢迎大家。
X86 CPU 根据任何操作的结果与零的比较设置标志。
对于 ==
,您的编译器将使用专用的比较指令或减法,在这两种情况下都设置此标志。 if()
然后通过以该位为条件的跳转实现。
对于&
,使用了另外一条指令,逻辑位与指令。这也适当地设置了标志。所以,同样,下一条指令将是条件分支。
因此,问题归结为:减法与按位与指令之间是否存在性能差异?答案是 "no" 在任何理智的体系结构上.两条指令使用相同的 ALU,都设置相同的标志,并且该 ALU 通常设计为在单个时钟周期内执行减法。
底线:编写可读代码,不要尝试对无法优化的内容进行微优化。
这些操作甚至不等价,因为当 a
和 b
都是 0
时,a & b
将是 false
。
所以我建议表达你想要的语义(即a == b
)并让编译器进行优化。
如果您随后测量您在那个时候遇到了性能问题,那么您可以开始analyzing/optimizing...
简短的回答是这样的——这取决于你比较的是什么类型的东西。但是,在这种情况下,我假设您正在相互比较两个变量(而不是变量和立即数等)
This website,虽然比较老,研究了不同指令在x86平台上占用了多少个时钟周期。我们在这里感兴趣的两条指令是 "AND" 指令和 "CMP" 指令(编译器分别将其用于 & 和 ==)。我们在这里可以看到,这两条指令都需要大约 1/3 的周期——也就是说,你平均可以在 1 个周期内执行其中的 3 条。将此与(1996 年)执行 23 个周期的 "DIV" 指令进行比较。
然而,这忽略了一个重要的细节。 "AND" 指令不足以完成您正在寻找的行为。事实上,对 x86_64 的简短编译表明您需要针对“&”版本的 "AND" 和 "TEST" 指令,而“==”仅使用 "CMP" 操作说明。因为所有这些指令在 IPC 中都是等效的,所以“==”实际上会稍微快一些......截至 1996 年。
如今,处理器在裸机层的优化非常好,您不太可能注意到差异。也就是说,如果您想确定...只需编写一个测试程序并自己找出答案。
如上所述,即使你有 2 的幂,这些指令仍然不等价,因为它不适用于 0。好吧......我想从技术上讲,零不是2 的幂。:) 但是你想旋转它,使用“==”。
假设我有一个整数,它是 2 的幂,例如。 1024:
int a = 1 << 10; //works with any power of 2 no.
现在我想检查另一个整数 b
是否与 a
相同。这是 faster/better(尤其是在弱嵌入式系统上):
if (b == a) {}
或
if (b & a) {}
?
抱歉,如果这是一个菜鸟问题,但无法通过搜索找到答案。
编辑:感谢许多有见地的回答。我只能 select 其中之一,但欢迎大家。
X86 CPU 根据任何操作的结果与零的比较设置标志。
对于 ==
,您的编译器将使用专用的比较指令或减法,在这两种情况下都设置此标志。 if()
然后通过以该位为条件的跳转实现。
对于&
,使用了另外一条指令,逻辑位与指令。这也适当地设置了标志。所以,同样,下一条指令将是条件分支。
因此,问题归结为:减法与按位与指令之间是否存在性能差异?答案是 "no" 在任何理智的体系结构上.两条指令使用相同的 ALU,都设置相同的标志,并且该 ALU 通常设计为在单个时钟周期内执行减法。
底线:编写可读代码,不要尝试对无法优化的内容进行微优化。
这些操作甚至不等价,因为当 a
和 b
都是 0
时,a & b
将是 false
。
所以我建议表达你想要的语义(即a == b
)并让编译器进行优化。
如果您随后测量您在那个时候遇到了性能问题,那么您可以开始analyzing/optimizing...
简短的回答是这样的——这取决于你比较的是什么类型的东西。但是,在这种情况下,我假设您正在相互比较两个变量(而不是变量和立即数等)
This website,虽然比较老,研究了不同指令在x86平台上占用了多少个时钟周期。我们在这里感兴趣的两条指令是 "AND" 指令和 "CMP" 指令(编译器分别将其用于 & 和 ==)。我们在这里可以看到,这两条指令都需要大约 1/3 的周期——也就是说,你平均可以在 1 个周期内执行其中的 3 条。将此与(1996 年)执行 23 个周期的 "DIV" 指令进行比较。
然而,这忽略了一个重要的细节。 "AND" 指令不足以完成您正在寻找的行为。事实上,对 x86_64 的简短编译表明您需要针对“&”版本的 "AND" 和 "TEST" 指令,而“==”仅使用 "CMP" 操作说明。因为所有这些指令在 IPC 中都是等效的,所以“==”实际上会稍微快一些......截至 1996 年。
如今,处理器在裸机层的优化非常好,您不太可能注意到差异。也就是说,如果您想确定...只需编写一个测试程序并自己找出答案。
如上所述,即使你有 2 的幂,这些指令仍然不等价,因为它不适用于 0。好吧......我想从技术上讲,零不是2 的幂。:) 但是你想旋转它,使用“==”。