是什么阻止了优化
来源:互联网 发布:2016淘宝域名怎么设置 编辑:程序博客网 时间:2024/06/09 23:54
编译器会帮我们做很多优化,使我们写的很不优雅的代码也可以和大牛们写的得到比较接近的效率。当然,这前提是你们用的算法是一样的。编译器绝不会优化算法,不会把你的冒泡排序改成快排。但是,常数级别的优化也是很重要的。
编译器能做的事情有很多,在编译原理中我们知道,它可以消除死代码,提取公共子表达式等代码中妨碍效率的地方。但是,优化往往受到限制,因为它受到的最基础的约束就是不能改变程序的行为。这意味着,当它犹豫是否进行某一步优化时,它必须保守。就是说,它可以做很多事,但是对于稍有风险的事,它就选择不做。那么,都有哪些事情让优化感到风险呢?
第一个是函数调用。举个例子:
这是一个将字符串改成小写的程序,分析一下程序复杂度为O(n),这看上去是一定的,其实不然,它的实际复杂度为O(n2)。问题出在strlen(s)上,这个函数本身就是O(n)的,执行了n次,所以时间复杂度为O(n2),从编译原理的课上所学来看,编译器应该会发现这个问题,将strlen()函数提出来啊。其实不然,它会担心在你的循环中,你改变了字符串s。所以,它不敢帮你提出strlen()函数。如果你优化时,在不了解循环中的事情就擅自提出了这个函数,那么就会产生不好的事情。
第二个是内存别名。别名就是有两个指针指向了同一块内存。看一个例子:
这两个程序,看上去做的是一件事情,而且显然左边的效率更高一些。优化时很可能就将右边的代码改成了左边的。但是,如果指针xp和yp指向了同一个int那么结果就大大不同了。如果*xp = 1;那么计算过后左边结果*xp=3,右边*xp=2。这就是内存别名。
在优化过程中必须考虑内存别名的存在,如图:
如果a和b指向了同一个数组,那么结果就会大不一样。
在优化过程中,我们必须小心一些,不然就会改变程序的行为。如果我们确信不存在上述情况,而且对于优化产生的后果和风险都坦然接受或置之不理,那么编译器也会帮你做一些事情。G++编译时使用的-O参数就是用来选择优化等级的。等级越高,编译器越激进。带来的风险就越大。-O 主要进行跳转和延迟退栈两种优化;-O2 除了完成-O1的优化之外,还进行一些额外的调整工作,如指令调整等。-O3 则包括循环展开和其他一些与处理特性相关的优化工作。-O2进行了代码调整,就意味着它可以将我们上文中提到的那么strlen()的问题进行优化。当然,这也只是我的个人猜测。
- 是什么阻止了优化
- 是什么阻止了你的能力
- 是什么阻止了人工智能的步伐
- volatile与barrier指令阻止过度优化
- 面试--阻止编译优化方法 (46)
- 科普:是什么在阻止你访问facebook、youtube、twitter?
- 事件冒泡是什么 如何用jquery阻止事件冒泡
- 人类已经不能阻止开源了
- 地球人已经无法阻止Markdown了
- 人类已经阻止不了喵星人玩电脑了
- SQLServer阻止了对组件的访问
- 阻止事件冒泡好像不用兼容了
- Windows防火墙阻止了远程调试
- 是什么欺骗了我们?
- 忘了标题是什么
- 是什么改变了我
- 是什么改变了我
- 是什么改变了我
- java.util.Properties类 学习笔记
- HDU 1257 最少拦截系统 【LIS】
- 边采集边上传
- Python用subprocess的Popen来调用系统命令
- 58搜索公开的群聊的布局
- 是什么阻止了优化
- Leetcode Dungeon Game(经典动态规划)
- java定时任务:oracle导出excel后,发送excel作为附件的邮件
- vc6开发activex并发布全攻略(一)(初级篇)(原创)
- [IOS] 静态库项目之间的相互引用
- activty的生命周期
- 重构机房拦路虎(一)- 未能加载文件或程序集“DAL”或它的某一个依赖项。系统找不到指定的文件
- Eclipse调试Java程序技巧
- 禁止debian自动启动图形界面