更快、更强 64位编程的三十二条军规

更快、更强 64位编程的三十二条军规

2005-11-16 17:28作者:谢启东出处:天极开发责任编辑:方舟

   即使目前没有为纳米电子学、空气动力学、分子静力学、细胞生命周期建模等等编写高级应用程序,说不定以下这32条规则,对你向更高级处理器移植程序会有所帮助。

  近期以来,似乎大家都在谈及64位计算,如采用AMD Athlon 64处理器的笔记本、采用IBM PowerPC 970芯片的Apple G5、又或Intel Itanium架构是否会被取消,对此,IT界和新闻界似乎都还没有尽兴。新一轮处理器所带来的冲击,不仅表现在改善数据库执行效率、提高图形程序速度上,也为编写解决世界上最复杂科学问题的应用程序,铺平了道路。

  不管怎样,想利用64位处理器带来的好处,不只是仅仅拷贝一个程序到一台新计算机上那样简单,至少,应用程序需要用64位库重新编译,而最坏的情况就是需要重写整个程序,以便去除不可移植的指针算法等其他麻烦。即使这样,新的应用程序也不一定比在旧的32位平台上运行得更好。

  幸运的是,要弄清楚在开始之前需要做哪些工作,还是比较容易的,特别是相关处理器的性能和局限,同样地,只要遵循一定的规则,就能以最少的改动换来期望的结果。为了让大家有个好的开始,特拟出了以下32条“军规”,其中包括了开发64位应用程序所必须了解的技术和信息。

首先,有小小不利因素


  1、64位处理器不是最近几年才发明的,差不多在十年前,DEC和Sun公司就推出了用于高端服务器的64位处理器,Motorola公司也于不久后的1996年推出了它的PowerPC 620处理器,甚至在同年,任天堂公司也推出了它的Nintendo 64游戏系统。可直到近两年,随着AMD Athlon 64和IBM PowerPC 970处理器的面世,人们才开始关注到64位计算的到来。随着这些处理器应用于桌面系统,分析家们开始预测,32位计算即将灭亡(可能稍微有点过早)。

  2、64位架构处理器就本身而言,不会在速度上两倍于32位的同等处理器。为什么呢,因为64位这个术语,只是简单地描述了处理器通用寄存器的大小,虽然这个大小决定了一次可处理的数据量,但并不代表数据处理的速度。

  3、某些应用程序在64位处理器上运行,可能实际上会较在同等的32位处理器上慢,主要是因为64位地址在缓存中占用了更多的空间,反而降低了缓存命中率。在Tony Bourke的一份对Sun Ultra 5工作站的独立调查报告中指出,不大量执行数据运算的程序,在64位平台上可能会降低20%的缓存命中率。“数据类型的扩大,如指针,意味着要占用更多的内存,此时内存成了瓶颈”,SUSE Linux项目经理Andreas Jaeger也表示,“在64位平台上,因为内存开销的增加,所以程序进行指针跟踪可能会更慢”。 接下来有好消息

  4、那为什么还需要64位处理器呢?其中的一个原因是,更宽的寄存器位可以一次处理更大的数字值。在32位系统上,2的32次方再加上1会引起溢出,因为在32位寄存器上,没有更多的位可以存储这个数值。而在许多编程语言中,由于提供了特殊的64位结构,所以开发32位程序的程序员一般都靠此来解决数值溢出这个问题,实际上,这些结构体需要处理器在两个32位寄存器上执行两次操作,这对那些需要经常执行复杂数学运算的程序来说,这个方法在执行效率上并没有优势。而64位处理器不再需要两个寄存器,这样,在科学计算领域中,程序员就可以编写出在更短的时间内解决更复杂问题的程序,一个最明显的例子就是VirginiaTech X超级计算机,由1100个Apple的双G5处理器构成,现在它是世界上排名第三的超级计算机。根据Apple公司的说法,G5处理器是被设计用来运行纳米电子学、化学、生物化学、空气动力学、分子静力学、细胞生命周期建模和计算声学等等高级应用程序的。

  5、另一个64位计算的受益者是视频编辑(和渲染)。64位系统所带来的强大计算能力,对视频程序开发者来说,无疑是个好消息,以往那些需要解码大段视频的程序,如今可以更快更复杂。这对视频游戏业来说,更加如此,游戏开发者一直都在寻找新的方法来显现更加逼真的场景。

  6、某些64位处理器有一些特殊的功能,这使得它们在速度上可以完全超越32位处理器。举例来说,AMD x84-64处理器有16个通用寄存器——比它的32位前辈多8个,PowerPC处理器有32个通用寄存器,而安腾(Itanium)有128个(虽然其中只有8个对程序员来说是可见的,另外120个由处理器按需分配)。就以上来说,应用程序可以在处理器内部保存更多的数据,以便随时取用,比起以往那种在需要数据时,再从内存里加载要好多了。

  “Apple G5处理器内部包含两个64位浮点单元,在音频创建、3D渲染和科学计算等依赖于浮点运算的领域,可谓功不可没。”Apple开发者关系协会发言人Anuj Nayar如是说,“它同样也包含了两个64位整数单元,在计算大数值整数时,可极大地提高效率。”

  7、在AMD Opteron和Athlon 64处理器上,如果要进行字节操作,此处有一个额外的优势,可以使用16个通用寄存器的低字节位,这意味着应用程序不再需要把数据在一些特殊的寄存器中挪来挪去

  8、另一个AMD x86-64处理器架构带来的好处就是,可以允许应用程序使用指令指针,来帮助计算函数和变量在共享库中的地址。如果没有这种RIP(相关指令指针),应用程序就必须使用一个额外的寄存器,这样在每个函数调用之前,都要花一些时间来设置这个寄存器。

  9、如果为Apple G5 (PowerPC 970)处理器编译程序时,使用了G5内建的平方根函数,那么性能将有极大的提升。就如大多数针对处理器的优化一样,在编译程序时,也必须进行正确的设置,才可以让编译器尽可能地使用这些新功能。当然,如果程序中不使用平方根函数,或者使用得很少,那对程序在速度上的表现就没太多的帮助。另外,使用这些函数可能会增大可执行文件的大小

  10、64位系统允许应用程序一次直接寻址访问超过4GB的内存,而32位程序被限制在4GB以内,原因是32位寄存器最大只能保存数值2的32次方-1。一旦使用64位的寄存器,程序便可寻址到264,理论上可以访问18PB(18千兆兆字节)的内存,这差不多相当于32位的40亿倍(实际可寻址的内存数,取决于操作系统和相关的物理限制)。

  11、可寻址访问18PB内存,意味着可把数据库、复杂的3D环境,甚至于整个操作系统都放在内存中,这样可比它们在硬盘中不知要快上多少倍。当然,目前世界上的计算机都没有18PB的内存,但一些基于安腾(Itanium)的服务器,内存就有512GB之多,就目前的发展趋势来看,在不远的将来,程序和计算机本身,都将推动对内存的需求量超过这个数字。

  12、目前来说,应用程序也极有可能推动对磁盘空间需求的增长,而64位架构刚好可以寻址更大的磁盘空间,这就使管理更大的磁盘变得简单多了。一如应用程序可寻址访问多少内存一样,磁盘也存在着一些限制,比较说磁盘上能存入多少文件,每个文件的大小有多大等等。

  13、再也不用担心Y2K38等问题了。源于Unix系统对时间的管理方式,很多使用time_t数据类型的32位应用程序,在2038年1月19日,都会碰到类似当年千年虫的问题,这是因为没有更多的位,可以用来继续计数自1970年1月1日以来的秒钟数(某些用于抵押和退休金管理的程序可能会更早地碰到此类问题,如果这些程序要进行许多未来事件的日期处理的话)。可幸的是,在64位系统上,公元292,000,000,000年到来之前,时钟都不会出错。在此须牢记的是,要使用64位库重新编译整个应用程序,以便避开这个小小的“故障”。


