浅谈Gcc4.4.4优化

     Intel Compiler的编译器默认会加载一些有利于程序运行效率的开关,这也是Intel的编译器领先于其他编译器默认开关的原因之一。其实,作为跨平台的编译器,Gcc在选用恰当的优化选项后,运行效率在某些方面也是堪比Intel Compiler的。

     下面仅列举Gcc常用的优化选项。有的含义不作说明,请参看帮助文档。

1、-O系列

(1)-O和-O1

      包含下列选项

-fauto-inc-dec
-fcprop-registers
-fdce
-fdefer-pop
-fdelayed-branch
-fdse
-fguess-branch-probability
-fif-conversion2
-fif-conversion
-finline-small-functions
-fipa-pure-const
-fipa-reference
-fmerge-constants -fsplit-wide-types
-ftree-builtin-call-dce
-ftree-ccp
-ftree-ch
-ftree-copyrename
-ftree-dce
-ftree-dominator-opts
-ftree-dse
-ftree-fre
-ftree-sra
-ftree-ter
-funit-at-a-time
-fomit-frame-pointer

 

(2)-O2

    除了加载-O1的选项外,还加载

-fthread-jumps
-falign-functions -falign-jumps
-falign-loops -falign-labels
-fcaller-saves
-fcrossjumping
-fcse-follow-jumps -fcse-skip-blocks
-fdelete-null-pointer-checks
-fexpensive-optimizations
-fgcse -fgcse-lm
-findirect-inlining
-foptimize-sibling-calls
-fpeephole2
-fregmove
-freorder-blocks -freorder-functions
-frerun-cse-after-loop
-fsched-interblock -fsched-spec
-fschedule-insns -fschedule-insns2
-fstrict-aliasing -fstrict-overflow
-ftree-switch-conversion
-ftree-pre
-ftree-vrp

(3)-O3

      除了加载-O2外,还加载

-finline-functions
-funswitch-loops’?
-fpredictive-commoning
-fgcse-after-reload
-ftree-vectorize

(4)-Os

     为代码尺寸而优化代码。

     除了包含-O2的开关外,-Os还会使得下列开关禁用。

-falign-functions 
-falign-jumps 
-falign-loops
-falign-labels 
-freorder-blocks 
-freorder-blocks-and-partition
-fprefetch-loop-arrays 
-ftree-vect-loop-version

    另外,对于多个-O选项的情形,最后一个加载的为有效。比如gcc –O1 –Os –O3 –o test test.c,有效的优化开关为-O3。

    一般来说,用的最多的是-O3和-Os,如果遇到程序运行不正常的问题,请降低优化级别,如把-O3改为-O2(情况很少见)。

 

2、针对目标机器

(1)-march=cpu-type

     为cpu-type所针对的机器开启需要的指令集。

     cpu-type可以为pentium4、core2、athlon-4等(具体参见文档),比如-march=core2时,则会开启core2所支持的MMX、SSE、SSE2、SSE3、SSSE3指令集。

     另外还支持native类型,为编译器所在目前的CPU类型优化指令集,指定-march=native。

(2)-mfpmath=unit

     选择浮点运算单元。

     unit可以为387和sse。

    387为x86系列的默认值,使用标准的387浮点协处理器。

    sse为x64的默认值,使用sse指令集。

    一般你的程序如果有大量的浮点运算的话,在P4和K8以上级别的处理器上推荐开启-mfpmath=sse。

(3)加载指定指令集。

     可以使用-msse2、-msse4.1加载指定的指令集。

 

3、其他比较有效的选项

(1)-ftracer

     执行尾部复制以扩大超级块的尺寸,它简化了函数控制流,从而允许其它的优化措施做的更好。单独使用没啥意义,和其他优化选项一起使用很有效。

(2)-ffast-math

     违反IEEE/ANSI标准以提高浮点数计算速度,是个危险的选项,仅在编译不需要严格遵守IEEE规范且浮点计算密集的程序考虑采用。不考虑精度时使用这个选项速度会加快。

(3)-fivopts

     在trees上执行归纳变量优化。

(4)-ftree-parallelize-loops=n

     使循环并行化。只当循环无数据依赖时使用,在多核CPU上时使用才会有利。

(5)-ftree-loop-linear

     在trees上进行线型循环转换。它能够改进缓冲性能并且允许进行更进一步的循环优化。

(6)-fforce-addr

     必须将地址复制到寄存器中才能对他们进行运算。由于所需地址通常在前面已经加载到寄存器中了,所以这个选项可以改进代码。

(7)-floop-interchange

     交换循环变量。

    例如

DO J = 1, M
    DO I = 1, N
        A(J, I) = A(J, I) * C
    ENDDO
ENDDO

    会改变为

DO I = 1, N
    DO J = 1, M
        A(J, I) = A(J, I) * C
    ENDDO
ENDDO

    改变后,如果N比缓冲区大的话,会更有效率。这是因为Fortran里数组是以列主元为排列方式的。当然这个选项并不仅仅用于Fortran,Gcc家族的编译器都有效。

(8)-fvisibility=hidden

    设置默认的ELF镜像中符号的可见性为隐藏。使用这个特性可以非常充分的提高连接和加载共享库的性能,生成更加优化的代码,提供近乎完美的API输出和防止符号碰撞。我们强烈建议你在编译任何共享库(Dll)的时候使用该选项。

      -fvisibility-inlines-hidden

    默认隐藏所有内联函数,从而减小导出符号表的大小,既能缩减文件的大小,还能提高运行性能,强烈建议你在编译任何共享库的时候使用该选项。

(9)-minline-all-stringops

    默认时GCC只将确定目的地会被对齐在至少4字节边界的字符串操作内联进程序代码。该选项启用更多的内联并且增加二进制文件的体积,但是可以提升依赖于高速 memcpy, strlen, memset 操作的程序的性能。

(10)-m64

    生成专门运行于64位环境的代码,不能运行于32位环境,仅用于x86_64[含EMT64]环境。

(11)-fprefetch-loop-arrays

    生成数组预读取指令,对于使用巨大数组的程序可以加快代码执行速度,适合数据库相关的大型软件等。具体效果如何取决于代码。不能和-Os一起使用。

(12)-pipe

    在编译过程的不同阶段之间使用管道而非临时文件进行通信,可以加快编译速度。建议使用。

 

4、推荐选项开关

    综上,比较安全的开关为

-pipe -O3(-Os) -march=native -mfpmath=sse -msse2 -ftracer 
-fivopts -ftree-loop-linear -fforce-addr

    如果不需要多高的精度,比如GUI框架之类,加入

-ffast-math

    如果是编译的是共享库(.dll,.a)加入

-fvisibility=hidden
-fvisibility-inlines-hidden

posted on 2010-06-08 15:51  PcX  阅读(2070)  评论(0编辑  收藏  举报

导航