Intel® Advisor Roofline 分析
一种可视化性能优化权衡的新方法
Kevin O’Leary,技术咨询工程师;Ilyas Gazizov,高级软件开发人员;Alexandra Shinsel,技术咨询工程师;Roman Belenov,高级软件开发人员;Zakhar Matveev,产品架构师;以及 Dmitry Petunin,技术咨询工程师,Intel 公司
软件必须同时具备多线程和向量化才能充分利用当今和未来的硬件。数据驱动的向量化设计可以带来长期的性能增长,风险更小,影响更大。即使拥有完美的向量和线程并行性,开发人员也常常需要额外平衡 CPU/向量/线程利用率与内存子系统数据瓶颈。这类优化可以通过使用 "边界和瓶颈" 的 Roofline 性能模型来解决。
本文概述了 Intel® Advisor 2017,并讨论了新的 Intel Advisor Roofline 分析功能。Roofline 模型提供了对如何最好地解决应用程序性能问题的直观而强大的表示。最后,通过一个案例研究展示了在实际示例上的优化过程。
Roofline 模型
Roofline 模型最初由加州大学伯克利分校的研究人员 Samuel Williams、Andrew Waterman 和 David Patterson 在 2009 年的论文 Roofline: An Insightful Visual Performance Model for Multicore Architectures 中提出。最近,它被扩展到解决内存子系统的所有级别,正如 Aleksandar Ilic、Frederico Pratas 和 Leonel Sousa 在他们的论文 Cache-Aware Roofline Model: Upgrading the Loft 中所描述的那样。
Roofline 模型通过帮助您回答以下问题来洞察您的应用程序如何工作:
- 我的应用程序在当前硬件上运行是否最优?如果不是,哪个硬件资源利用率最低?
- 什么限制了性能?我的应用程序工作负载是受内存还是受计算限制?
- 什么才是提高应用程序性能的正确策略?
该模型通过测量两个参数来绘制数据,帮助您可视化应用程序的计算和内存带宽上限:
- 算术强度,即 CPU 和内存之间传输的每字节浮点运算次数
- 每秒浮点运算次数(GFLOPS)
数据点与模型线(Rooflines)的接近程度显示了优化的程度(图 1)。右侧蓝色区域的内核是计算密集型的。当您向上移动 Y 轴时,它们会接近浮点峰值。这些内核的性能受平台计算能力的限制。为了提高内核 3 的性能,可以考虑将其迁移到高度并行的平台,例如 Intel® Xeon Phi™ 处理器,其中计算上限和内存吞吐量更高。对于内核 2,可以考虑向量化作为性能改进策略,因为它离上限还很远。
图表的左侧(红色区域)的内核是内存密集型的。当您向上移动 Y 轴时,它们受到平台 DRAM 和缓存峰值带宽的限制。为了提高这些内核的性能,可以考虑改进算法或其实现,以便每个数据项进行更多的计算,从而将绘图位置向右移动,那里性能上限更高。由于内存带宽更高,这些内核也可能在 Intel Xeon Phi 处理器上运行得更快。
Intel Advisor 概述
Intel Advisor 是一款软件分析工具,为应用程序提供强大的软件设计和性能特征化平台。Intel Advisor 包含多线程并行原型设计(Threading Advisor)、向量并行优化(Vectorization Advisor)以及内存与计算特征化(Advisor Roofline Automation)功能。
本文主要关注 Advisor Roofline 和 Vectorization 分析。在使用 Intel Advisor GUI 时,您可以使用“工作流”切换按钮在 Vectorization 和 Threading Advisor 流程之间切换。可以通过 Roofline 侧边栏(图 2)访问 Roofline 图。
Vectorization Advisor 可以通过以下步骤帮助您提高代码性能:
- Survey (调查) 显示哪些循环消耗的时间最多,并提供详细的 SIMD 统计数据。
- FLOPS 和 Trip Counts (迭代计数) 测量每个循环和函数的迭代次数、调用次数以及每秒精确的浮点运算次数。
- Recommendations (建议) 提供了有关如何解决性能问题的具体建议。
- Dependencies Analysis (依赖项分析) 提供动态依赖项分析,以验证循环是否具有可能限制向量化和并行化的跨迭代依赖项。
- Memory Access Patterns Analysis (内存访问模式分析) 检查您的内存访问方式是否有利于向量化。
通过结合 Vectorization Advisor 和 Roofline 分析,您可以发现许多重要的性能和设计洞察。例如,了解 Vectorization Advisor Survey Report 提供的 Vectorization Efficiency (向量化效率) 指标,在解释 Roofline 图上的数据时通常至关重要。
Intel Advisor Roofline 分析
Intel Advisor 实现的 Roofline 模型是“缓存感知”的,它通过解决内存/缓存层次结构的所有级别来提供额外的洞察。
- 倾斜的 Rooflines 图示了当所有数据都适合相应缓存时的峰值性能水平。
- 水平线显示了如果向量化和其他 CPU 资源得到有效利用,可实现的峰值性能水平。
Intel Advisor 在 Roofline 图上为每个循环放置一个点(图 3)。圆圈的大小和颜色表示循环的相对执行时间。大多数循环需要进一步优化才能更好地利用缓存内存。有些,例如位于中间垂直线右侧的、落在标有 ScalarAddPeak 的虚线上的绿点,可能是向量化效果不佳的循环。正如您所见,Roofline 图可以轻松找到改进应用程序性能的机会。
如何解读 Intel Advisor Roofline 图
Roofline 图提供有用的信息,但它不是一个参考表,您不能简单地找到您的输入并读取相应的输出。它是一个指导,建议调查哪些因素。它需要解释。
Roofline 图上的线条,例如图 3 中的线条,代表了基于 Intel Advisor 运行的基准测试结果的内核性能的硬件限制,以确定主机系统的基线和性能限制。最上面的线条形成了 Rooflines,代表了机器的最大性能。在图 3 中,最上面的线条是“L1 Bandwidth”(L1 带宽)和“Single Vector FMA Peak”(单精度向量 FMA 峰值)。并非所有内核都能达到此性能,最终可能会受到较低 Rooflines 的限制,具体取决于算法的性质(例如,无法向量化的内核将受限于标量计算的最大性能)。
内核在图上的水平位置是其算术强度(CPU 和内存之间传输的每字节浮点运算次数,以操作数大小衡量),这主要由其算法决定,尽管可以通过编译期间发生的优化在一定程度上改变。图 4 给出了不同算法及其相对算术强度的示例。重新设计内核的算法以增加其算术强度,可将其推到 Roofline 图的右侧,这可能有助于提高其最大潜在性能,因为内存带宽 Rooflines 是倾斜的。
内核相对于各种 Rooflines 的垂直位置揭示了瓶颈。如果内核位于某个 Roofline 之上,则该 Roofline 不是主要的性能瓶颈,尽管它仍然会影响性能。位于内核之上的 Rooflines 是潜在的瓶颈,每个都对应一个可以使用特定类型优化来克服的问题。如果内核位于标量计算峰值线下方,那么就值得调查内核的向量化状态。如果它未向量化或向量化效率低下,那么该 Roofline 很可能代表瓶颈,并表明改进或实现内核的向量化(如果可能)是明智的。另一方面,如果该内核已有效向量化,则可以排除标量计算峰值作为瓶颈,您可以继续调查内核之上的其他 Rooflines。
使用 Intel Advisor 解决性能问题
本节提供了一些 Intel Advisor 的技巧。
技巧 1: 使用摘要视图查看耗时最多的循环(图 5 和图 6)以及调优建议(图 7)。
技巧 2: 使用 Roofline 自定义来移除您不需要的 Rooflines(图 8)。
例如,如果您只处理单精度数据,可以安全地从 Roofline 中移除双精度峰值。
技巧 3: 使用 Smart Mode (智能模式) 来查找最佳优化候选(图 9)。
循环按其 Elapsed Self Time (自上次执行时间) 在 Roofline 上排序,但通过激活 Smart Mode,您可以识别总时间较长的循环。在循环中花费的总时间越多,优化它的总体影响就越大。
技巧 4: 使用其他 Intel Advisor 功能来补充 Roofline 图中的信息。
向量化效率是您的向量化温度计(图 10 和图 11)。在 Instruction Set Analysis (指令集分析) 下,查看 Traits (特性) 列以了解可能影响向量化的因素(图 10)。如果您怀疑您的内存引用方式不利于向量化,请考虑运行 Intel Advisor 内存访问模式收集。[编者注:Vladimir Tsymbal 在本期《The Parallel Universe》杂志上的文章“Identifying Scalability Problems in Parallel Applications on Multicore Systems”描述了一些分析内存访问的技术。]
技巧 5: 使用循环切换(图 12)将向量化循环与非向量化循环隔离开。
技巧 6: 将源代码窗口与 Roofline 图结合使用(图 13)。
Intel Advisor 将您的源代码无缝集成到性能配置文件中。
案例研究:使用 Roofline 分析优化 MRI 图像重建基准测试
514.pomriq SPEC ACCEL 基准测试是一个 MRI 图像重建内核,在 Stone 等人 (2008) 的论文中有描述。MRI 图像重建是将采样的无线电响应转换为磁场梯度。采样坐标位于磁场梯度空间,即 K 空间。MRI 图像重建中的 Q 矩阵是基于采样轨迹、K 空间采样点计划的可预计算值。该算法检查大量输入,代表预期的 MRI 扫描轨迹和将被采样的点。Q 矩阵的每个元素是通过对所有轨迹采样点贡献的总和计算得出的。每个贡献涉及输入和输出 3D 位置的三个元素向量点积以及一些三角运算。输出的 Q 元素是复数,但输入是多元素向量。该内核本质上是计算密集型的,因为三角函数计算成本高昂,而且问题的规律性允许轻松管理内存带宽。因此,一旦平铺和数据布局消除了任何人为的内存带宽瓶颈,最重要的优化就是低级顺序代码优化和提高指令流效率,例如循环展开。
514.pomriq 的输入包括一个文件,其中包含 K 空间值的数量;X 空间值的数量;以及 K 空间样本的 K 空间坐标、X 空间坐标和 Phi 场复数值的列表。每组坐标和复数值都存储为数组,每个字段连续写入。514.pomriq 的输出是结果 Q 矩阵的复数值,以“实部、虚部”格式表示每一行。本案例研究将分析 514.pomriq 计算内核,并侧重于其优化。在 Intel Xeon Phi 7250 处理器上运行的 514.pomriq 的 Intel Advisor 摘要如图图 14 所示,从中可以轻松看出涉及计算 Q 矩阵的循环是热点。
我们使用 Intel Advisor Smart Mode 来缩小最佳优化候选范围(图 15a)。我们花费时间最多的循环已被向量化,但仍低于 MCDRAM Roof(图 15b)。这可能表明存在内存使用问题。让我们使用 Code Analytics (代码分析) 和 Recommendations (建议) 来检查该循环。
我们在此处看到大量的 gather 指令,并建议探索循环的内存访问模式(图 16 和图 17)。在运行内存访问模式分析后,我们观察到 4% 的 gather 步长,这提示我们可能存在瓶颈:非最优内存访问(图 18)。查看详细信息后,我们可以验证没有必要使用 gather 指令,因为步长是恒定的(图 19a)。我们也可以在 Intel Advisor 建议中看到相同的信息(图 19b)。
在检查了内核的源代码后,一切都变得清晰了。
#pragma omp simd private(expArg, cosArg, sinArg) reduction(+:QrSum, QiSum) for (indexK = 0; indexK < numK; indexK++) { expArg = PIx2 * (kVals[indexK].Kx * x[indexX] + kVals[indexK].Ky * y[indexX] + kVals[indexK].Kz * z[indexX]); cosArg = cosf(expArg); sinArg = sinf(expArg); float phi = kVals[indexK].PhiMag; QrSum += phi * cosArg; QiSum += phi * sinArg; }
该代码使用结构体数组,在向量化后变成“gather”。但是,新版本的 Intel® 编译器可以识别访问模式并应用优化来消除 gather,从而使用更轻量级的指令。“Gather”的替换是通过“Gather to Shuffle/Permutes”(gather 到 shuffle/permute)编译器转换完成的,这通常对现代 CPU 非常有利,尤其是在支持 Intel AVX-512 的平台上。[编者注:Martyn Corden 在本期《The Parallel Universe》杂志上的文章“Vectorization Opportunities for Improved Performance with Intel® AVX-512”描述了 Intel® Compiler 2017 如何利用 Intel AVX-512 来创造新的循环向量化机会。]
让我们看看使用新 Intel 编译器(例如 Intel Compiler 2017 Update 1)并支持“Gather to Shuffle/Permutes”后重新编译的 Roofline 图。我们可以看到点现在位于 MCDRAM 之上,并且没有 gather 指令(已替换为 Intel AVX-512 的“2-source permute”),每秒浮点运算次数也有所增加(图 21 和图 22)。
然而,解决此类问题还有更有效的方法:AOS(结构体数组)到 SOA(数组结构体)的转换。此优化允许我们使用更方便的数据容器来提高向量处理效率。过去,这需要手动重写底层数据结构。现在,使用 Intel® SIMD Data Layout Templates (SIMD 数据布局模板) 库(图 23),我们只需在声明 `kValues` 结构体、初始化结构体以及计算 K 值的地方添加几行代码,即可轻松提高性能。
#include <sdlt/sdlt.h> struct kValues { float Kx; float Ky; float Kz; float PhiMag; }; SDLT_PRIMITIVE(kValues, Kx, Ky, Kz, PhiMag) sdlt::soa1d_container<kValues> inputKValues(numK); auto kValues = inputKValues.access(); for (k = 0; k < numK; k++) { kValues [k].Kx() = kx[k]; kValues [k].Ky() = ky[k]; kValues [k].Kz() = kz[k]; kValues [k].PhiMag() = phiMag[k]; } auto kVals = inputKValues.const_access(); #pragma omp simd private(expArg, cosArg, sinArg) reduction(+:QrSum, QiSum) for (indexK = 0; indexK < numK; indexK++) { expArg = PIx2 * (kVals[indexK].Kx() * x[indexX] + kVals[indexK].Ky() * y[indexX] + kVals[indexK].Kz() * z[indexX]); cosArg = cosf(expArg); sinArg = sinf(expArg); float phi = kVals[indexK].PhiMag(); QrSum += phi * cosArg; QiSum += phi * sinArg; }
让我们查看新的 Roofline 图(图 24)。应用此优化后,点不再是红色。这意味着它现在花费的时间更少,并且 GFLOPS 更高,使其接近 L2 Roof。此外,该循环现在具有单位步长访问,因此无需特殊内存操作(图 25a 和图 25b)。内核的总性能提升了近 3 倍,整个应用程序的性能提升了 50%。
结论
Roofline 模型提供了一种新的、视觉上直观且强大的应用程序性能表示。通过使用正确的优化技术,如 Roofline 图所在区域所示,您可以避免在影响有限的优化上浪费宝贵的时间。Roofline 模型可以回答以下问题:
- 我能获得更好的性能吗?
- 主要的性能瓶颈是什么:内存还是 CPU?
- 如果我优化某个特定瓶颈,可以获得多少加速?
- 如果我使用另一个平台,可以获得多少加速?
随着系统越来越大、越来越复杂,获得这些答案并非易事,但 Roofline 分析可以为您节省时间和精力。
现代化您的代码
- 为了充分利用您的硬件,您需要通过向量化和多线程来现代化您的代码。
- 采取一种有条理的方法,例如本文概述的方法,并利用 Intel® Parallel Studio XE 中的强大工具,可以使现代化任务变得更加容易。
- 使用 Intel Advisor Roofline 分析,现已在 Intel® Parallel Studio XE 2017 Update 1 中提供。
- 发送电子邮件至 vector_advisor@intel.com,获取有关一些令人兴奋的新功能的最新信息,这些功能目前正在开发中。
有用的 Intel Advisor 链接
开始使用 Intel® Advisor Roofline 功能
基于自上次执行时间的 FLOPS 计算,并包含对如何解读嵌套循环的 Roofline 结果的重要解释。
参考文献
Stone, S. S.; J. P. Haldar, S. C. Tsao, W. W. Hwu., Z. Liang, and B. P. Sutton. "Accelerating advanced MRI reconstructions on GPUs." In International Conference on Computing Frontiers, pages 261–272, 2008.