其次,需要思考的事

   14、为了充分发挥64位处理器的性能,还必须有一个64位操作系统。当前Linux/Unix操作系统的各种变体层出不穷,包括Red Hat、SUSE、Sun、Turbolinux甚至Apple(Mac OS X)都发布了数款力作,此时对Windows用户来言,他们的选择非常有限。迄今为止,Microsoft也只是发布了Windows XP Professional x64 Edition 和 Windows Server 2003 x64 Edition的英文版。

   15、与大众看法相反的是,64位处理器对加密程序来说,并不会有太大的帮助。据《Secrets and Lies》作者——安全专家Bruce Schneier说法,现今的加密手段已经足够快了,“如果只是从两毫秒减少到一毫秒,有什么意义吗?64位处理器不会对大多数的加密手段带来一个质的改变。”

   16、对于32位和64位系统,是否分别发给用户不同的二进制文件,完全取决于你优化代码的方法。举例来说,只是针对Apple G5而简单重编译的代码,不会在老版本的G4上工作得很好,但如果为了G5处理器特定的功能,而对代码作了修改,你将不得不提供一份单独的二进制文件。解决这个问题的最好办法是,在执行特定于某种处理器的代码之前,先作一个判断,看当前的处理器是否匹配,但这也有不利之处,因为生成的二进制文件将会更大。

   17、可以只使用一种系统来开发多个平台的程序。例如,使用GCC,你可在一个64位的AMD64平台上,同时生成32位x86应用程序和64位AMD64应用程序,生成32位程序时,只需要在编译器中带上“-m32”。

