灵活地使用编译器开关选项可生成具移植性且高度优化的代码,你用了吗?
充分利用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.