跳到主要内容

Moore Perf Compute 性能分析

1. 什么是性能分析?​

性能分析 (Profiling)是识别 GPU 应用程序性能瓶颈的过程。通过分析关键指标,了解内核在 GPU 上的执行效率,找出限制性能的因素。

性能指标模块 (Sections)​

Moore Perf Compute 按照分析目的,将性能指标划分为 3 个模块,在报告中以 Section 形式展示:

Section用途
LaunchStats内核启动配置和资源使用情况
MemoryWorkloadAnalysis内存访问模式分析
SpeedOfLight计算和内存吞吐量评估
Section 启用说明

LaunchStats、MemoryWorkloadAnalysis 和 SpeedOfLight 默认启用。MemoryWorkloadAnalysis_Chart 与 MemoryWorkloadAnalysis_Tables 用于补充展示内存分析结果,默认关闭,需要在采集时按需启用。


2. Roofline 模型​

2.1 什么是 Roofline 模型?​

Roofline 模型是可视化 GPU 性能上限的有效方式。它直观地显示内核性能与硬件极限之间的关系,帮助开发者快速定位性能瓶颈类型(计算受限或内存受限)。

信息

下文提到的"峰值 TFLOPS"和"峰值 GB/s"均指 S5000 架构的理论值。

2.2 物理瓶颈​

所有 GPU 性能问题最终可归约为三类物理限制:

性能 = min(计算吞吐, 内存吞吐, 延迟隐藏效率)
瓶颈类型物理根源典型症状优化方向
计算受限FP32/FP16/INT8 计算单元饱和高计算利用率,低内存利用率减少 FLOPs、使用低精度
内存受限全局内存带宽饱和高内存利用率,低计算利用率合并访问、共享内存缓存
延迟受限指令流水线停顿低计算利用率,低内存利用率提高占用率、减少同步
关键洞察

在优化之前,必须先识别瓶颈类型。盲目优化可能导致无效工作。

2.2 Roofline 图表解读​

性能 (FLOPS)
↑
│ ╭─────────────── 峰值计算性能
│ ╱│
│ ╱ │
│ ╱ │
│ ╱ │
│ ╱ │
│ ╱ │
│ ╱ 内存带宽极限
│ ╱ │
│ ╱ │
│╱ │
└───────────────────┴────────────→ 算术强度
0 脊点 (FLOPs/Byte)
区域诊断优化策略
脊点左侧内存受限增加算术强度(共享内存、数据重用)
脊点右侧计算受限减少 FLOPs 或使用更低精度
脊点位置内存/计算平衡点算法设计的理论目标

2.3 算术强度计算​

算术强度 = 每秒浮点运算数FLOP / 每秒内存带宽总数。
指每从内存中读取一个字节的数据,程序可以执行多少浮点运算(FLOP),单位为 FLOPs/Byte。

对于 GEMM (C = A × B):
FLOPs = 2 × M × N × K # 每次乘累加算 2 次 FLOP

内存访问取决于数据重用策略:

策略 A: 无重用(每次从全局内存读取)
内存访问 = (M×K + N×K + M×N) × sizeof(FP32)

策略 B: 矩阵 B 完全缓存(典型共享内存实现)
内存访问 = (M×K + N×K) × sizeof(FP32)

示例:M=N=K=1024, FP32, 策略 B
FLOPs = 2 × 1024³ = 2.15 GFLOPs
内存 = (1024² + 1024²) × 4 = 8 MB
算术强度 = 2.15G / 8M = 269 FLOPs/Byte

→ 对于 S5000(峰值约 200+ FLOPs/Byte),处于计算受限区域边缘
→ 优化方向:增加数据重用(共享内存分块)可进一步提升性能

3. 如何使用性能分析工具?​

3.1 重放机制 (Replay)​

不是所有性能计数器都能在同一时间读取。为了获取完整指标集,需要多次执行内核:

3.2 可重现性 (Reproducibility)​

为确保分析结果的可重现性,Moore Perf Compute 会强制串行化执行 kernel:

  • 每次运行都会强制 kernel 串行执行
  • 同一时间只能分析一个进程

为什么需要串行化? 并发执行会导致 GPU 资源竞争,引入非确定性的性能波动。串行化可消除这种干扰,确保每次测量的一致性。

数据差异的可能原因:

原因说明
系统负载变化其他进程占用 GPU
GPU 温度变化散热不良导致降频
后台服务动态频率调整

提高可重现性的建议:

# 1. 关闭其他 GPU 程序(将 other_gpu_app 替换为实际进程名)
pkill -f other_gpu_app

