Application Optimization for NVIDIA Grace CPU
Application Optimization for NVIDIA Grace CPU
Lukas Krenz, Mathias Wagner, Sr. Developer Technology Engineer
| S72978 | GTC 2025
目录
- NVIDIA Grace CPU 基础
- 让您的工作负载运行起来
- 实现最佳性能
- 编译器
- 选择优化的数学库
- 性能分析
- 理解硬件:Grace 文档
- 硬件性能计数器
- 工具概览
- Perf stat
- Nsight Systems
- NVTX
- Nsight Systems - 核心指标
- Nsight Systems - Uncore 指标
- 识别热点 (Identify Hotspots
- Compiler Explorer – 理解你的编译器在做什么
- SIMD 编程方法 (SIMD Programming Approaches
- 编译器自动向量化 (Compiler Auto-vectorization
- Arm 内存模型 (Arm Memory Model
- 总结 (Summary
NVIDIA Grace CPU 基础
超级芯片的构建模块
- 高性能高能效核心
- 72个旗舰级 Arm Neoverse V2 核心,每个核心配备 SVE2 4x128b SIMD。
- 快速片上互联结构
- 3.2 TB/s 的对分带宽连接 CPU 核心、NVLink-C2C、内存和系统 IO。
- 高带宽低功耗内存
- 高达 480 GB 的数据中心级 LPDDR5X 内存,可在 16W 功率下提供高达 500 GB/s 的内存带宽。
- 一致性的芯片间连接
- NVLink-C2C 提供 900 GB/s 的带宽,用于 CPU 或 GPU 之间的一致性连接。
- 业界领先的每瓦性能
- 相较于当今领先的服务器,每瓦性能提升高达 2 倍。
让您的工作负载运行起来
- 期望:它“就是能用”,Arm 生态系统非常成熟。
- 大多数应用程序/库在 Grace 上都可以开箱即用。
- 首先关注正确性。
- 性能优化是一个迭代的过程。
实现最佳性能
复用他人的工作
- 首先把基础工作做好:
- 使用正确的编译器和正确的编译器标志。
- 启用编译器优化。
- 如果适用,使用优化库。
- 仅当上述步骤失败时:
- 为您的应用程序收集数据。
- 找出性能瓶颈。
- 改进代码。
- 首先进行高级别改进(例如 C++)。
- 然后进行低级别改进(内联函数、汇编)。
- 这些步骤中的每一步都应涉及验证正确性,并且应由数据驱动。
编译器
- 使用支持 Grace/Neoverse V2 的编译器。
- 检查并更新您的编译器标志。
- 使用标志
-O3 -mcpu=native -ffp-contract=fast- 当使用 native 时,GCC 的
-mcpu=neoverse-v2+crypto+sha3+sm4+sve2-aes+sve2-sha3+sve2-sm4标志会启用所有功能(可能不检测加密扩展)。 - 如果可以接受快速数学优化,请使用
-Ofast,但在移植前请务必检查其准确性。 - 如果输出的一致性很重要,请使用
-ffp-contract=off来禁用浮点运算收缩(例如,FMA)。
- 当使用 native 时,GCC 的
- 使用
-flto来启用链接时优化。- 链接时优化的好处因代码而异。详情请参阅 https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html 。
- Grace 受益于代码局部性:考虑使用配置文件引导优化(Profile-Guided Optimization)。
- 应用程序可能需要
-fsigned-char或-funsigned-char,具体取决于开发者的假设。 - Fortran 可能会从
-fno-stack-arrays中受益。 - 可以从 https://developer.nvidia.com/grace/clang 获取 NVIDIA 构建的 Clang:为速度而优化,并经过验证与核心 NVIDIA 技术(如 CUDA® Toolkit)兼容。
选择优化的数学库
使用默认接口以实现性能可移植性
- 优先使用 Netlib BLAS/LAPACK 和 FFTW 接口。
- 基于这些接口构建可以实现性能可移植性。
- NVPL (https://developer.nvidia.com/nvpl)
- 为 NVIDIA CPU 优化的数学库。
- 可直接替换实现标准接口(如 Netlib, FFTW)的数学库。
- 为高性能库提供新接口。
- ArmPL (https://developer.arm.com/Tools%20and%20Software/Arm%20Performance%20Libraries)
- ATLAS, OpenBLAS, BLIS
- 社区支持,并为 Grace 提供了一些优化。
性能分析
- 了解您的硬件
- 对您的代码重要的硬件能力。
- 了解您的代码
- 所用算法的主要特性。
- 了解您的工具
- 使用各种工具(NVIDIA, Arm, 第三方, 开源...)。
- 不同的工具有不同的优势。
- 构建一套工具来满足您的需求。
- 获得一个可靠的基线性能(可复现)。
- 为性能预期建立模型。
- 对于大型应用:找到一个合适的代理(proxy)
- 需要相当快的周转时间。
- 可能需要使用工具进行多轮分析。
理解硬件:Grace 文档
- Grace 相关文档位于:https://docs.nvidia.com/grace
- 必读:Grace Performance Tuning Guide(Grace 性能调优指南)
- 同时参考 Arm 文档,例如 Neoverse V2 Software Optimization Guide(Neoverse V2 软件优化指南):https://developer.arm.com/documentation/108898/latest/
硬件性能计数器
- Grace 通过其性能监控单元(Performance Monitoring Units, PMU)支持多个性能计数器。
- 核心事件:测量每个核心内发生的所有事情,如指令、周期、分支、分支未命中、缓存未命中。
- Uncore 事件:涵盖核心之外发生的所有事情,在套接字(socket)级别收集。
- 可扩展一致性结构(Scalable Coherence Fabric)事件:涵盖末级缓存、内存流量以及套接字之间的流量。
- PCIe 事件:涵盖通过 PCIe 的流量,例如在使用 NVMe 磁盘时用于监控 I/O。
- Arm 统计性能分析扩展(Arm Statistical Profiling Extension, SPE)
- 独立的测量单元——不属于核心 PMU。
- 在 CPU 后端进行采样。
- 收集精确的程序计数器(指令指针)值(无偏差)、数据地址、延迟等信息。
- 目前工具支持有限。
- 更多详情请参考 NVIDIA Grace 调优指南和 Arm Neoverse V2 PMU 指南 (https://developer.arm.com/documentation/109709/latest/)。
工具概览
- 许多性能工具都支持 Grace。
- 理想情况下,应结合使用多种工具,每种工具都有其优势和劣势。
- NVIDIA 开发了 NVIDIA Nsight Systems:
- 提供带有硬件事件和指标的时间线视图。
- 支持代码注释。
- 开源工具,例如:
- Perf:收集硬件计数器、调用栈等等。
- Likwid:硬件性能计数器,支持对区域进行注释。
- eBPF 工具,如 bpftrace:内核追踪、用户级追踪、跟踪点等。
- Linaro MAP:专注于并行代码的商业性能分析器。
Perf stat
- 用于计算事件的工具。
- 在不计算过多事件时开销极低
- → 可用作运行基准测试时的默认包装器。
- 测量平均频率(周期/时间)、IPC(指令/周期)、分支未命中等。
- 提供对基准测试和 CPU 行为的初步了解。
- 高级用法:计算事件的时间序列,例如随时间变化的内存带宽。
- 示例:
$ perf stat -I 100 -o perf.json --json \
-e 'duration_time,{nvidia_scf_pmu_0/cmem_rd_data/,nvidia_scf_pmu_0/cmem_wr_total_bytes/}'
- "以 JSON 格式 (-o perf.json --json) 每 100ms (-I 100) 收集事件 duration_time, ... (-e ...)"。
- 根据指标计算 socket 0 上的内存流量(GB/s):
(32 * cmem_rd_data + cmem_wr_total_bytes) / duration_time / 1e9
Nsight Systems
时间线视图
- Nsight Systems 文档
https://docs.nvidia.com/nsight-systems/UserGuide/index.html- → Linux 上的 CPU 性能分析
- → 从命令行进行性能分析
- 为离线时间线收集性能数据
nsys profile ./app- https://docs.nvidia.com/nsight-systems/UserGuide/index.html#cli-profiling
- 在 Nsight Systems 中打开生成的
*.nsys-rep文件。
NVTX
标记您的代码
- https://github.com/NVIDIA/NVTX/
- 也是 CUDA Toolkit 的一部分。
- 可用于 C, C++, Python, Fortran (NVHPC TK)。
- 示例代码:
#include <nvtx3/nvToolsExt.h>
void congrad_64()
{
nvtxRangePush(__func__); // Range around the whole function
for (int i = 0; i < 6; ++i)
{
nvtxRangePush("loop range"); // Range for iteration
// Do ab iteration
nvtxRangePop(); // End the inner range
}
nvtxRangePop(); // End the outer range
}
Nsight Systems - 核心指标
收集核心性能指标
使用以下命令查看可用的核心指标:
nsys profile --cpu-core-metrics=help
Nsight Systems - Uncore 指标
收集 uncore 性能指标
使用以下命令查看可用的套接字(socket)级别指标:
nsys profile --cpu-socket-metrics=help
识别热点 (Identify Hotspots)
链接:https://github.com/brendangregg/FlameGraph
-
使用 Nsight Systems
- 在 Nsight Systems 安装目录下的Scripts/Flamegraph目录中
-nsys profile -o report ./app
-python3 stackcollapse_nsys.py report.nsys-rep | ./flamegraph.pl > result_flamegraph.svg -
使用 perf
-perf record -a -g ./app
-perf script | stackcollapse-perf.pl > out.perf-folded
-flamegraph.pl out.perf-folded > perf.svg
Compiler Explorer – 理解你的编译器在做什么
该工具可以帮助开发者理解编译器对源代码所做的具体优化和转换,通过并排显示源代码、生成的汇编代码以及编译器优化后的代码,可以直观地看到向量化等优化的效果。
代码来自 Coral 基准测试套件的 HACCmk 基准测试,来源:https://asc.llnl.gov/coral-benchmarks
SIMD 编程方法 (SIMD Programming Approaches)
请按顺序遵循这些建议,例如,优先选择自动向量化而不是内联函数(intrinsics)。
- 编译器 (Compilers)
- 自动向量化:NVIDIA, GCC, LLVM, ACI, Cray...
-
编译器指令:例如 OpenMP
-#pragma omp parallel for simd
-#pragma vector always -
库 (Libraries)
- NVIDIA Math Libraries (NVPL)
- Arm Performance Library (ArmPL)
- 开源科学库 (BUS, FFTW, PETSc, etc.) -
库的类别包括:BLAS, LAPACK, PBLAS, SCALAPACK, TENSOR, SPARSE, RAND, FFTW
-
内联函数 (Intrinsics - ACLE)
- https://developer.arm.com/architectures/instruction-sets/intrinsics
- https://developer.arm.com/documentation/100987/latest
- https://arxiv.org/abs/1902.09544 -
汇编 (Assembly)
- 参考 https://developer.arm.com/documentation/ddi0584/latest (Arm®v8-A 架构的可扩展向量扩展)
编译器自动向量化 (Compiler Auto-vectorization)
-
通常在较高的优化级别下启用。
- 使用一些更激进的选项,如-Ofast(例如,归约操作)。 -
诊断标志可以让你看到编译器做了什么以及没有向量化的部分。
- LLVM:
--Rpass(-missed|-analysis)=loop-vectorize
- GCC:
--fopt-info-vec-(optimized|missed|all|note)
- NVIDIA compilers:
--Minfo=vect -
查看输出和生成的代码 → 使用 Compiler explorer / Godbolt。
-
在适用的情况下,在 C / C++ 中使用 restrict 指针。
-
使用 pragmas 来指导编译器(取决于所使用的编译器)。
-#pragma GCC ivdep
-#pragma clang loop vectorize
-#pragma omp simd
Arm 内存模型 (Arm Memory Model)
-
Arm 的内存模型是弱序 (weakly-ordered) 的,与 x86 的内存模型不同:加载/存储操作可能在运行时被 CPU 重排。
-
写入操作对其他线程的可见顺序可能不同。
-
许多程序使用顺序一致性 (sequential consistency) 来在线程间传递消息 (例如,
std::atomicwithstd::memory_order_seq_cst)。 -
对于线程间的同步,release/acquire 语义可能就足够了。
-
使用较弱的内存顺序可以提高性能,但也可能引入错误。
-
如果不确定:请使用库中的同步原语。
-
这是一个复杂的话题,更多上下文请参考 Herb Sutter 的文章:https://herbsutter.com/2013/02/11/atomic-weapons-the-c-memory-model-and-modern-hardware/
总结 (Summary)
主要 takeaways
- 大多数应用程序将能开箱即用 (out of the box)!
- 正确性第一,性能第二。
- 首先把基础工作做好。
- 选择一个推荐的编译器。
- 使用最佳的标志进行编译。
- 如果可能,使用性能库。
- 使用数据驱动的迭代优化工作流。
- 使用性能分析工具。
- NVIDIA Nsight Systems - 开源工具,如 perf
- 理解你的性能预期和瓶颈。
- 优化你的热点,但前提是存在优化的潜力。
也欢迎访问我们今天下午 3:00 – 3:50 PM 的 CWE:
如何在 NVIDIA Grace CPU 上运行和优化您的工作负载 [CWE73338]