原文: Hunting Down Performance Bottlenecks
在本博文中,我想就 ARM® DS-5™ Streamline 性能分析器 如何帮我分析 CPU 循环耗费在某些并行基准代码中的什么地方,分享我的经验。
我曾研究称为 MontBlanc 的研究项目,其旨在使用待发布的 ARM(移动)技术构建 HPC(高性能计算)原型系统。我负责性能分析和 MPI 通信库的优化。MPI 是分布式内存消息传递应用程序的实际标准,如在集群上或超级计算机上运行并通过外部网络互连进行通信的大型并行应用程序。
不久之前,我遇到了搞清楚 CPU 循环耗费在微基准中的什么地方的问题,该基准测量 MPI 通信库的端到端的延迟。
该特定基准是简单的乒乓测试。它包括两个过程 - 我们称它们为乒和乓。乒过程通过调用 MPI_Send 将消息发送给乓过程,然后通过调用 MPI_Recv 等待回复。乓过程调用同一 MPI 函数,但顺序相反,即其等待来自乒的消息,并在它收到时立即发回确认。乒过程测量从乓获取确认所花费的时间。这些步骤在紧凑的循环中进行重复,通常是几百倍次,以计算平均往返延迟。
我有两个运行该基准的 SECO 板(见图 1)。每个 SECO 板支持带 ARM Cortex™-A9 MP 双核的 NVIDIA Tegra2芯片。它们具有直接通过单根网线连接的集成千兆位以太网端口。该板还具有连接到本地网络的第二个 100Mb 以太网端口。
图 1 测试机架中的两个 SECO 板
虽然基准本身很简单,但在运行时 MPI 库和 Linux 内核内会发生很多操作,以通过以太网连接发送和接收消息。MPI 依赖这些板上的常见 TCP/IP 协议。每个 MPI 发送/接收调用通过系统调用实际嵌入 Linux 内核内,然后内核网络子系统进行所有必要的预处理和后处理来将该应用程序数据转换成以太网帧,反之亦然。
与参考千兆位以太网连接系统相比,我看到我在 SECO 板上运行测试时的延迟数相当高。我的任务是在消息软件堆栈中制定优化,以减少高延迟。为完成任务,我必须找出耗费大部分循环的地方,即堆栈的哪个组件负责大部分开销。
我怀疑罪魁祸首是该内核中的 TCP/IP 处理,但我需要证据进行证明。我必须在乒循环中的紧凑发送/接收循环期间衡量内核产生的 CPU 利用率。DS-5 Streamline 使该测量相当简单和直观。
我在我的台式机的首个 SECO 板和 DS-5 GUI 上启动了 gator 守护程序。我点击 Streamline 数据窗口中的“捕获选项”按钮,以打开“捕获和分析选项”对话框(见图 2)。在该窗口中,我输入连接地址(即 seco001:2001,其中 2001 是我的 gator 守护程序侦听的端口号)。我还选择“高分辨率时间线”选项来获取我的短基准运行的详细结果。
图 2 捕获对话框(单击以放大)
接着,我在基准源代码中注明内循环,以将其标为 Streamline 视图内的特别兴趣区。Streamline 提供了标记该代码中的特定区域的仪器 API。注释显示为时间线视图中的可见标记,以帮助查找和分析应用程序的各种运行时阶段。
这是我的实验的所有必要设置。我点击“开始捕获”按钮,并开始运行我在 SECO 板(使用单独的 ssh 会话)上的基准。完成基准后,我点击“停止捕获”。DS-5 在几秒钟内传输和处理该跟踪文件。默认时间线视图出现在我的屏幕上,如图 3 所示。
图 3 Streamline 时间线视图(单击以放大)
接着,我将时间线视图限制在我的基准的内循环内,具体如下所示。我选择了窗口底部的进程列表中的“乒乓”以筛选任何其他进程活动的结果。然后,我将时间线分辨率更改为 5ms 以获取更详细的执行视图。我将卡尺放在时间线上的黄色标记上,以筛选掉发生在我的兴趣区外的任何活动。请注意,通过卡尺进行筛选会影响所有 streamline 视图。因我在源代码中的注释,此处出现标记,即它们在我的基准内的内循环开始和完成时显示。我还“打开了”CPU 活动栏,以显示每个 CPU 核心的单独视图。如图 4 所示,很明显,运行内循环时乒乓使用核心之一的全部 - 而其他核心实际为空闲状态。
图 4 时间线视图重点关注我的兴趣区(单击以放大)
为弄清楚乒乓进程内正在发生的操作,我切换到“调用路径”视图(见图 5)。在这里,我可以立即看到 65% 以上的时间乒乓在内核内执行 - 但究竟在内核内的什么地方?
图 5 调用路径视图(单击以放大)
下一步是要从 vmlinux 文件将内核符号加载到 Streamline 中。我重建了调试内核 (CONFIG_DEBUG_INFO=y),以将调试符号添加到 vmlinux 文件中。然后,通过使用“捕获与分析选项”对话框,我单击“添加 ELF 映像”并为该内核找到 vmlinux 文件,然后重新分析该数据(见图 6)。
这表明涉及了众多内核功能,但使用最频繁的一个是“getnstimeofday”(约占示例的 21%),由 TCP/IP 框架(滑动窗口流控制)进行调用。这证实了我原来的假设,即时间主要用于处理 TCP/IP 网络堆栈。
基于这些发现,我将 OpenMPI 库中的基于 TCP/IP 的“重量级”默认传输层实施替换为“轻量级”以太网直接传输层实施(称为 OpenMX)。这使端到端延迟减少了近 40%!
综上所述,DS-5 Streamline 使您的应用程序性能检测变得简单,即使您仅对特定运行时阶段感兴趣 - 您可以对您的源代码进行标注以标出各个区域 - 即使您有兴趣同时分析由您的代码触发的用户空间和操作系统活动。在该具体项目中,我能够找到基准中的瓶颈,然后通过简单更换一个库代码块显著提高其性能 - 非常令人满意的结果!
ARM 高级工程师 Gabor Dozsa。 他是 ARM 研发部的成员,关注未来的 ARM 技术和应用程序。最近,他一直致力于高性能计算系统中的库代码的性能分析和优化。