检测线程化应用的内存带宽饱和度

分类:
标签:

摘要

内存子系统组件在很大程度上影响着应用的性能特征。现在,随着越来越多的线程和进程共享有限的高速缓存容量和内存带宽等资源,线程化应用的可扩展性受到了极大限制。内存密集型线程化应用在运行多个线程时可能会出现内存带宽饱和的问题。在这种情况下,线程化应用将无法像预期一样扩展,性能也可能有所下降。本文介绍了在线程化应用中检测内存带宽饱和度的技巧。

本文是《英特尔® 多线程应用开发指南》系列文章中的一篇,旨在为开发人员开发适用于英特尔® 平台的高效多线程应用提供指导。

背景

鉴于当前的处理器集成有更多的核心和高速缓存,它们与内存子系统组件相比频率更高,速度更快。每芯片上内核数的不断增加为高速缓存容量和内存带宽带来了巨大的压力。最终,最大限度提高每枚内核对可用高速缓存和内存带宽的利用率成为开发向前扩展应用的根本。如果系统无法足够迅速地将主内存中的数据传输至内核,那么内核在等待数据时便会处于闲置状态。计算过程中的闲置内核是对资源的浪费,将导致总计算执行时间延长,浪费多核心配置的部分优势。

当前基于 Nehalem 架构的英特尔® 处理器从传统的前端总线 (FSB) 解决方案迁移至非统一内存访问/架构 (NUMA) 模型,增加了内核可用的内存带宽大小,减少了上文提到的内存饱和现象。图 1 描述了从 FSB 到 NUMA 的迁移。


图 1. 从 FSB 到 NUMA 的迁移。

任何并行应用达到带宽饱和的明显症状均是停止扩展。换句话说,一个应用的可用内存带宽一旦达到饱和,该应用便无法有效扩展至更多线程或内核。不过,导致多线程应用不再扩展的原因有很多,其中部分性能妨碍因素包括线程开销、同步开销、负载不平衡和不适当的粒度等。英特尔® 线程档案器经过专门设计,可有效识别应用层面的此类性能问题。

以下结果是使用不同数量的线程执行 STREAM 5.6 性能指标评测所得到的数据(只列出了 Triad 得分)。

功能

频率(MB/秒)

平均时间

最短时间

最长时间

1 条线程

Triad:

7821.9511

0.0094

0.0092

0.0129

2 条线程

Triad:

8072.6533

0.0090

0.0089

0.0093

4 条线程

Triad:

7779.6354

0.0096

0.0093

0.0325


从以上结果中不难看出,STREAM 在该特定平台(单插槽英特尔® 酷睿™ 2 四核处理器架构系统)上并未因拥有更多线程而受益。深入剖析可以发现,虽然双线程版本的 Triad 得分有些微提高,但四线程版本的性能比单线程版本还要低。

图 2 列出了英特尔线程档案器对性能指标评测的分析结果。时间轴 (Timeline) 视图表明,所有线程均实现完美平衡,没有同步开销。虽然英特尔线程档案器是一款识别应用层面线程性能问题的强大工具,但它无法检测出线程化应用的内存带宽饱和度。


图 2. 英特尔线程档案器的 STREAM 性能指标评测(使用四条 OpenMP* 线程)时间轴视图。

建议

英特尔® VTune™ 性能分析器和性能调试实用程序 (PTU) 与基于事件的采样功能相结合,可帮助开发人员测量应用带宽的使用情况,并与系统上的最高可用(或理论)带宽进行对比。基于事件的采样功能需要依赖由处理器支持的性能监控单元 (PMU) 来实现。

VTune 分析器和 PTU 可帮助开发人员使用 EBS 功能估算某具体应用的内存带宽使用情况。在英特尔® 酷睿™ 微架构上,CPU_CLK_UNHALTED.CORE 和 BUS_TRANS_MEM.ALL_AGENTS 性能事件可用来估算内存带宽。

  • CPU_CLK_UNHALTED.CORE 事件可计算内核非停机状态下的内核周期数。内核运行 HLT 指令时将进入停机状态。
  • BUS_TRANS_MEM.ALL_AGENTS 事件可计算总线上任何代理程序发起的活动数量。如果系统中的各路处理器均连接至不同的总线,那么该数值只代表处理器所在总线上的活动数量。

对于采用英特尔酷睿 2 处理器的系统,可使用以下公式来计算内存带宽:

(64 * BUS_TRANS_MEM.ALL_AGENTS * CPU 频率) / CPU_CLK_UNHALTED.CORE


图 3. VTune 分析器对四线程 STREAM 性能指标评测的 EBS 分析结果。

图 3 列出了使用四条线程进行 STREAM 性能指标评测的 EBS 结果。使用上面的公式,可以估算出 STREAM 内存带宽的使用情况为 7.6Gb/秒。

内存带宽 = (64 * 1,419,200,000 * 2.9GHz) / 35,576,000,000 = 7.6GB/秒

STREAM 报告的可容忍 Triad 得分是 7.7GB/秒,由此可看出基于 VTune 分析器的计算方法很合理。我们选择 STREAM 性能指标评测的目的是展示如何通过使用 EBS 测量的内存带宽大致估算指定系统的可用内存带宽。

如果应用在添加了更多线程时无法进行扩展以充分利用现有内核,并且英特尔线程档案器没有如上所述显示任何应用层面的线程问题,那么以下三步操作可帮助用户判断某具体应用的可用内存带宽是否已达到饱和:

  1. 执行 STREAM 或类似的性能指标评测,了解目标系统上的可持续内存带宽。
  2. 在 VTune 分析器或 PTU 下运行目标应用,并使用 EBS 功能收集适当的性能计数器。对于英特尔酷睿 2 微架构而言,这些事件是 CPU_CLK_UNHALTED.CORE 和 BUS_TRANS_MEM.ALL_AGENTS(公式 1)。
  3. 将 VTune 分析器测量的内存带宽数据与在第 1 步中测量到的可持续和可用内存带宽进行比较。如果应用的可用带宽即将达到饱和,那么该应用不会再扩展至更多内核。
一般来说,受限于内存的应用程序(性能受到内存访问速度的限制)不会因拥有多条线程而受益。

使用指南

英特尔® 酷睿™ i7 处理器和英特尔® 至强® 5500 系列处理器被称为带“非内核”部件。“非内核”是处理器中位于所有其它独立内核外部的组成部分。例如英特尔® 酷睿™ i7 处理器拥有四枚共享一个三级高速缓存和一个内存接口的内核。其中,三级高速缓存和内存接口便视作非内核部分(参见图 4)。

VTune 分析器和 PTU 均不支持由处理器非内核部分触发的事件采样行为,必须使用其它方法测量内存带宽。用于测量内存带宽的相关性能事件并不是像常见 VTune 分析器或 PTU 模式那样使用 EBS 功能进行采样,而是使用基于时间的采样功能进行计算。这测量的是指定时间范围内整个系统的内存带宽,而无法估算具体功能、进程和模块的带宽使用情况。


图 4. 简化的四核 Nehalem 处理器结构图。

上文给出的公式可用来测量英特尔酷睿 2 架构系统上任何应用、模块或函数的内存带宽使用情况,但同样具备非内核部件的基于酷睿 2 的英特尔至强多路处理器除外。在 Nehalem 架构系统上测量内存带宽的基本公式如下:

内存带宽 = 1.0e-9 * (UNC_IMC_NORMAL_READS.ANY+UNC_IMC_WRITES.FULL.ANY)*64 / (挂钟时间,以秒计)

更多资源

如需更全面地了解编译器优化,请参阅优化注意事项.