# 2. 多次运行取平均值
for i in {1..5}; do
mcu -o run_$i.mcu-rep ./my_app
done

# 3. 在稳定环境中测试

3.3 MUSA Green Contexts 支持​

Green Contexts 是多上下文支持机制,允许多个进程/应用共享 GPU 资源:

┌─────────────────────────────────────────────────────────┐
│ GPU │
│ ┌─────────────┬─────────────┬─────────────┐ │
│ │ MPX 0 │ MPX 1 │ MPX 2 │ ... │
│ │ (Context A)│ (Context B)│ (Context C)│ │
│ │ App 1 │ App 2 │ App 3 │ │
│ └─────────────┴─────────────┴─────────────┘ │
└─────────────────────────────────────────────────────────┘

识别 Green Context 结果:

  • 报告标题栏的 Attributes 按钮会变成绿色
  • Session 页面显示 Green Context Resources 部分
  • 显示 MPX IDs 和 MP 数量
详细使用指南

如需了解 Green Contexts 分析的详细操作步骤和界面说明,请参考 用户指南 中的 Green Contexts 分析章节。

3.4 内存工作负载分析​

内存工作负载分析(Memory Workload Analysis)用于帮助您判断 kernel 是否主要受内存访问、带宽或内存指令吞吐限制。该能力由以下三个 section 组成:

  • MemoryWorkloadAnalysis:默认开启,也可以手动取消
  • MemoryWorkloadAnalysis_Chart:默认关闭
  • MemoryWorkloadAnalysis_Tables:默认关闭

这三个 section 可以同时选中,也可以任选其中一个或两个,或者全部不选。

可以通过以下方式控制采集内容:

  • 命令行:使用 mcu --sections <section列表> my_application 指定要采集的 section。常见示例如下:
mcu --sections MemoryWorkloadAnalysis my_application
mcu --sections MemoryWorkloadAnalysis,MemoryWorkloadAnalysis_Chart my_application
mcu --sections MemoryWorkloadAnalysis_Chart,MemoryWorkloadAnalysis_Tables my_application
  • GUI:在 Connect to process 窗口配置分析任务时,打开 Metrics 配置页面,勾选或取消勾选 Memory Workload Analysis、Memory Workload Analysis Chart 和 Memory Workload Analysis Tables 选项

采集完成后,相关结果会显示在报告的 Details 页面。

不同 section 组合下的展示方式
  • MemoryWorkloadAnalysis + MemoryWorkloadAnalysis_Chart + MemoryWorkloadAnalysis_Tables:三者数据统一显示在 Memory Workload Analysis 分区中。展开后,可通过分区右上角的下拉框在 全部(All)、内存图表(Memory Chart) 和 内存表格(Memory Tables) 之间切换
  • MemoryWorkloadAnalysis + MemoryWorkloadAnalysis_Chart,或 MemoryWorkloadAnalysis + MemoryWorkloadAnalysis_Tables:数据仍显示在 Memory Workload Analysis 分区中,但不会出现右上角的下拉切换
  • MemoryWorkloadAnalysis_Chart + MemoryWorkloadAnalysis_Tables:Details 页面会分别显示 Memory Workload Analysis Chart 和 Memory Workload Analysis Tables 两个独立分区
  • 只选其中一个 section:Details 页面只显示对应名称的独立分区,即 Memory Workload Analysis、Memory Workload Analysis Chart 或 Memory Workload Analysis Tables
  • 三个都不选:报告中不会显示相关分区

多 GPU 场景下,结果会按 device 分别展示;切换 device、kernel 和 launch 时,数据不会混淆。

如果当前环境不支持相应的 section,采集阶段会给出提示,报告中也不会显示该部分内容。

理解结果时,通常结合以下几类信息使用:

  • 顶部摘要指标:Memory Throughput、Mem Busy、Max Bandwidth、Mem Pipes Busy、L1 Hit Rate 和 L2 Hit Rate
  • Memory Chart:用图形方式展示 kernel 与缓存、共享内存、设备内存之间的数据流
  • Memory Tables:用表格方式汇总共享内存和设备内存的访问统计

3.4.1 如何快速判断瓶颈​

阅读结果时,建议先看顶部摘要指标,再看图表或表格细节:

  • Mem Busy 较高:说明相关内存硬件单元已经比较繁忙
  • Max Bandwidth 较高:说明内存层级之间的数据传输带宽接近上限
  • Mem Pipes Busy 较高:说明 memory instructions 的发射吞吐可能成为限制因素
  • L1 Hit Rate 或 L2 Hit Rate 较低:说明更多访问继续流向更靠后的缓存层级或设备内存,访存代价通常更高

