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

检测线程应用中的内存带宽饱和度 (PDF 231KB)

摘要

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

本文是“英特尔多线程应用开发指南”系列的一部分,该系列介绍了针对英特尔® 平台开发高效多线程应用的指导原则。

背景

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

当前基于 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 Quad 的系统)上并未因拥有更多线程而受益。 深入剖析后可以发现,虽然双线程版本的 Triad 得分有些微提高,但四线程版本的性能比单线程版本还要低。

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


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

建议

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

VTune 分析器和 PTU 可帮助开发人员使用 EBS 功能估算具体应用的内存带宽使用情况。 在英特尔® 酷睿™ 2 微架构上,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 架构系统上测量内存带宽的基本公式如下:

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

更多资源

有关编译器优化的更完整信息,请参阅优化通知