C 将0映射到任何非零值的无分支方法,而不考虑其他值?
我正试图找到此功能的最快实现方式:C 将0映射到任何非零值的无分支方法,而不考虑其他值?,c,performance,optimization,bit-manipulation,branch,C,Performance,Optimization,Bit Manipulation,Branch,我正试图找到此功能的最快实现方式: uint16_t forbid_zero(uint16_t x) { if(x == 0) return SOMETHING_NONZERO; return x; } 什么是非零并不重要,只要它不是零。除零以外的任何值都应不经修改地通过。做这件事最快的黑客是什么?我想有一些很好的无分支的方法 在上下文中,我在关键路径中有一个算法,其中零作为输入值将触发无限循环和其他不良行为,我很好奇是否有可能将输入设置为始终非零,而不进行分支
uint16_t forbid_zero(uint16_t x)
{
if(x == 0)
return SOMETHING_NONZERO;
return x;
}
什么是非零并不重要,只要它不是零。除零以外的任何值都应不经修改地通过。做这件事最快的黑客是什么?我想有一些很好的无分支的方法
在上下文中,我在关键路径中有一个算法,其中零作为输入值将触发无限循环和其他不良行为,我很好奇是否有可能将输入设置为始终非零,而不进行分支以检查0。将不正确的非零值传递给算法的结果并不那么糟糕;错误将被其他层上已经存在的检查发现,因此将0映射到任何其他值就足够了。一种可能的实现是:
uint16_t forbid_zero(uint16_t x)
{
return x | !x;
}
编译资源管理器将显示:
但是,即使您在问题中使用同一编译器给出的实现:
forbid_zero(unsigned short):
testw %di, %di
movl $1, %eax
cmovne %edi, %eax
ret
…当然也不能保证
!x也不会被编译成分支。也许return-!x | x代码>“我认为有一种很好的无分支的方式。”好吧,你不能拿一段C代码来预测它最终将如何在处理器中执行(除非你在这方面非常有经验)。您需要编译代码并研究生成的二进制文件。即使在那里,由于处理器使用的所有技巧,也很难预测性能,因此最终可能不得不进行分析。在现代CPU上,完全可预测的分支几乎是免费的。避免分支主要与不可预测的分支有关。我很欣赏你们两位提出的观点,但没有必要在每个性能问题上都提出。如果有人知道请求无分支代码,可以安全地假设他们有理由。
forbid_zero(unsigned short):
testw %di, %di
movl $1, %eax
cmovne %edi, %eax
ret