编译器是否会简化按顺序执行多次的操作
Will an operation done several times in sequence be simplified by compiler?
这个问题我已经有很长时间了,但从来不知道去哪里找。如果某个操作被编写了很多次,编译器会简化它,还是会运行完全相同的操作并获得完全相同的答案?
例如,在下面的类似c的伪代码中,(i%3)*10
重复了很多次。
for(int i=0; i<100; i++) {
array[(i%3)*10] = someFunction((i%3)*10);
int otherVar = (i%3)*10 + array[(i%3)*10];
int lastVar = (i%3)*10 - otherVar;
anotherFunction(lastVar);
}
我知道变量更适合视觉目的,但它也更快吗?(i%3)*10
每个循环计算 5 次吗?
在某些情况下,我不知道使用变量还是离开原始操作更快。
编辑:在win 10上使用gcc(MinGW.org GCC-8.2.0-3)8.2.0
执行哪些优化取决于编译器、指定的编译器优化标志和体系结构。
以下是针对您的示例的一些可能的优化:
- 循环展开 这使得二进制文件更大,因此是一种权衡;例如,您可能不希望在内存非常少的微型处理器上执行此操作。
- 通用子表达式消除 (CSE) 您可以非常确定您的
(i % 3) * 10
在每次循环迭代中只会执行一次。
关于您对视觉清晰度与优化的关注:在处理像您这样的"本地情况"时,您应该关注代码清晰度。
优化收益通常是在更高的级别上进行的;例如,在您使用的算法中。
关于优化有很多话要说;以上只是几个开场白。你对事物的工作方式感兴趣是件好事,因为这对一个优秀的(C/C++)程序员来说很重要。
当然,你应该删除代码中存在的混淆:
for (int i = 0; i < 100; ++i) {
int i30 = i % 3 * 10;
int r = someFunction(i30);
array[i30] = r;
anotherFunction(-r);
}
突然间,它看起来简单了很多。
留给编译器(使用适当的选项)来优化您的代码,除非您发现在测量后实际上必须伸出援手。
在这种情况下,展开三次对于编译器来说是一个好主意。尽管内联可能总是显示更好的选择。
是的,按顺序执行多次的操作将由编译器优化。
更详细地说,所有主要的编译器(GCC、Clang 和 MSVC)都将(i%3)*10
的值存储到临时(暂存、垃圾)寄存器中,然后在再次使用等效表达式时使用该值。
这种优化称为GCSE(GNU公共子表达式消除),否则称为CSE。
这占用了计算循环所需的时间
相关文章:
- 按下Arduino按钮后,如何在C#应用程序上执行操作
- 是否可以访问类数据成员并在析构函数中对它们执行操作?
- 如何让派生类在调用基类之前执行操作?
- CListCtrl 根据选定的行值执行操作
- 在服务器上执行操作的正确和 REST 方式?
- 是否可以拦截/检测关闭 PC 并首先执行操作的请求?
- 如何有效地使用 std::async 对指针数组执行操作
- 无法对套接字执行操作,因为系统缺少足够的缓冲区空间或队列已满
- 递归推动POP POSTFIX计算器无法正确执行操作,只需将最后一个数字作为结果
- QListWidgetItem 当按钮单击时执行操作
- 为什么C++没有简洁的语法允许在不定义计数器的情况下多次执行操作?
- 如何在标准库C/C++函数中进行gdb单步执行操作
- 如何对 n 个字符串执行操作,然后在C++中打印它们
- 从文件中读取运算符并执行操作C++
- 使用重载运算符在函数调用时执行操作
- 您如何选择在opencv-dnn上执行操作的设备
- 如何使用BoostSpirit.Qi增量解析(并对其执行操作)大文件
- 在remove_if删除元素之前,我可以滥用谓词对元素执行操作吗
- 在使用Qt修改任何复选框状态时执行操作
- 是否可以在不使用任何头文件的情况下在C++中执行I/O操作