相关的编译器


  18、当为程序速度作优化时,经常不得不牺牲可移植性,这通常意味着硬件生产商提供的编译器比GNU的编译器,能生成更快的可执行代码。“GCC是一款优秀的编译器产品,但生成代码的质量,在很大程度上依赖于对特定处理器的细微调整,”SUSE公司的Jaeger说到,“比如说,在安腾(Itanium)处理器上,Intel的编译器通常能生成更好的代码;但在AMD64处理器上,目前保持最高SPECint值的代码,仍是由GCC编译器生成的。”

  19、在为G5处理器优化代码方面,Apple公司为OS X 10.3操作系统的每个版本,都免费提供了它的Xcode Tools套件。这个开发工具包,包括一个集成开发环境(IDE)、一个用户界面生成器、一个调试器和一个专为G5作过优化的GCC 3.3版的编译器。

  20、如果为Athon 64和Opteron系列作开发,AMD公司推荐使用Microsoft的编译器。Linux用户通过使用GCC,也能得到令人满意的效果。

  21、在安腾(Itanium)系统上,你可使用Intel C++编译器来为那些C/C++源码生成高度优化的64位可执行代码。Intel公司针对Linux和Windows操作系统分别有不同的编译器版本,两者售价均为399美元。这里也有一些第三方的编译器产品,其中有Microsoft、HP、IBM,甚至SGI的,如果Linux用户要使用GCC编译器,最好先看一下第18条。

  22、如果要在UltraSPARC处理器上开发和优化代码,Sun公司提供了Sun ONE Studio开发套件,售价大约一千美元。

  23、在Unix系统上,ILP32(整型int、长整型long、指针pointer)数据模型对64位应用程序不再适用。如果你之前在写程序时,已假定所有的int、long、指针的长度都是32比特,那么现在必须要掉转头来重写一遍,因为此时long和指针的长度已是64比特(LP64)。特定要提醒的是,要仔细检查一切有关int、long、指针的赋值和比较语句

  24、在64位Windows系统上,long的长度依然是32比特,但指针和long long是64位,这被称作LLP64模型

  25、把64比特的指针值转换为32比特的int(或Windows上的32比特的long),将导致严重的后果。特别是在为32位和64位平台书写不同代码时,如果使用通用数据类型,就能避免这个问题。比如说,你正在Windows平台上使用C/C++,如果想存储一个指针值,那么INT_PTR将比int更加好;而在Linux系统上,这种类型是intptr_t。使用此类的通用数据类型将确保变量有足够的比特位来放下指针地址,而不管使用的是什么处理器。

  26、要在常量表达式中指定数据类型。如果你想使一个常量为long,必须清楚地在数值后跟上l或者L,否则,编译器有可能把它当作int来对待。

  27、多留意设备驱动程序。如果你的应用程序是跟随设备驱动程序一同分发,或者与第三方的驱动程序有交互,那么要谨记,代码必须为64位对象而重新编译。当然,如果你或者第三方开发者在写驱动程序时就使用的是ILP32数据模型,那么必须及时更新,以使用LP64或LLP64模型,参见第23和24条。

  28、小心C语言中的符号扩展问题。举例来说,当转换一个unsigned int到64位的unsigned long时,它必须先转换成一个signed int,然后是signed long,最后才能转换成unsigned long。在此期间,任何数值超过2的31次方的int值,将会被系统当成一个负数,而负号也会扩展到因转换成long而新增的32个比特位中,最后被转换成的unsigned long数值,将会比原值大许多。

  29、当从32位到64位时,数据对齐方式也会有所改变。就如一个变量在一个架构上是四字节对齐,而到了另一个上面就成了八字节对齐。一些程序员为了避免这个问题,只是简单地使用了一些结构,然而,对那些需要创建动态结构或者执行一次就过的操作来说,知道此时如何处理可变对齐方式是非常重要的。一个解决方法是,避免把数据大小和偏移量编码成一个常量,而应使用C语言中的sizeof操作符来确定数据大小。

  30、如果你的64位程序将会运行在Linux系统上,那么系统中必须装有64位库,通常这些库被安装于以/lib64结尾的路径下,以便与32位库区分开来。(注意,在DEC Alpha和Itanium处理器上,没有32位库,而64位库就在/lib目录下。)

  31、Windows XP Professional x64 Edition和Windows Server 2003 x64 Edition允许运行32位及64位应用程序;然而,它们只有64位库所有32位指令都通过被称为WOW64的x86仿真层传递,它负责把相应指令转换成对64位库的调用

最后,还是必须向前冲!


   32、在为64位处理器优化软件时并不难,所需做的仅是知道什么要注意、什么要避免。唯一要记住的是,也许程序移植到64位平台之后,并不会有性能上的提升,但总好过什么都不做。

你可能感兴趣的:(Win32,VC++,64位编程)