迁移到 SMP
对于某些人来说,SMP(对称多处理)代表着日常工作;对于另一些人来说,则代表着对性能提升的期望。Windows 9x 用户无需费心,因为该平台每个主机仅支持一个 CPU。Windows NT 在多处理器上的扩展性不如其他操作系统。2.0 Linux 内核系列提供了一些 SMP 支持,但 2.2 系列的支持要好得多。Linux 扩展性良好,最多可达 16 个 CPU。除此之外,Linus Torvalds 尚未决定提交,因为为了使 Linux 能够良好地扩展到更多,所需的权衡意味着会牺牲小型系统的性能。对于大规模 SMP,Sun 的 Solaris 在 64 个 CPU 上表现良好。SGI 和 IBM 也提供大规模 SMP 产品。本文介绍了在 x86 架构的 Linux 下运行 SMP 的入门知识。
有一段时间,我一直想尝试 SMP Linux。当 2.2 内核出现,而我家庭网络中的另一次硬件交易使我的桌面电脑变成了一台 486(我的妻子得到了 K6-200,以搭配她的新键盘,因为集成指针需要了房子里唯一的 PS/2 鼠标端口)时,我决定用一些不同的东西来替换这台 486。
在渴望地关注多 CPU Alpha 系统和 Intel P6 以及奔腾 II 主板的同时,我决定以较低的成本构建一台 SMP 机器,但使用新零件。Alpha 和 Ultra-SPARC 系统的价格没有达到我希望支付的低价,而且由于我有一个 Baby AT 机箱,奔腾 II 主板无法与我可以回收利用的硬件配合使用。这样就只剩下 Baby AT 尺寸的 P5 和 P6 主板。我没有找到价格吸引人的全新 P6 主板,但我确实找到了一些可以使用的 P5 主板。
在进行了更多研究之后,包括回顾了 Slashdot 上关于 SMP 的过去讨论,我选择了 Tyan Tomcat IV 1564D,它采用了 Intel 430HX 芯片组。这款主板可以使用一个或两个(最好是匹配的)奔腾处理器,从 P5-75 到 P5-233 MMX。它还可以容纳高达 512MB 的 RAM,分布在八个 72 针 SIMM 插槽中,使用奇偶校验或非奇偶校验内存设备。它具有典型的板载 I/O,包括两个 IDE、两个串行、一个并行、一个 PS/2 鼠标端口和 USB。它也可以使用非 Intel CPU,但只会支持一个,因为在 AMD Athlon 进入市场之前,Intel 实际上控制了 x86 世界中的 SMP,而支持任何 SMP 的非 Intel 产品都不使用 Intel 信号。
我从 Motherboard Express 购买了两个 P5-233 MMX CPU 和主板。我从 Crucial Technology 添加了 128MB 的快速页面奇偶校验内存。
为了正常运行,SMP 应与线程安全的 libc(例如 glibc2)结合使用。我运行 Debian GNU/Linux 2.1 版本,该版本的所有库和实用程序都是最新的,可用于 SMP。Debian 的软件包集还包括 libc5 库,用于编译为需要 libc5 的软件。经过近三年的持续使用,我发现 Debian 是最令人满意的 Linux 发行版。我在执行升级和保持更新方面没有遇到任何麻烦。软件包管理器不需要手动下载,并且仅检索保持最新状态所需的软件包。(我之前和并行使用 Red Hat(直到 5.2 版本)的经验发现 RPM 中或附近没有内置此类功能。如果存在,我错过了它。)
某些驱动程序也需要更新才能在 SMP 内核下正确运行,因为必须进行额外的锁定以减少系统资源的争用。4Front Technologies 的 OSS 声卡驱动程序有单处理器和 SMP 版本。PCMCIA Card Services 可能需要重新编译。大多数其他驱动程序都位于内核源代码树中,因此在编译新内核后,它们应该可以与 SMP 一起工作。
在用新的 Tyan 单元替换 486 主板后,Linux 立即启动。我已经运行了 2.2 内核,因此将其重新配置为 SMP。(有关如何执行此任务的更多信息,请参阅 Linux 内核源代码的 Documentation 子目录中的 smp.txt。)
我编译的第一个 SMP 内核无法正常工作。从我阅读的 4Front Technologies 的 OSS 声卡驱动程序和内核本身附带的文档中,我意识到依赖项没有正确构建。我将 .config 文件保存在其他地方,执行了 make mrproper 以清理内核源代码树,然后恢复了 .config 文件。在执行 make oldconfig 后,我再次构建并安装了 SMP 内核。在下次启动时,我看到了额外的启动消息,表明两个 CPU 都已开始运行。2.2.7 内核与 Debian 2.1 附带的实用程序结合使用,将每个进程的 CPU 使用率报告为可用总量的百分比。一个占用所有 CPU 的进程将显示 50% 的使用率。
为了演示第二个 CPU 提供的性能差异,我使用 Linux 内核编译、distributed.net rc5des 加密破解器和 POV-Ray 的光线追踪器进行了基准测试(见表 1)。所有这些都直接利用了多个 CPU。POV-Ray 还可以直接使用分布在网络上的 CPU。所有数据均为三次运行的平均值。
在同一内核下运行时,重新编译单处理器 2.2.7 内核耗时 376.91 秒。在同一 SMP 内核下运行时,重新编译 SMP 2.2.7 内核耗时 395.04 秒(仅在一个 CPU 上运行时),比单处理器编译时间长 5%。在两个 CPU 上运行时(make -j 2 bzImage),编译耗时 302.77 秒,为单处理器编译时间的 80%。
对于 POV-Ray,我使用了基准测试源文件 skyvase.pov,可从 POV-Ray 的网站获得。我在 xpvmpov 的默认分辨率 320x240 下运行它。SMP 运行时间为单处理器运行时间的 72%。
rc5des 代码破解器在单处理器和 SMP 内核下的基准测试速度几乎相同。在实际操作中,它将根据需要运行在尽可能多的 CPU 上,或自动检测 CPU 数量。我认为两个内核之间的性能差异较小,是因为它包含为获得最佳性能而进行的优化。它很可能尽可能多地在 1 级 (L1) 缓存中运行。
SMP 可能会在其他方面提高性能。GUI 操作可能会受益于让 X 服务器在一个 CPU 上运行,而应用程序在另一个 CPU 上运行。任何在一个 CPU 上运行良好但可以利用另一个 CPU 的程序都将从使用 SMP 中受益。我现在在我拥有的所有运行 Linux 的 CPU 上运行 SETI@home 客户端。
L1 和 L2 缓存的数量和速度都很重要。RAM 速度也很重要。Intel P5-233MMX 包含 32KB L1 缓存,分布为 16KB 代码缓存和 16KB 数据缓存。我妻子的 AMD K6-200MMX 包含 64KB L1 缓存,分布为 32KB 代码缓存和 32KB 数据缓存。对于某些任务,它的性能比一个 Intel P5-233MMX 更快。Intel 奔腾 Pro CPU 同时具有板载 L1 和 L2 缓存,L2 缓存高达 1MB。奔腾 II CPU 的板载 L2 缓存高达 2MB。新的 CPU 也以更快的速度运行其缓存。CPU 上更多的缓存意味着外部缓存和主 RAM 的争用更少,这意味着更高的性能。CPU 通过支持芯片组相互协作以维护缓存一致性,以便它们始终保持 RAM 的准确视图。
将进程锁定到一个 CPU,特别是当该进程的代码和数据适合 L1 缓存时,也可能会提高性能。Linux 对此的支持不如更成熟的 UNIX 变体那样完善,但可能很快就会实现。
我需要 SMP 来完成我的工作吗?不需要。单个 200MHz P5 级处理器可以充分执行我想执行的任务。对于大多数任务而言,足够的内存(包括 RAM 和缓存)比处理器数量对性能的贡献更大。我从中获得乐趣了吗?哦,是的。
