Daa*_*mer 7 c optimization performance
有没有办法删除以下if语句来检查该值是否低于0?
int a = 100;
int b = 200;
int c = a - b;
if (c < 0)
{
c += 3600;
}
Run Code Online (Sandbox Code Playgroud)
值c应在0和3600之间都撒谎a和b签名.值a也应介于0和3600之间.(是的,它是0.1度的计数值).该值通过中断复位到3600,但如果该中断来得太晚,它会下溢,这不是问题,但软件应该仍然能够处理它.它做的.
我们if (c < 0)在相当一些计算位置的地方进行检查.(计算新职位等)
我曾经习惯使用模数运算符来使用除数的符号,我们的编译器(C89)正在使用除数签名.
有没有办法以不同的方式进行此计算?示例结果:
a - b = c
100 - 200 = 3500
200 - 100 = 100
Run Code Online (Sandbox Code Playgroud)
jma*_*man 11
好问题!这个怎么样?
c += 3600 * (c < 0);
Run Code Online (Sandbox Code Playgroud)
这是我们保留分支预测器槽的一种方法.
这个怎么样(假设32位整数):
c += 3600 & (c >> 31);
Run Code Online (Sandbox Code Playgroud)
c >> 31 将所有位设置为原始MSB,对于负数,其为1,对于2-complement,其他为0.
负数移位权是根据C标准文档正式实现定义的,但它几乎总是用MSB复制实现(通用处理器可以在单个指令中完成).
这肯定会导致没有分支,(c < 0)在某些情况下可能会使用分支实现分支.
你为什么担心这个分支?[原因在对该问题的评论中解释.]
替代方案如下:
((a - b) + 3600) % 3600
Run Code Online (Sandbox Code Playgroud)
这假定a并且b已经在范围内0..3600; 如果他们不受控制,更普遍的解决方案是Drew McGowen 建议:
((a - b) % 3600 + 3600) % 3600
Run Code Online (Sandbox Code Playgroud)
分支未命中必须非常昂贵才能使这么多计算变得有价值.