灵活地使用编译器开关选项可生成具移植性且高度优化的代码,你用了吗?
充分利用AMD 64位技术需要以下三个条件:必要的AMD64硬件平台,一个可支持AMD64的操作系统,和一个支持AMD64 的64位编译器。AMD公司提供了第一个条件,Window和Linux提供了第二个条件,而一些开发工具提供了最后一个条件。这篇文章主要着重于阐述怎样设置Windows(Visual C++ 2005)及Linux(gcc 3.3.3)环境下的C/C++编译器选项。
虽然PathScale和Portland Group公司等几个开发工具提供商推出了支持AMD64架构的编译器产品,但对于大多数Windows和Linux下的开发者来说,Microsoft和gcc编译器仍然是不二的选择。
Microsoft编译器
虽然Microsoft还没有完全发布针对AMD64的操作系统,但通过它的消费者预览计划,已经提供了一个beta版操作系统可供使用,这个叫做Windows XP Professional x64的系统已经可以获取,这个产品的早期版本有不同的名字,所以不要弄混淆了。
在这要讨论的C/C++编译器是Microsoft Visual Studio 2005 Beta的其中一个组件,MSDN的订阅用户不用任何费用就可以获得。有关编译器的信息及开发环境目前都是已知的。
在开始设置编译器选项之前,必须要注重的是,没有任何选项可以把程序代码从32位转换成64位。要移植的代码必须多留意ILP(整型、长整型和指针),如:一个整型占用几比特位,长整型、指针呢。这三种类型的数据也许代表了为什么移植的程序会悄无声息地失败的一系统问题。
在x64的应用程序二进制层面上,ILP分别是32位、32位和64位(注重这与64位Linux上的ILP不同),所以,在移植代码到新平台之前,要充分考虑这些数据的位宽。-Wp64 -W3,这一对应用于32位代码的编译器选项可以标识出移植到64位平台的潜在问题。
选项Wp64是主要的作用因素,而-W3只是简单地告诉编译器要使用三级警告,而三级警告通常是建议性的,比如就像可移植性问题(但较低的警告级别通常会指出更严重的问题所在),这些选项将会捕捉到对数据值的无意识截断。从个人角度来说,不管目标平台是什么,都要打开这些选项,以保证编写出的代码都具有可移植性。
假如使用Visual Stuio .NET,通常可以在"工程"->"属性"对话框中,在GUI模式下打开这些选项,然而,你还是可以从命令行模式使用make [程序名]或批处理文件,来编译程序,通常是在命令行中键入 cl 命令,这个命令将调用C/C++编译器。命令后面紧接着依次是:开关选项、文件名、链接期间选项。
一旦你写好的代码能正常运行,通过设置以下的优化选项,可在运行平台上得到更好的执行效率(以下只是针对AMD平台的建议)。
-O2打开几个标准的优化步骤
-Ob2打开内联函数展开(小函数将在被调用处内联处理,这比直接调用它们效率更高)
-GL打开内部过程优化(只在函数间)
-fp:在浮点数学运算中,假如只是导致精度稍微的损失,那么加快运算形式。假如需要极度精确的浮点结果,可能你要避免使用此选项,但假如在数字的最后一些位中,程序可接受取整(四舍五入),使用此选项将会极大地提高浮点执行效率。在本文后面的参考资源中,会有关于此折衷方法的具体解释,同样也会解释通过使用pragma,怎样在函数调用函数时打开快速浮点功能。 Visual C++ 2005带来了配置向导优化(profile-guided optimization PGO),这种形式的优化只是由两个步骤得来的结果。首先,代码将会通过设备化(-LTCG:PGI)选项来编译,接下来程序会运行,在运行期间,设备化代码产生一个可执行的概括文件,这个文件包含了哪些函数被调用,是以什么顺序呢等信息。
运行过几次之后,程序将在源代码级重新编译,并且使用设备化文件作为输入。编译器此时在程序执行模式的基础之上,再进行一次附加的优化(这次编译使用-LTCG:PGO选项)。
设备化可以告诉编译器许多重要的信息,例如:假如两个函数总是一个接另一个地执行,可能的话,就把它们放在同一个内存页当中。基于AMD芯片的电脑上,Microsoft自己的测试表明(相关详见资源中有关PGO的文章),在benchmark测试中,配置向导优化将带来大约10%的性能提升。
假如程序不是面向大众的,可以考虑关闭一个Microsoft缺省打开的安全特性:侦测缓冲溢出(-GS)。假如程序不是多线程的,也可以考虑关闭产生线程安全代码的缺省选项(-D_ST_MODEL)。关闭这两个选项会带来稍微的性能提升,但要确定必须是在没有牺牲安全的情况下换来这点速度提升。拿不准的话,还是让它们缺省打开吧。
利用上述的这些开关控制选项,可得到Microsoft Windows平台上干净、快速、且可具移植性的程序代码,那我们再来看看Linux。
Photoshop教程
数据结构
五笔输入法专题
QQ病毒专题
共享上网专题
Google工具和服务专题
GCC编译器
在Linux平台上,GNU gcc C/C++编译器存在着许多种不同的版本。
对于在Linux平台下的AMD64应用程序二进制层面上,ILP是32位、64位和64位。正如前面所说的,在移植代码到新平台之前,要充分考虑这些数据的位宽。AMD推荐以下可以使用AMD64技术的操作系统版本,它们是:
Red Hat Enterprise-gcc-ssa (从3.5开始的一个分枝)-package: gcc-ssa 安装于 /usr/bin
SuSE Linux-gcc 3.3.3 (Hammer版)-package: gcc-33 安装于 /opt/gcc33
以上两个版本的gcc通过使用下述选项,都可以生成更快的代码,这对gcc来说,终归是一场挑战,因为相对于优化,它最初的设计目标是创建可具移植性的代码。
-O3打开几个通用的优化
-ffast打开浮点数学运算的更快方法,与之前提过的Microsoft的选项类似
-funroll-all-loops将把所有的循环解开成代码。这个开关选项使可执行文件的体积变大,但能改善执行效率,然而,测试一下此选项所带来的改变是非常重要的。举例来说,假如因为循环被展开后,不再适合放入缓存,那实际上将降低性能,因此,有些循环最好还是不要管它。多试几次,将会有助于判定此选项带来的价值。
64位GCC编译器同样也提供了配置向导优化(profile-guided optimization PGO)。想了解PGO是如何运作的更多信息,参考前面所提及的Microsoft编译器部分。对以上提及的gcc编译来说,要想使用PGO,第一步是带上-fprofile-arcs选项,接下来在重新编译中打开-fbranch-probabilities选项。
还有一件更重要的事,假如程序中有许多数学运算,就像计算FFT、调用触发器函数,或者解算线性代数,可能此时就要考虑使用AMD核心数学库(ACML),它提供了针对于含有AMD64技术芯片的高度优化的函数。在这些数学函数被经常调用的密集循环中,ACML能带来实质上的性能改变。
总之,明智地使用这些开关选项,你可以在AMD64平台上生成可具移植性,且极有效率的代码。