在 OpenPower 上兜兜风,第 1 部分: 探索 POWER5 上的 64 位开发

您的代码的可移植性究竟如何?

OpenPower™ 程序提供了对运行 64 位 Linux® on POWER5™ 处理器的服务器进行自由远程访问的能力。在 OpenPower 上兜兜风 系列文章的第 1 部分中,作者 Peter Seebach 将介绍获得系统访问能力和为其编译应用程序(32 位和 64 位)的过程。他还特别关注那些没有 root 特权的 “客户” 软件开发特有的问题 —— 有些东西对于大部分 Linux 用户来说以前从未遇到过。

Peter Seebach, 自由作家, Plethora.net

Peter Seebach1999 年,Peter Seebach 首次在 Alpha 上测试了自己的代码已为 64 位环境做好了准备。对于这个问题来说,再仔细也不过分。当然,那些代码都可以工作,因此让我们开始吧。



2010 年 9 月 21 日

我的编辑曾经说过可能希望编写有关 OpenPower 程序的文章,这样的话平常不怎么好奇的人们也许会对此有足够的好奇心来尝试它。作为一个新硬件的爱好者,实际上我并没有为此做些什么,因此我决定签约撰写这篇文章。尽管在得到回复之前花了几天时间,但是整个签约过程还是非常顺利。另外一方面,我的帐号已经创建并配置好了。

用户对于 OpenPower 系统的访问都是通过 ssh 来进行的。您需要将自己的公钥(如果现在还没有公钥,可以使用 ssh-keygen 来生成)提供给 OpenPower 项目管理员,他们会为您进行安装。我为这个项目创建了一个新密钥,因为这种方式看起来更加简单:

清单 1. 为 SSH 生成公钥
$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/seebs/.ssh/id_rsa): /home/seebs/.ssh/openpower
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/seebs/.ssh/openpower.
Your public key has been saved in /home/seebs/.ssh/openpower.pub.
The key fingerprint is:
62:53:9b:94:89:1a:af:06:38:18:fb:9a:ec:92:40:dc seebs@vash.cel.plethora.net

“openpower.pub” 密钥是转发给 OpenPower 项目管理员的文件。他们发给我一条提示,通知我的帐号已经在 “ibmop720.osuosl.org” 机器上配置好了,我可以使用 “ssh -i openpower seebs@ibmop720.osuosl.org” 来登录这个系统。(实际上第一次工作时出现了一个输入错误,影响了它的工作;我之后的查询是在 1 个小时之后才得到响应的。)

浏览系统

生平第一次,我有点喜欢 top(1) 在其报告的数字中使用逗号了,如果没有逗号的帮助,将很难对这些庞大的数字进行解析:

清单 2. 这个 ferrite 核心中有多少东西?
top - 15:46:39 up 65 days, 59 min,  4 users,  load average: 0.00, 0.00, 0.00
Tasks: 116 total,   1 running, 115 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.0% us,  0.0% sy,  0.0% ni, 100.0% id,  0.0% wa,  0.0% hi, 0.0% si
Mem:  32033412k total, 31313732k used,   719680k free,  4494228k buffers
Swap:  1050616k total,      572k used,  1050044k free, 21668944k cached

是的,它有 32GB 内存。65 天的运行时间没有什么特殊的,不过这证明了这台机器没有出现任何随机崩溃或其他故障。在我进行的简单探索中,我还发现这个系统的负载并不高。加载单个编译进程产生的负载情况与我们期望的情况类似:大约是 12% 的负载。这是一个非常灵活的系统,非常适合进行开放测试的情况;除非您正在执行大量并行批处理作业,否则就不用担心其他用户对您自己的工作会造成什么影响。

当然,判断系统对于 Internet 连接的响应能力非常困难,这是因为网络延时的原因。使用典型的数据集对您感兴趣的特定算法真正进行一下基准测试会告诉您需要了解哪些内容。

关于编译环境……它是一个 Linux(具体来说,是 SuSE Enterprise Server 9)系统。它安装了非常多的包(不过没有 Web 服务器)。我发现缺少的几个包(例如 svgalib)都是对于远程访问服务器来说无关紧要的一些包。

