Appearance
原文:课程项目说明 说明:内容由原网页整理翻译为中文 Markdown,并按课程项目文档的阅读习惯做了适度重组与润色。
MLSYS 课程项目 · 第一阶段:GPU 性能分析与硬件探测
随着 Agent 时代的到来,系统工程的工作方式正在发生根本性变化。过去,算子优化、高性能 GPU 调优这类任务通常只掌握在极少数顶尖专家手中;这些人必须同时理解高层算法、编译器与运行时系统、以及 GPU 硬件架构的底层细节。若放在过去,要把这一类复杂任务大规模做完,往往需要成百上千人的团队协作。
今天,这道门槛正在迅速下降。借助具备感知、推理与迭代改进能力的智能体,单个研究者或工程师已经有可能完成过去需要整个部门才能推进的工作。只要我们能够设计出这样的系统:它既能观察硬件行为,又能识别性能瓶颈,还能反复修改与优化代码,那么 AI 基础设施中最昂贵、最稀缺的“专家层”工作,就有机会被部分自动化。
这正是本学期课程项目的核心目标:
不再把重点放在“手工写代码”上,而是转向设计能够自己写、自己评估、自己优化基础设施的自主系统。
项目范围将覆盖 GPU profiling、CUDA kernel 自动调优,以及自动化的 LLM 基础设施生成。
第一阶段:GPU 性能分析指南——使用 ncu 识别瓶颈
截止时间:2026 年 4 月 21 日上午 8:00
NVIDIA Nsight Compute (ncu) 是一个面向 CUDA kernel 的交互式内核级 profiling 工具。与更关注全局时间线的 Nsight Systems (nsys) 不同,ncu 会深入到单个 kernel 的内部执行过程,展示硬件资源是如何被消耗的。
在这个项目中,你的 Agent 需要学会分析 ncu 输出的指标,并据此判断某个算子(例如矩阵乘法)的真正瓶颈在哪里。下面按课程原文整理出几类最核心的指标,以及它们在性能调优中的意义。
1.1 核心总览指标
在进入细粒度分析之前,首先应借助 Roofline Model 判断当前算子更偏向 Compute-Bound 还是 Memory-Bound。
sm__throughput.avg.pct_of_peak_sustained_elapsed(计算利用率)- 含义:SM(Streaming Multiprocessor)计算单元的利用率。
- 分析:如果这个值很高,说明 GPU 的计算核心已经处于较高负载状态。
gpu__compute_memory_throughput.avg.pct_of_peak_sustained_elapsed(内存吞吐率)- 含义:GPU 内存带宽的利用率。
- 分析:如果这个值很高,说明性能更可能受到数据传输速度限制。
SOL(Speed of Light)
- 含义:
ncu报告中经常出现的SOL Compute与SOL Memory,表示当前算子达到了硬件理论峰值性能的百分之多少。 - 分析:它们有助于快速判断算子距离“硬件上限”还有多远。
- 含义:
1.2 存储层次相关指标
如果一个算子偏向内存受限,那么接下来的问题就是:到底是哪一级存储出了问题?
L1 相关指标
- 分析重点:L1 cache 的命中率与吞吐情况。
- 典型含义:如果全局内存访问频繁而又难以命中 L1,就会显著增加延迟。
L2 相关指标
- 分析重点:L2 作为 VRAM 与 SM 之间的中间层,其利用率与流量情况。
- 典型含义:若 L2 利用率极高,通常说明数据正在频繁地在片外与片上之间交换。
DRAM / VRAM 带宽相关指标
- 分析重点:外部显存带宽使用率。
- 典型含义:如果此项长期超过 80%,通常意味着代码需要更好的数据重用策略,例如更积极地使用共享内存。
1.3 计算单元相关指标
如果算子更偏向计算受限,那么就要进一步问:究竟是哪类计算单元在工作?
Tensor Core 相关指标
- 分析重点:对深度学习中的矩阵乘法尤其关键。
- 典型含义:如果这类指标偏低,通常意味着代码并没有有效触发 Tensor Core。
传统 FP32 单元相关指标
- 分析重点:普通浮点执行单元的利用情况。
FP32 指令总量
- 分析重点:实际执行了多少 FP32 指令。
- 典型含义:可帮助判断算子是否主要依赖传统标量 / 向量浮点路径。
1.4 Occupancy 与调度
有时硬件利用率不高,并不是因为计算不够重,而是因为线程没有把 GPU “填满”。
Theoretical Occupancy
- 含义:在当前寄存器和共享内存使用条件下,硬件理论上允许同时驻留的 warp 百分比上限。
Achieved Occupancy
- 含义:运行过程中真正达到的 occupancy。
分析方式
- 如果
Achieved Occupancy远低于Theoretical Occupancy,往往意味着还存在指令延迟、调度不均、线程块分布不平衡等问题。
- 如果
1.5 常见瓶颈与诊断思路
课程原文这里给出的重点并不是死记每个指标,而是形成一条稳定的诊断流程:
- 先看 Roofline,总体判断是算力受限还是带宽受限。
- 如果更偏内存受限,继续下钻到 DRAM、L2、L1 等指标。
- 如果更偏计算受限,进一步看 Tensor Core、FP32 单元等具体计算路径。
- 最后再结合 occupancy、bank conflict 等辅助指标,判断是否存在“资源没填满”或“片上访问有冲突”等次级问题。
1.6 给学生的建议:如何让 Agent 利用这些数据
课程给出了一条非常实用的 Agent 工作流,可以整理成如下步骤:
先取 Roofline
- 让 Agent 优先读取
sm__throughput与gpu__compute_memory_throughput。
- 让 Agent 优先读取
再决定往哪一层继续看
- 如果 Memory 百分比更高,就进一步分析
dram、l1、l2等指标。 - 如果 Compute 百分比更高,就检查是否真正触发了 Tensor Core。
- 如果 Memory 百分比更高,就进一步分析
检查异常点
- 看 occupancy 是否过低;
- 看是否存在 bank conflict;
- 看是否有明显的 pipeline stall。
把指标映射回代码
- 例如:循环展开是否不够?
- 是否缺少
__shared__暂存? - 数据布局是否导致访存不合并?
- 是否没有正确利用 Tensor Core 路径?
如何在命令行中获得这些指标
text
# Example: Get all detailed metrics for a Matrix Multiplication kernel
ncu --metrics sm__throughput.avg.pct_of_peak_sustained_elapsed,gpu__compute_memory_throughput.avg.pct_of_peak_sustained_elapsed,sm__pipe_tensor_op_hmma_cycle_active.avg.pct_of_peak_sustained_active ./your_executable1.7 硬件内禀特性分析:把 GPU 当作“可探测对象”
在这一阶段里,Agent 的角色不再只是一个被动的性能报告器,而更像一个硬件探针(hardware probe)。目标是通过自动生成并分析微基准测试,反推出底层 GPU 的真实物理特性与架构极限。
Agent 需要识别的目标包括:
内存延迟层次
- 测量 L1、L2、DRAM 的访问周期数。
- 这通常需要 Agent 生成 pointer chasing 一类 kernel,以绕过硬件预取器。
有效峰值带宽
- 测出共享内存和全局内存在当前环境下的最大可达吞吐。
L2 Cache 容量
- 通过延迟—数据规模曲线中的“悬崖点”定位 L2 的实际容量。
真实 Boost 频率
- 在持续计算压力下,估算 GPU 的稳定核心频率(MHz)。
资源冲突代价
- 量化共享内存 bank conflict 相对于无冲突访问的额外延迟成本。
课程对提交形式也给了明确要求:
- 学生提交内容:你的 Agent 系统本身,也就是基础设施代码。
- 输入样例:
json
{"targets": ["dram_latency_cycles", "max_shmem_per_block_kb", "actual_boost_clock_mhz"]}- 输出样例:
json
{"dram_latency_cycles": 442, "max_shmem_per_block_kb": 48}最终评分时,你的 Agent 输出将与服务器端参考基准给出的高精度 ground truth 进行对比。
1.8 为什么不能靠“查表”糊弄过去
为了防止 Agent 只是去查“A100 参数表”或背标准规格,课程特别说明:评测环境会被动态扰动,使静态查表方法失效。
可能发生的扰动包括:
非标准频率锁定
- GPU 核心与显存频率可能被锁定到任意非标准值,例如 825 MHz,而不是常见规格中的频率。
- 这会让基于公开参数表推导出的带宽或 GFLOPS 全部失真。
资源遮罩(SM 限制)
- 评测环境可能限制 kernel 只能运行在部分 SM 上,或通过环境变量限制每个 block 可用的共享内存资源。
指令集或 API 限制
- 像
cudaGetDeviceProperties这样的标准 API 结果可能被虚拟化,甚至故意提供误导信息。
- 像
因此,课程推荐 Agent 采用一种多策略融合的方法:
- 写小型 C++ / CUDA 微基准进行低层 probing;
- 运行真实二进制并测量结果;
- 结合
ncu指标做交叉验证; - 对可疑结果做多轮重复试验。
这说明课程真正想训练的,并不是“会调用 profiling 工具”,而是“会在不可信环境里做实验推断的自主系统”。
1.9 评分方式:LLM-as-a-Judge
为了同时评价数值精度和工程推理质量,这个项目采用 LLM-as-a-Judge 形式评分。
评测系统会把以下三类信息一起送入高能力大模型中进行裁判:
学生 Agent 输出
- 最终的
results.json - Agent 给出的 reasoning / logs
- 最终的
Ground Truth 数据
- 由参考 benchmark 在当前具体环境下测得的真实硬件参数
- 包括频率锁定、资源遮罩等环境扰动信息
实验过程证据
- Agent 执行中产生的
ncutrace 摘要 - 微基准测试结果
- Agent 执行中产生的
评分标准总分 100 分,大致包含:
数值精度
- 满分:结果落在可接受工程误差内,例如延迟 ±5%、带宽 ±2%。
- 部分分:趋势判断正确,但校准不够精确。
- 零分:结果只是标准线上规格,与真实受限环境不符。
推理质量
- Agent 是否识别出了 GPU 频率被锁定?
- 是否注意到了 SM 被遮罩?
- 是否理解某些 API 数据不可靠?
微基准设计有效性
- 是否真的生成了合适的 CUDA probe,例如 pointer chasing?
- 还是只是依赖了可能被限制的 API?
交叉验证能力
- 是否做了多轮试验?
- 是否用不同类型的 probe 对可疑指标做了确认?
从这里可以看出,课程项目不是把 Agent 当作一个“答题器”,而是当作一个真正的系统研究者:它既要给出数值,更要给出可信的实验路径和推理过程。