这些指标适合用来快速缩小排查范围,但通常仍需结合 Memory Chart 和 Memory Tables 一起判断。

3.4.2 Memory Chart 阅读方法​

Memory Chart 的核心作用不是只告诉您“访问了哪些内存”,而是帮助您看清数据沿着哪条路径流动,以及主要压力更可能集中在哪一层。

在当前界面中,图表通常从左到右展示以下路径:

  • Kernel
  • Global / Local / Texture / Surface
  • L1 Cache
  • L2 Cache
  • System & Peer Memory 或 Device Memory
  • 共享内存相关路径:Kernel -> Shared -> Shared Memory

阅读时可以按下面的顺序查看:

  1. 先确认主要活跃路径是在全局内存路径,还是共享内存路径。
  2. 再看每条连线上的数值标签,判断主要压力来自指令、请求还是数据传输。
  3. 最后结合 L1 Hit Rate 和 L2 Hit Rate,判断访问是否被前级缓存有效吸收。

3.4.3 图中的对象和连线如何理解​

图中的方块表示不同的访问对象或内存层级,连线表示它们之间的数据流。常见读法如下:

  • Kernel 到 Global / Local / Texture / Surface 或 Shared 之间的标签通常以 Inst 结尾,表示相关内存指令数量
  • Global / Local / Texture / Surface 到 L1 Cache 之间的标签通常以 Req 结尾,表示请求数量
  • L1 Cache、L2 Cache、System & Peer Memory、Device Memory 之间的标签通常表示传输大小;当切换显示方式后,也可以表示吞吐率
  • L1 Cache 和 L2 Cache 方块内部会直接显示命中率,便于判断缓存是否有效

这几类信息可以组合起来理解:

  • Inst 很高但后续 Req 相对较低:说明前端访存指令较多,但进入后续内存层级的请求压力未必同样高,需要继续结合后续链路判断
  • Req 很高且继续向 L2 Cache、Device Memory 传播:说明前级缓存对访问的吸收有限,后端内存压力更大
  • 共享内存路径活跃:说明该 kernel 存在较多共享内存相关访问,可进一步结合 Memory Tables 中的 Bank Conflicts 判断是否存在共享内存访问冲突

3.4.4 两个界面控制项​

图表右上角有两个常用控制项:

  • Values:在传输大小(Transfer Size)和吞吐率之间切换,适合分别观察“总量”与“速度”
  • Inactivity:控制未活跃路径的显示方式,适合在复杂图中聚焦当前真正发生数据流动的部分

3.4.5 什么时候配合 Memory Tables 一起看​

如果 Memory Chart 只能帮助您看到“哪条路径忙”,但还不足以解释“为什么忙”,建议同时查看 Memory Tables:

  • 看共享内存访问是否集中在 Shared Load、Shared Store 或 Shared Atomic
  • 看 Bank Conflicts 是否偏高
  • 看设备内存的 Bytes 和 Throughput 是否显著偏高

这样可以把图中的访问路径和表中的统计数据对应起来,更容易定位是缓存命中不足、共享内存冲突,还是设备内存传输压力过大。

3.4.6 如何排查共享内存 Bank Conflict​

如果怀疑 kernel 的共享内存访问模式存在问题,可以按下面的顺序排查:

  1. 先查看 Memory Chart,确认共享内存路径是否明显活跃。
  2. 再查看 Memory Tables 中 Shared Memory 表的 Bank Conflicts,判断共享内存访问是否存在明显冲突。
  3. 如果已经调整了共享内存布局,例如为 2D tile 添加 padding,可以对比优化前后的两个报告,确认 Bank Conflicts 是否明显下降。
  4. 最后再结合 Memory Throughput、Mem Busy、执行时间等结果,判断这项优化是否真正带来了性能收益。

共享内存路径活跃并不一定单独说明存在 Bank Conflict,仍需结合 Bank Conflicts 一起判断;如果该指标下降后性能改善仍然有限,则需要继续排查缓存命中率、设备内存吞吐率或其他瓶颈。

如需查看完整的优化示例,请参考最佳实践中的共享内存 Bank Conflict 优化章节。如需了解 Bank Conflict 的原理,以及 padding、swizzle 等更通用的优化方法,请参考 MUSA SDK Programming Guide 中的相关章节。


4. 性能分析三层模型​

分析策略: 从 L1 发现问题 → 在 L2 定位内核 → 用 L3 理解根因