|
|
本帖最后由 Muacs 于 2026-6-16 01:23 编辑
既然讨论代码效率,那就不得不从汇编角度考虑了
方案A有个最大的问题,就是可能会遇到分支预测失败,一旦触发,整条指令流水线清空,性能开销瞬间暴涨几十倍;
汇编代码里有两条jne跳转指令,一旦命中重置分支,指令流水线重置,产生惩罚周期。
而方案B全程无分支跳转,性能稳定。
你有两个误区,
1.if虽然代码看起来直观,但≠性能更好,很容易遇到分支预测失败的的情况,
分支代码最大的性能杀手不是单次判断,而是分支预测失败时的不确定性带来的延迟。
2.其实现代的CPU和编译器下,方案B的模运算实际上也远没有200,除法一般只有10~40周期,而且常量取模时会直接消除除法运算;
mod n这里n是常量时,编译器会把取模优化成乘法+移位,完全消除除法指令,只有n为变量才会以除法进行运算;
if的分支遇到最坏的情况时,性能损失远超除法开销;单次循环对比时,多数场景B也会比A更快。
总结:
新手用方案A可能更好,因为代码可读性更好,方案B需要熟悉模运算。
具体使用也需要结合实际项目环境。
如果是高频次循环,追求稳定,比如游戏、音视频处理、实时环形缓冲区等,用方案B更好。
如果是低频次循环,数组长度小且固定,还有逻辑判断多时,可以用方案A牺牲一点性能来换取代码可读性。
还有个方法是就是把方案A代码修改一下,和原逻辑相等,编译器会消除跳转,性能优于原来的双if。
- while (true)
- {
- ++i;
- if (i == n) i = 0;
- --j;
- if (j == -1) j = n - 1;
- // 其它
- }
复制代码
|
|