GNU编译优化级别-O-O1-O2-O3salon
最近做⼀个算法的GPU加速,发现实际上使⽤gcc的-O3(最⾼级编译优化)选项,可以获得很⾼的加速⽐,我的程序⾥达到了3倍的样⼦,有时效果甚⾄⽐GPU加速好。因此⼩⼩学习了下GNU的编译优化。
附⾔⼀句,在进⾏调试的时候,最好关闭编译优化,不然程序⾃动优化,执⾏的步骤可能稍有变化。
GNU编译器提供-O选项供程序优化使⽤:
-O 提供基础级别的优化not relevant
-O2 提供更加⾼级的代码优化,会占⽤更长的编译时间
-O3 提供最⾼级的代码优化
不同的优化级别使⽤的优化技术也可以单独的应⽤于代码。可以使⽤-f命令⾏选项引⽤每个
德国留学生的优势是什么
单独的优化技术。
1,编译器优化级别1
在优化的第⼀个级别执⾏基础代码的优化。这个级别试图执⾏9种单独的优化功能:
humour
-fdefer-pop: 这种优化技术与汇编语⾔代码在函数完成时如何进⾏操作有关。⼀般
情况下, 函数的输⼊值被保存在堆栈中并且被函数访问。函数返回时, 输⼊值还在
堆栈中。⼀般情况下, 函数返回之后, 输⼊值被⽴即弹出堆栈。这样做会使堆栈中
的内容有些杂乱。
-fmerge-constans: 使⽤这种优化技术, 编译器试图合并相同的常量. 这⼀特性有
时候会导致很长的编译时间, 因为编译器必须分析c或者c++程序中⽤到的每个常量,
并且相互⽐较他们.
-fthread-jumps: 使⽤这种优化技术与编译器如果处理汇编代码中的条件和⾮条件
分⽀有关。在某些情况下, ⼀条跳转指令可能转移到另⼀条分⽀语句。通过⼀连串
跳转, 编译器确定多个跳转之间的最终⽬标并且把第⼀个跳转重新定向到最终⽬标。
-floop-optimize: 通过优化如何⽣成汇编语⾔中的循环,编译器可以在很⼤程序上
keylogger
提⾼应⽤程序的性能。通常, 程序由很多⼤型且复杂的循环构成。通过删除在循环
内没有改变值的变量赋值操作, 可以减少循环内执⾏指令的数量, 在很⼤程度上提⾼
性能。此外优化那些确定何时离开循环的条件分⽀,以便减少分⽀的影响。
-fif-conversion: if-then语句应该是应⽤程序中仅次于循环的最消耗时间的部分。
简单的if-then语句可能在最终的汇编语⾔代码中产⽣众多的条件分⽀。通过减少
或者删除条件分⽀, 以及使⽤条件传送设置标志和使⽤运算技巧来替换他们, 编译
器可以减少if-then语句中花费的时间量。
-fif-conversion2: 这种技术结合更加⾼级的数学特性,减少实现if-then语句所
需的条件分⽀。
-fdelayed-branch: 这种技术试图根据指令周期时间重新安排指令。它还试图把
尽可能多的指令移动到条件分⽀前, 以便最充分的利⽤处理器的治理缓存。
-
fguess-branch-probability: 就像其名称所暗⽰的, 这种技术试图确定条件分⽀最可
能的结果, 并且相应的移动指令, 这和延迟分⽀技术类似。因为在编译时预测代码的安排,
所以使⽤这⼀选项两次编译相同的c或者c++代码很可能会产⽣不同的汇编语⾔代码,这取决
于编译时编译器认为会使⽤那些分⽀。因为这个原因, 很多程序员不喜欢采⽤这个特性, 并且
专门地使⽤-fno-guess-branch-probability选项关闭这个特性
-fcprop-registers: 因为在函数中把寄存器分配给变量, 所以编译器执⾏第⼆次检查以便减少
调度依赖性(两个段要求使⽤相同的寄存器)并且删除不必要的寄存器复制操作。
2, 编译器优化级别2
结合了第⼀个级别的所有优化技术, 再加上⼀下⼀些优化:
世界杯2014赛程-fforce-mem: 这种优化再任何指令使⽤变量前, 强制把存放再内存位置中的所有变量都复制到寄存器
中。对于只涉及单⼀指令的变量, 这样也许不会有很⼤的优化效果. 但是对于再很多指令(必须数学操作)
中。对于只涉及单⼀指令的变量, 这样也许不会有很⼤的优化效果. 但是对于再很多指令(必须数学操作)
中都涉及到的变量来说, 这会时很显著的优化, 因为和访问内存中的值相⽐ ,处理器访问寄存器中的值要
快的多。metro station
-foptimize-sibling-calls: 这种技术处理相关的和/或者递归的函数调⽤。通常, 递归的函数调⽤
可以被展开为⼀系列⼀般的指令,⽽不是使⽤分⽀。这样处理器的指令缓存能够加载展开的指令并且
处理他们, 和指令保持为需要分⽀操作的单独函数调⽤相⽐, 这样更快。
-fstrength-reduce: 这种优化技术对循环执⾏优化并且删除迭代变量。迭代变量是捆绑到循环计数器
的变量, ⽐如使⽤变量, 然后使⽤循环计数器变量执⾏数学操作的for-next循环。
-fgc:这种技术对⽣成的所有汇编语⾔代码执⾏全局通⽤表达式消除历程。这些优化操作试图分析
⽣成的汇编语⾔代码并且结合通⽤⽚段,消除冗余的代码段。如果代码使⽤计算性的goto, gcc指令推
荐
whateveryoudo使⽤-fno-gc选项。
-fc-follow-jumps: 这种特别的通⽤⼦表达式消除技术扫描跳转指令, 查找程序中通过任何其他途径都不
会到达的⽬标代码。这种情况最常见的例⼦就式if-then-el语句的el部分。
-frerun-c-after-loop: 这种技术在对任何循环已经进⾏过优化之后重新运⾏通⽤⼦表达式消除例程。
这样确保在展开循环代码之后更进⼀步地优化还编代码。
-fdelete-null-pointer-checks: 这种优化技术扫描⽣成的汇编语⾔代码, 查找检查空指针的代码。编译
器假设间接引⽤空指针将停⽌程序。如果在间接引⽤之后检查指针,它就不可能为空。
-fextensive-optimizations: 这种技术执⾏从编译时的⾓度来说代价⾼昂的各种优化技术,但是它可能
对运⾏时的性能产⽣负⾯影响。
-fregmove: 编译器试图重新分配mov指令中使⽤的寄存器, 并且将其作为其他指令操作数, 以便最⼤化
捆绑的寄存器的数量。
-fschedule-insns: 编译器将试图重新安排指令, 以便消除等待数据的处理器。对于在进⾏浮点运算时有
延迟的处理器来说,这使处理器在等待浮点结果时可以加载其他指令。
-fsched-interblock: 这种技术使编译器能够跨越指令块调度指令。这可以⾮常灵活地移动指令以便等待
期间完成的⼯作最⼤化。
-fcaller-saves: 这个选项指⽰编译器对函数调⽤保存和恢复寄存器, 使函数能够访问寄存器值, ⽽且不必
保存和恢复他们。如果调⽤多个函数, 这样能够节省时间, 因为只进⾏⼀次寄存器的保存和恢复操作, ⽽
不是在每个函数调⽤中都进⾏。
-fpeephole2: 这个选项允许进⾏任何计算机特定的观察孔优化。
六人行第一季下载
-freorder-blocks: 这种优化技术允许重新安排指令块以便改进分⽀操作和代码局部性。
-fstrict-aliasing: 这种技术强制实⾏⾼级语⾔的严格变量规则。对于c和c++程序来说, 它确保不在数据
类型之间共享变量. 例如, 整数变量不和单精度浮点变量使⽤相同的内存位置。
-funit-at-a-time: 这种优化技术指⽰编译器在运⾏优化例程之前读取整个汇编语⾔代码。这使编译器可以
重新安排不消耗⼤量时间的代码以便优化指令缓存。但是, 这会在编译时花费相当多的内存, 对于⼩型计算机可能是⼀个问题。
-falign-functions: 这个选项⽤于使函数对准内存中特定边界的开始位置。⼤多数处理器按照页⾯读取内存,
并且确保全部函数代码位于单⼀内存页⾯内, 就不需要叫化代码所需的页⾯。
-fcrossjumping: 这是对跨越跳转的转换代码处理,以便组合分散在程序各处的相同代码。这样可以减少remarks
代码的长度,但是也许不会对程序性能有直接影响。
代码的长度,但是也许不会对程序性能有直接影响。
3, 编译器优化级别3
它整合了第⼀和第⼆级别中的左右优化技巧, 还包括⼀下优化:
-finline-functions: 这种优化技术不为函数创建单独的汇编语⾔代码,⽽是把函数代码包含在调度程序的
代码中。对于多次被调⽤的函数来说, 为每次函数调⽤复制函数代码。虽然这样对于减少代码长度不利, 但是通过最充分的利⽤指令缓存代码, ⽽不是在每次函数调⽤时进⾏分⽀操作, 可以提⾼性能。
-fweb: 构建⽤于保存变量的伪寄存器⽹络。伪寄存器包含数据, 就像他们是寄存器⼀样, 但是可以使⽤各种
其他优化技术进⾏优化, ⽐如c和loop优化技术。
-fgc-after-reload: 这中技术在完全重新加载⽣成的且优化后的汇编语⾔代码之后执⾏第⼆次gc优化,
帮助消除不同优化⽅式创建的任何冗余段。