如果您之前曾经从事过 Linux (或其他任何 UNIX®)系统上的开发,那么您会非常熟悉这个环境。在共享系统上您获得的是一个非 root 帐号,如果您需要安装自己的软件包时可能会增加一些需求,当要安装的包具有一些依赖性时更是如此,不过这并没有什么问题。


编译应用程序

在新系统上首先尝试的东西之一是编译应用程序。我喜欢的一个测试用例是 NetPBM,它很庞大并且具有非常丰富的有趣特性,因此是一个很好的测试用例。从一个下载服务器上获得 NetPBM 10.34,并开始试验它。NetPBM 是一个非常不错的测试用例:它使用了其他一些库,具有各种可移植的数值处理代码。尽管您可能会希望使用自己的代码来进行大量图像处理过程,不过 NetPBM 的确可以用作一个非常好的用于测试的样本集。

NetPBM 的 “configure” 脚本不是 autoconf,不过同样工作良好。好吧,应该说在大部分情况下都可以很好地工作;它会猜测有哪些地方存在问题。对于编译过程来说,您立即会注意到的问题是链接某些共享库时出现错误。诊断信息会显示自己出现了什么问题:

清单 3. 出现了什么问题?
/usr/lib/gcc-lib/powerpc-suse-linux/3.3.3/../../../../powerpc-suse-linux/bin/ld:
Error: The symbol `pm_error' has a R_PPC_REL24 relocation, that means 'libpm.o' was
compiled without -fPIC.

这是一个很好的错误消息。我们的第一反应是打开 Makefile.config(保存编译设置的文件),查找关于设置标记位置的提示。浏览 makefile 会显示:

清单 4. 线索
# We have seen -fPIC required on IA64 and AMD64 machines (GNU
# compiler/linker).  Build-time linking fails without it.  I don't
# know why -- history seems to be repeating itself.  2005.02.23.

	CFLAGS_SHLIB =
	# Solaris or SunOS with gcc, and NetBSD:
	#CFLAGS_SHLIB = -fpic
	#CFLAGS_SHLIB = -fPIC
	# Sun compiler:
	#CFLAGS_SHLIB = -Kpic
	#CFLAGS_SHLIB = -KPIC

非常确信,增加 “-fPIC” 可以解决这个问题,这正是错误消息建议的(也是 Makefile 中有关其他两个常见的 64 位体系架构的注释给我们的提示)。(好的,现在添加这个选项,并运行 “make clean” 删除旧对象文件。)其他类似问题也都是与 svgalib 支持代码(如果您在 svgalib.o 的位置上输入 “none”,就可以防止这个问题;默认情况下,假设它在 Linux 系统上都是可用的)和 X11 的一些怪癖有关,可以将 /usr/X11/lib/libX11.so 作为 libX11.so 的位置来解决有关的错误。

将 netpbm 安装到您自己的根目录非常容易,不过在这样做之后,netpbm 二进制文件就无法找到自己需要的共享库了。解决方案是将您的库目录放到 LD_LIBRARY_PATH 环境变量中。

当您不是 root 用户时应该做些什么

那些习惯只使用 root 特权来安装软件的用户可能会发现没有 root 特权之后安装软件变得有点怪异。通常,处理这种问题的最好方法是将自己的根目录作为另外一个类似于 /usr 或 /usr/local 的前缀,下面有自己的 bin 和 lib 目录。对于使用 autoconf 的应用程序来说,可以使用 “configure --prefix=$HOME”。将环境变量 LD_LIBRARY_PATH 设置为 “$HOME/lib”;举例来说,如果您正在使用 bash,可以将 “export LD_LIBRARY_PATH=$HOME” 添加到您的 .profile 文件中。这样可以处理大部分程序的问题。

通常,安装和使用支持库应该不会需要 root 权限。也有一些特殊程序和库会需要 root 权限,不过比较少。举例来说,如果没有 root 特权,您就无法编译 Apache 的 suexec 程序。然而,如果您所做的就是构建一个运行在自己的用户 ID 下的专有 Web 服务器,那么就不需要 suexec 了。

不使用 root 特权来安装软件对于长期使用桌面 Linux 和服务器管理的用户来说会有些不知所措,不过这对于大部分软件来说都不是什么大问题。


什么是 long long 类型?

POWER5 体系结构天生就是 64 位的。不幸的是,并非所有的软件都可以充分利用这个优点;实际上,默认编译器选项生成的就是 32 位的代码。相同系统上具有很多库的 64 位和 32 位版本,用来链接到 64 位和 32 位二进制文件上,这种问题看起来似乎非常复杂,不过随着 AMD 对 x86 处理器体系架构的 64 位扩展的流行,开发人员已经相当熟悉这一情形了。由于天生能够支持原来的 32 位代码,这可以使系统管理员的工作变得更加轻松。不过对于开发人员来说,这的确使问题变得有点复杂。

很早之前,Henry Spencer 就警告过 C 程序员,不要抱有 “整个世界都将是 VAX 的” 这样的想法。最近几年,更多辩论已经相信 “整个世界都将是 386”。具体对 C 开发人员来说,在 20 年的时间之内,人们学习 C 语言所使用的主要目标平台都是 32 位的系统,其中大部分数据类型都是 32 位的,指针类型也是 32 位的,最常用的整型大小也是 32 位的(正如您猜测的一样)。

当 64 位体系架构开始出现时,一个问题也随之出现了:很多依赖于 long 类型的代码都是 32 位的,而有些依赖于 long 类型的代码却是更大的类型。本身支持 64 位类型的系统通常都采用一种称为 “LP64” 的模型,其中 long 类型和指针大小都是 64 位的。本身支持 32 位类型的系统通常都保留 32 位的 long 和指针,不过这些系统引入了一个新类型 “long long”,它是 64 位的。这个类型与早期 16 位硬件上的 32 位类型一样,实际上是通过编译器所生成的复杂代码而进行处理的。要了解有关 C 类型历史的更多内容,请参看 developerWorks 上最近这篇 C types article

作为一个开发人员,这对您意味着在 64 位硬件上可能会有一些意外发生。有些程序仍不能在 64 位环境中工作,因为它们的开发人员假设所有体系结构都与他们的一样。(这个问题并不是 Power 体系结构特有的;相同的程序通常在 x86_64 环境中也会失败。)即使在 64 位的 POWER 系统上,默认编译选项也都是为旧式 32 位应用程序而设计的。

构建支持 64 位的应用程序并不一定就会改进应用程序的性能。不过这通常都非常有用,因为这为那些需要超过 4GB 数据的应用程序提供了更大的地址空间。然而,所有的 64 位对象都会占用更多空间,更多缓存空间,更多内存带宽……简而言之,处理 它们需要更多工作。

在某些情况中,这会导致令人惊奇的结果,本地 64 位代码的运行速度在相同的处理器上运行会比本地 32 位代码速度更慢!尽管 64 位处理器通常都具有足够的数据总线来保证一切运行良好,不过在需要切换成 64 位数据时,要移动的数据大小依然是双倍的。有关总线架构的最近标准规范文章 讨论了这方面的一些问题;原始带宽和延时是影响它的两个主要因素。

总体来说,64 位模式往往会对性能造成一点损害。另外一方面,如果您要处理大量数据集(数据挖掘或数据库操作),访问更大的数据缓存,那么对于 64 位模式来说这非常容易。当我们在谈论切换到 64 位对象时所引起的性能降低时,其数量级甚至不如您将数据第一次交换到磁盘上所引起的性能降低的程度,因为 4GB 的地址空间远远不够。

对于在那些过于庞大以至于 32 位类型不能够可靠表示的对象上进行大量整数数学计算来说,使用 64 位模式可能会带来一些优点;本地 64 位数学算法指令比使用 32 位操作进行的仿真操作速度更快。

实际上,开发人员碰到这种问题时,大部分时间都花费在了获取各个库的正确版本上。OpenPower 系统上所有安装的库都有 32 位和 64 位的版本。

将 NetPBM 编译成 64 位

首先声明一点:我不确定自己这样做的方法是否是最好的方法。我只是不断进行一些尝试,直至一切可以正常工作为止。NetPBM 编译系统在 32 位模式中几乎可以完美地工作。在 64 位模式中,这就有点困难了。我们要做的第一件事情是将编译器和链接器换成 64 位模式;gcc 手册会介绍这个问题。将 “-m64” 添加到 CFLAGS 中就可以了。但是要确定如何提供一个在所有情况中都会使用的链接器标记却并不这么简单;我最后决定将 LD 定义修改成 “$(CC) -m64”。这样只要编译器不能找到支持库的正确(64 位)版本,就会向我提示信息。其他包也许可以更加简单地实现这种功能。

很多开发人员支持程序在挑选 “默认值” 时都有一些偏好(例如 /usr/lib),因此如果它们可以在 /usr/lib 中找到某个库,那么就不会继续考虑是否可以在其他地方也能找到这个库的问题。举例来说,我修改了 Makefile.config 中的几行内容来引用这些库的 lib64 版本:

清单 5. 在 /usr/lib64 中查找库
TIFFLIB = /usr/lib64/libtiff.so
JPEGLIB = /usr/lib64/libjpeg.so

在 lib64 中缺少了几个符号链接,这让事情变得更加复杂了。通常,在 Linux 上共享库都有主版本号和次版本号,还有一些符号链接指向更通用的名字。有关共享库版本的更多信息,请参看 developerWorks Linux 专区中 有关共享库版本的文章。举例来说,在 OpenPower 系统上 /usr/lib 中 libpng 的文件如下:

清单 6. libpng.so
$ ls -l libpng.so*
lrwxrwxrwx  1 root root     11 2006-05-30 16:48 libpng.so -> libpng.so.3
lrwxrwxrwx  1 root root     18 2006-05-25 11:06 libpng.so.2 -> libpng.so.2.1.0.12
-rwxr-xr-x  1 root root 213468 2002-08-05 05:35 libpng.so.2.1.0.12
lrwxrwxrwx  1 root root     17 2006-05-25 11:07 libpng.so.3 -> libpng.so.3.1.2.5
-rwxr-xr-x  1 root root 198626 2004-06-30 18:55 libpng.so.3.1.2.5

相比较而言,在 lib64 目录中,缺少了 libpng.so 符号链接。简单地指定 “-lpng” 并不能正常工作;Makefile.config 中正确的设置应该是 “PNGLIB = /usr/lib64/libpng.so.3”。

通过一些这种修改之后,除 SVG(Scalable Vector Graphics)转换之外的所有东西都编译好了;SVG 转换依赖于一个 XML 解析库,库文件是通过编程运行 “xml2-config --libs” 获得的,不幸的是,没有什么方法能够告诉它提供 64 位库的答案。尽管我们可以手工重写这个工作。

结果就编译出了 64 位的 NetPBM。像往常一样,file 命令是检查结果的首选方法:

清单 7. file 命令的输出结果
np64/bin/pamtotiff: ELF 64-bit MSB executable, cisco 7500, version 1 (SYSV),
for GNU/Linux 2.4.21, dynamically linked (uses shared libs), stripped
np/bin/pamtotiff:   ELF 32-bit MSB executable, PowerPC or cisco 4500, version 1 (SYSV),
for GNU/Linux 2.2.5, dynamically linked (uses shared libs), stripped

如上所示,新版本并不完全比 32 位的快;不过,netpbm 库有时会被其他一些希望以一种可移植格式来导出数据的应用程序使用, 对于其他真正需要以 64 位模式运行的程序,64 位版本的库使其成为可能。


结束语

本文对 OpenPower 项目进行了简介,并了解了在移植到 64 位 POWER 系统上时所面临的问题。下一篇文章将更深入介绍在移植到一种新体系架构上时要处理的问题。

细心的读者可能已经注意到一个问题:严格来说,本文中介绍的大部分内容可能在 PowerPC® 系统(例如 G5 Power Mac)上都已经做过了。情况的确如此。然而,自由访问 64 位 Power 体系架构机器并不是所有人都可以轻易做到的事情。另外,如果您正在考虑购买一个很大的服务器,那就最好在一个 8 路的 POWER5 机器上先测试一下自己的代码,而不是在一个 4 路 G5 上进行测试。最后一件事情,但却是不容忽视的事情:您没法忽略价格的因素。

参考资料

学习

获得产品和技术

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Linux
ArticleID=210886
ArticleTitle=在 OpenPower 上兜兜风,第 1 部分: 探索 POWER5 上的 64 位开发
publish-date=09212010