c++ - `if` 语句在取模之前和分配操作之前是多余的吗?

标签 c++ c performance arm thumb

考虑下一个代码:

unsigned idx;
//.. some work with idx
if( idx >= idx_max )
    idx %= idx_max;

可以简化为仅第二行:

idx %= idx_max;

并且将达到相同的结果。


我多次遇到下一个代码:

unsigned x;
//... some work with x
if( x!=0 )
  x=0;

可以简化为

x=0;

问题:

  • 使用 if 有什么意义吗?为什么?尤其是 ARM Thumb 指令集。
  • 可以省略这些 if 吗?
  • 编译器做了哪些优化?

最佳答案

如果您想了解编译器在做什么,您只需提取一些程序集即可。我推荐这个网站(我已经从问题中输入了代码)):https://godbolt.org/g/FwZZOb .

第一个例子更有趣。

int div(unsigned int num, unsigned int num2) {
    if( num >= num2 ) return num % num2;
    return num;
}

int div2(unsigned int num, unsigned int num2) {
    return num % num2;
}

生成:

div(unsigned int, unsigned int):          # @div(unsigned int, unsigned int)
        mov     eax, edi
        cmp     eax, esi
        jb      .LBB0_2
        xor     edx, edx
        div     esi
        mov     eax, edx
.LBB0_2:
        ret

div2(unsigned int, unsigned int):         # @div2(unsigned int, unsigned int)
        xor     edx, edx
        mov     eax, edi
        div     esi
        mov     eax, edx
        ret

基本上,出于非常具体和合乎逻辑的原因,编译器不会优化掉分支。如果整数除法的成本与比较的成本大致相同,那么分支将毫无意义。但是整数除法(通常与模数一起执行)实际上非常昂贵:http://www.agner.org/optimize/instruction_tables.pdf .这些数字因架构和整数大小而有很大差异,但通常可能是 15 到接近 100 个周期的延迟。

通过在执行模数之前取一个分支,实际上可以为自己节省很多工作。但请注意:编译器也不会将没有分支的代码转换为汇编级别的分支。那是因为分支也有一个缺点:如果模数最终还是必要的,那你只是浪费了一点时间。

在不知道 idx < idx_max 的相对频率的情况下,无法对正确的优化做出合理的判断。将是真的。所以编译器(gcc 和 clang 做同样的事情)选择以相对透明的方式映射代码,把这个选择权交给开发者。

所以那个分支可能是一个非常合理的选择。

第二个分支应该是完全没有意义的,因为比较和赋值的可比成本。也就是说,您可以在链接中看到,如果编译器有对变量的引用,它们仍然不会执行此优化。如果该值是一个局部变量(如在您演示的代码中),那么编译器将优化分支。

总而言之,第一段代码可能是一个合理的优化,第二段可能只是一个累了的程序员。

关于c++ - `if` 语句在取模之前和分配操作之前是多余的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43731203/

相关文章:

c++ - 如何将张量转换为图像数组?

c++ - 使用工厂方法合并不同的类(c++)

合并排序的 C 实现,如 Cormen's et al "Introduction to algortithms"not working properly 所示

objective-c - 有人可以向我解释 %f 和 %d 的目的吗?

performance - 如何在Matlab中向量化 'for'循环

javascript - 加速 Ionic 应用程序中的 Levenshtein 距离计算

c++ - 作为类成员更新引用

c++ - 在 C++ 中比较 double

c - 如何读取输入字符串直到 C 中的空白行?

python - 使用 Numpy 更高效地生成过滤器