拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

GPU Profiling实战笔记:从监控误判到内核级瓶颈定位

GPU Profiling实战笔记:从监控误判到内核级瓶颈定位 提到GPU profiling可能很多人第一反应是打开任务管理器看一眼GPU占用率看到100%就以为已经跑满了看到20%就抱怨显卡没发挥作用。我做了几年GPU相关的性能分析可以负责任地说这两个判断大概率都是错的。GPU profiling从来不是看一个占用率数字那么简单它要回答的问题是——你的程序在GPU上到底把时间花在了哪里、把资源浪费在了哪里以及为什么明明硬件在忙业务上却不出活儿。这篇文章是我基于自己的实际项目经验整理的一份GPU profiling实战笔记。内容覆盖从底层执行模型、常用工具链到真实瓶颈定位、驱动层异常排查再到优化动作落地的完整链路。适合正在做CUDA/CUDA内核开发、PyTorch深度学习训练调优、GPU集群运维的工程师也适合刚接触异构计算、想搞明白GPU利用率为什么上不去的初学者。1. 先厘清概念GPU profiling到底在剖什么1.1 profiling不是monitoring别把两个概念混着用我经常看到有人把GPU profiling和GPU监控混为一谈。监控monitoring是持续采集GPU的状态——利用率、显存、温度、功耗、时钟频率典型工具是nvidia-smi、nvidia-smi dmon、DCGM它回答的是现在GPU在干什么而profiling是对某一次执行过程做深入的采样和插桩分析——kernel耗时、启动开销、访存吞吐、warp调度情况、寄存器压力典型工具是Nsight Systems、Nsight Compute、PyTorch Profiler它回答的是刚才那次运行时间去哪了为什么这么慢。这两个层次都很重要但排障顺序应该是先做monitoring发现问题再做profiling定位根因。我接手过一个训练脚本nvidia-smi看GPU利用率只有18%所有人第一反应是GPU没喂饱数据加载有瓶颈。结果一profile发现问题根本不在数据管线而在一个自定义kernel的启动配置——block数量设置得太小GPU的几十个SM只激活了零星几个其余都在空转。这就是典型的只看监控不看profile会误判的场景。1.2 profiling要关注的四个维度我习惯把GPU profiling拆成四个维度来思考每个维度背后对应一类不同的瓶颈维度核心问题常见表现主要工具计算维度SM上的算力有没有被用满kernel时间远超理论耗时Nsight Compute的Compute Workload Analysis访存维度数据搬运是否成为瓶颈高带宽占用但SM大量等待Nsight Compute的Memory Workload Analysis同步/延迟维度kernel启动、线程同步、数据传输是否拖后腿GPU利用率锯齿状、小kernel扎堆Nsight Systems的时间线硬件/驱动维度供电、温度、PCIe链路、驱动状态是否正常XID错误、掉驱动、降频dmesg、nvidia-smi -q很多时候瓶颈不是单一维度而是多个维度叠加。比如一个kernel既访存密集又启动过于频繁那单纯优化访存模式只能改善一部分还得考虑把多个小kernel合并成一个。1.3 什么时候该做GPU profiling我总结了三类典型触发场景性能不达预期模型训练速度比理论上慢很多infra延迟高GPU利用率异常这时需要对训练循环和核心kernel做profile。资源异常显存OOM但排查不出谁占了显存或者GPU温度/功耗异常升高需要profile定位是哪个算子或哪个批次的显存峰值。环境变更后的回归验证换了驱动、换了CUDA版本、从单卡扩展到多卡、换了GPU型号之后哪怕程序能跑也要做一次基线profile确认性能没有劣化。2. 底层执行模型看懂GPU怎么干活才能看懂profile结果2.1 从host到device一次kernel launch的全流程GPU profiling的所有指标本质上都是在度量这条链路上每一环的开销。一个CUDA kernel从CPU发起执行要经历这么几步应用通过CUDA Runtime API提交kernel launch请求。驱动把kernel、参数、相关的CUDA context信息打包写入GPU命令缓冲区。命令缓冲区通过PCIe/系统总线传给GPU前端。GPU前端解析命令把kernel调度到各个SM上。SM上的调度器把线程块分派到执行单元按warp逐条发射指令。kernel执行结束结果写回显存CPU侧通过同步操作感知完成。很多人忽略的一点是kernel launch本身有一笔固定开销通常是几微秒到十几微秒。当你的kernel只有几十微秒的执行时间时launch开销就占了总耗时的大头。Nsight Systems的时间线里能清清楚楚看到CPU发指令和GPU执行之间的空隙这就是很多小kernel扎堆程序慢的根本原因。2.2 warp和cooperative thread arrayCTA到底什么关系我在网上看到不少人在搜cooperative thread arrayCTA和warp是什么关系这确实是理解GPU profiling绕不开的底层概念。直接给结论thread你写代码时的最小执行单元每个线程跑同一段kernel函数。warp硬件真正执行时的调度单位由32个线程组成。GPU的SIMT架构决定了一个warp里的线程在同一时刻执行同一条指令可以有分支分歧但本质上是一条指令喂给32个lane。CTAcooperative thread array也就是常说的线程块thread block是一组可以互相协作的线程集合它们可以在block内做同步__syncthreads()、通过共享内存交换数据。一个CTA通常包含多个warp比如256线程的CTA就是8个warp。用一句话概括CTA是程序员视角的逻辑并发结构warp是硬件视角的调度执行结构。CTA多大由你定warp多大是NVIDIA固定死的32线程。这个区分对profiling很重要。因为很多profile工具报告的是每SM活跃warp数warp占用率这类指标你要能心算出来一个256线程的CTA占用8个warp如果SM能容纳的并发warp上限是64那8个warp只占了12.5%的理论并发容量——哪怕kernel执行时ALU一直在运算这种低占用率的结构也会导致延迟无法被隐藏。2.3 occupancy越高一定越好吗算一笔账所谓occupancy占用率指一个SM上活跃warp数与理论最大warp数的比值。很多人调到高occupancy就觉得优化到位了这是个常见误区。occupancy的真正作用是隐藏访存延迟。当一个warp因为读显存被阻塞时SM调度器切换到另一个warp执行让访存和计算重叠。低occupancy时warp阻塞就是真的空闲高occupancy时访存延迟能被其他warp的计算掩盖。但高occupancy本身不直接等于高性能。假设一个kernel是纯计算密集所有数据都在寄存器里没有访存等待那计算单元始终满载多高的occupancy都无所谓反而是低occupancy还能减少调度开销。反过来一个访存密集的kernel如果occupancy太低所有warp都在等数据SM的ALU干瞪眼这时提高occupancy就非常有效。我做过一个例子一个kernel每个线程用64个寄存器导致一个SM上最多同时驻留1024个线程20世纪NVIDIA的经典上限是每个SM 2048线程寄存器文件大小固定occupancy只有50%。我把寄存器用量压到40个之后occupancy到了80%虽然每线程的局部计算能力理论峰值略微下降但访存延迟被更好地隐藏了整体kernel时间反而降了35%。这就是为什么profile工具里要同时看寄存器压力和occupancy两个指标不能只看一个。2.4 内存层次profile里那些带宽数字意味着什么GPU的内存/缓存层次对profiling结果的影响经常被低估。以NVIDIA A100为例一个SM有寄存器文件最大256KB一级缓存和共享内存加起来192KB可配置比例L2缓存40MB所有SM共享不同级别的带宽差异巨大。我用一个类比帮助理解寄存器相当于你的大脑工作记忆取用几乎零延迟共享内存相当于手边的笔记本几十个周期能翻到L1/L2缓存相当于书架上的资料需要起身查显存相当于仓库每次取货要走一个很长的通道。profile工具里常见的指标是global memory throughputL1/TEX hit rateL2 hit rate。当L2命中率高说明数据被复用了当global memory throughput接近峰值说明这个kernel是访存受限的。如果你看到一个kernel算力利用率低、访存带宽利用率极高那基本可以判定为memory-bound优化方向是减少无效访存、提高数据复用而不是堆更多计算。3. 我的常用profiling工具栈与安装避坑3.1 NVIDIA工具族谱Nsight Systems和Nsight Compute的分工NVIDIA官方的profiling工具迭代了好几代。早年的nvprof在CUDA 10之后基本废弃了新项目直接用Nsight系列。很多人第一次接触这俩工具会混淆我帮你理清分工Nsight Systems命令行是nsys做全流程时间线的分析。它能看到CPU上的API调用、CUDA kernel的启动和结束、内存拷贝、CUDA graphs、多流之间的重叠情况。回答的问题是哪个阶段耗时最长kernel有没有和拷贝重叠CPU有没有拖GPU后腿。这是你拿到一个程序后第一个该跑的工具。Nsight Compute命令行是ncu针对单个kernel做深度分析。它会对kernel做多次重放replay测量SM内部的各类硬件计数器——计算吞吐、访存吞吐、warp状态、寄存器分配、branch divergence、shared memory bank conflict等。回答的问题是这个kernel为什么这么慢瓶颈在计算还是访存。这是精确定位kernel内部瓶颈的第二站。我建议的统一流程是先用nsys看全局找出最耗时的3~5个kernel再用ncu去逐个分析这几个kernel内部到底发生了什么。直接拿ncu扫全程序会非常慢因为每个kernel都要重放很多次。常用的两个命令模板# 全局时间线分析跟踪CUDA和NVML nsys profile --tracecuda,nvtx,osrt --outputmy_profile -o report python train.py # 对指定kernel做深度分析输出到report.ncu-rep ncu --set full --kernel-name regex:kernel_name --launch-count 3 --export report ./my_app3.2 PyTorch训练怎么profiletorch.profiler实操做深度学习训练的GPU profiling我一般不会直接上Nsight先用PyTorch自带的torch.profiler快速定位热点算子。它的好处是能直接把算子名、CPU耗时、CUDA耗时、显存占用对应起来免去从CUDA kernel名字反推PyTorch操作的心智负担。一段最常用模板from torch.profiler import profile, ProfilerActivity with profile(activities[ProfilerActivity.CPU, ProfilerActivity.CUDA]) as prof: for step in range(10): train_one_step() prof.step() # 每个step打一个标记 # 按CUDA时间排序输出前20个算子 print(prof.key_averages().table(sort_bycuda_time_total, row_limit20))看输出表的时候有个关键心法先看cuda_time_total前几名是不是符合你的预期。如果你以为瓶颈是Attention结果排第一的是DataLoader到GPU的传输那问题在IO管线而不是模型。我排查过很多训练慢的案例第一热点经常是aten::to或cudaMemcpy这种拷贝瓶颈根本不该靠优化kernel解决而是要在数据管线上动手prefetch、持久化worker、直接加载到GPU端。torch.profiler还有一个很实用的with_stackTrue参数能把算子对应的python调用栈打出来定位是哪一行代码触发了这个算子。在复杂的训练脚本里找到底谁的显存/耗时暴涨这个参数能省很多时间。3.3 集群和云GPU场景DCGM Prometheus持续画像单机排障可以交互式跑nsys但上了集群、云GPU你需要的是持续采集的profiling/监控数据。NVIDIA官方的DCGMData Center GPU Manager是目前最成熟的方案。我推荐的最小可用组合是dcgm服务采集所有GPU的利用率、显存、SM占用、PCIe吞吐、温度、功耗、uncorrected errors。dcgm-exporter把指标暴露成Prometheus格式。Prometheus Grafana负责存储和可视化。这套东西的价值在于你可以拉出时间维度上的画像。比如训练任务每天凌晨某个时段GPU利用率骤降配合时间线一看发现是另一个定时任务抢占CPU导致数据加载变慢——这种跨组件的问题单靠一次profile根本看不出来必须靠持续监控数据。很多用Kubernetes的朋友会在上面叠加GPU虚拟化或调度配额比如热搜里有人提到k8s调用GPU、GPU资源分配、根组织云原生的GPU配额这里我提醒一句虚拟化/配额层的profiling和裸金属完全不同。如果GPU被多个任务分时共享单个任务看到的nvidia-smi利用率是别人的profile时间线也会被其他任务插队。这时候要先确认有没有MIG、时间片切分一类的机制再看结果才有意义。3.4 Intel GPU和AMD GPU的profiling工具并非所有人都在NVIDIA生态里。热搜词里出现Intel UHD Graphics昇腾系列GPU说明现在异构设备的谱系已经很宽了。Intel GPU带核显的机器做profiling可以用Intel自家的VTune Profiler它的GPU analysis能看EUExecution Unit利用率、访问带宽、shader占用。如果是跑oneAPI程序Level Zero接口下还有ze_tracer这类工具。AMD方面对应的是ROCm生态工具叫rocsolver/rocprof和OmniTrace能对标Nsight Compute。国产的昇腾系列用的是华为自己的Ascend Profiling工具链API风格也类似。我的个人经验是非NVIDIA平台的profiling工具成熟度普遍落后一截遇到问题先看硬件厂商官方文档别指望社区经验太丰富。日常调试可以先从官方提供的nvidia-smi替代命令开始AMD有rocm-smiIntel有xpu-smi做第一层可用性判断再决定要不要上重型工具。4. 实测案例从GPU利用率20%到定位真正的瓶颈4.1 案例一数据加载瓶颈GPU利用率忽高忽低这是一个非常典型的PyTorch训练场景。某个训练脚本跑起来nvidia-smi里的GPU利用率像心电图一样在0%和95%之间来回跳。第一反应是数据加载太慢但不要凭直觉下结论我用Nsight Systems快速验证。nsys时间线出来后的画面是GPU上有kernel在跑但每个kernel结束之后GPU有一段长长的空白CPU侧的cudaMemcpyAsync调用和DataLoader迭代的耗时占了绝大多数。这说明GPU不是没活干而是喂数据的CPU管线把GPU饿着了。解决办法按优先级排列把DataLoader的num_workers调到4~8让数据在后台线程预处理。开pin_memoryTrue让page-locked内存的H2D拷贝走快路径。用prefetch_factor提前多取几个batch。极端情况下把数据预处理挪到GPU上比如解码、归一化直接用CUDA tensor。改完之后再用nsys看same时间线GPU利用率的锯齿明显消失了。这个案例的教训是profile的value不在于告诉你GPU利用率低而在于告诉你低的原因在哪一层。4.2 案例二小kernel扎堆启动开销吃掉了执行时间另一个我常见的反直觉现象GPU利用率很高但程序还是很慢。表面上看显存带宽也高、SM也忙但总执行时间就是下不来。用nsys看时间线你会看到一串密密麻麻的kernel每个只有几微秒。比如一个推理程序里每个batch切成了几十个很小的elementwise算子。这些kernel本身计算量极小但因为每个都走一遍CPU提交-命令传输-GPU调度的流程launch overhead反而占了60%以上的耗时。这种case的解法是kernel融合。把一连串elementwise操作合并成一个kernel或者用PyTorch的torch.compile或TensorRT做自动化图优化减少kernel数量。CUDA Graph是另一个利器下面章节详述。当你看到时间线上有大量短命kernel时别纠结优化单个kernel的寄存器使用率那是捡芝麻先解决kernel数量和调度开销那才是西瓜。4.3 案例三一个kernel的occupancy和访存冲突用Nsight Compute定位还有一种情况是全局时间线没问题数据加载没问题kernl数量也不多但整个程序就是慢。这种就要用ncu进kernel内部看。我优化过一个自定义的矩阵归约kernel现象是ncu报告里Compute Workload Analysis显示SM吞吐只有峰值的63%。Memory Workload Analysis显示DRAM吞吐接近95%。Warp State Stats显示大量warp在long scoreboard状态等显存数据。这三个数字合起来答案非常明确这是个memory-bound kernelSM算力没满是因为在等数据不是不会算。优化方向不是堆指令而是减少每个线程读显存的次数。我做了两件事一是让每个线程循环加载多个元素到寄存器grid-stride loop做一次访存多算几次二是用shared memory做block内的数据复用让同一block的线程尽量从shared memory拿邻居的数据。改完之后的ncu报告DRAM吞吐从95%降到60%但SM吞吐反而升了总耗时降了40%。这就是典型的访存换计算收益远高于死磕计算指令。5. 驱动层异常排查当profiling撞上硬件故障做GPU profiling不可能只面对正常的程序。我遇到过好几次profile到一半驱动崩了或者设备掉了然后整个排查方向从性能分析转向硬件/驱动故障诊断。这一节把那些高频问题一次说清楚。5.1 dmesg里的XID错误以XID 79为例热搜词里有XID 79这是NVIDIA Linux驱动里的经典错误完整信息一般是GPU has fallen off the bus。我第一次遇到时以为是PCIe插槽接触不良后来发现原因五花八门。排查XID 79的完整链路我整理为先抓证据执行dmesg -T | grep -i xid找到完整的XID条目和它周围几行日志看有没有伴随NVRM字样、温度告警、电源事件。确认供电和散热用nvidia-smi -q -d POWER看当前功耗和最大功耗用nvidia-smi -q -d TEMPERATURE看温度。XID 79在笔记本上经常出现在高负载电池供电的场景因为功耗墙和瞬时电流波动导致GPU瞬间掉链子。检查PCIe链路状态用lspci -vvv看GPU对应PCIe设备的状态确认link width和link speed是否正常比如应该16x的变成8x或1x说明链路在降速。温度过高也会触发PCIe链路降速。尝试降频复现用nvidia-smi -lgc 700锁定一个较低的GPU时钟如果复现频率大幅降低基本可以坐实是供电/散热不稳问题。驱动回滚对比XID 79也跟驱动bug有关虽然不常见。保留一个旧版本驱动做A/B测试注意先nvidia-smi -pm 1或者卸载干净再装。我印象最深的教训是在移动工作站上XID 79常常不是硬件问题而是电源管理策略问题。Windows下混合显卡本子在电池模式切换到核显输出时独显供电被切掉Linux下如果没有正确配置nvidia-persistenced也会出现类似现象。最简单的验证方式插上电源适配器、设置高性能模式再跑一次同样的负载。5.2 Windows下错误代码43的排查Windows设备管理器里NVIDIA显卡报错误代码43是另一种高频问题热搜词里也出现了英伟达gpu错误代码43。这个错误意味着Windows已停止该设备原因是设备报告了问题。对独显笔记本用户来说尤其常见。我的排查顺序是先排除驱动问题到官网下载对应型号的最新驱动用DDUDisplay Driver Uninstaller在安全模式下彻底卸载旧驱动再全新安装。很多43是驱动残留冲突导致的。查供电和显卡切换笔记本上如果BIOS里有独显直连/混合模式选项切换到独显直连试试排除核显切换导致的设备状态异常。检查是否被节能策略禁用设备管理器里右键显卡属性-电源管理看看有没有允许计算机关闭此设备以节约电源被勾选把钩去掉。查硬件接触如果台式机重新插拔显卡和供电线如果是笔记本尽量送修之前确认不是散热问题——过热后芯片虚焊也会出现43。经验上有个规律43如果在刚开机时就出现多半是驱动或固件问题如果用一会儿之后出现往往伴随高热或供电不稳。结合任务管理器里的GPU温度趋势判断方向会更准。5.3 PyTorch装完却用不了GPU验证链路热搜里有pytorch安装教程gpu和验证paddle gpu是否验证成功这类问题本质上是环境验证链路不完整。我每次配新环境都会按这个顺序验证# 1. 驱动层nvidia-smi能看到GPU和驱动版本 nvidia-smi # 2. CUDA运行时层nvcc版本注意它与驱动支持的CUDA版本可以不同 nvcc --version # 3. PyTorch层能否识别GPU python -c import torch; print(torch.cuda.is_available(), torch.cuda.device_count())常见坑有三个pip把PyTorch装成了CPU版本这是最大的坑。直接用pip install torch在某些源镜像上会是CPU版torch.cuda.is_available()返回False。正确做法是去PyTorch官网选择对应的CUDA版本安装命令比如pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121版本号要匹配你的CUDA驱动兼容性。判断方法python -c import torch; print(torch.version.cuda)如果不是类似11.8/12.1这样的数字说明装错了。驱动支持版本低于CUDA要求比如新PyTorch要CUDA 12.x但你的老卡驱动只支持CUDA 11.4。这时要么升级驱动要么装旧版PyTorch。日志往往不会说清楚torch.cuda.is_available()直接就False。WSL/容器里宿主机驱动没打通WSL2里跑GPUWindows侧要有对应的GPU驱动容器里则要确保--gpus all或用NVIDIA Container Toolkit挂载了驱动。排查的时候记住一条主线从上往下逐层验证——驱动层能看到GPU吗CUDA runtime能初始化吗深度学习框架版本匹配吗每一层的失败都往上找原因很少需要直接怀疑硬件。6. profiling只是开始把分析结果变成可落地的优化动作6.1 从profile指标到优化决策的映射表工具跑完报告看了下一步自然是动手改代码。我总结了一份从profile观测到优化动作的快速映射表每次拿到新的report就先对号入座Profile特征瓶颈类型优先优化动作cuda_time_total里拷贝算子占比高数据传输瓶颈预取、pin_memory、数据从GPU端直接生成、拷贝和计算放不同流重叠kernel数量多且每个都很短launch开销瓶颈kernel融合、CUDA Graph、torch.compile/算子融合SM吞吐高但DRAM吞吐也接近峰值访存受限减少全局访存、用shared memory复用、调整访问模式的合并访问SM吞吐低且warp long scoreboard延迟受蔽不足提高occupancy、增加并行度、减少寄存器用量branch divergence指标高控制流分歧重排数据让同一warp走同分支、用算术替代分支Kernel时间规律性波动配合GPU利用率锯齿上游数据管道瓶颈优化DataLoader/IO、多流异步执行这张表的背后逻辑很简单profile给你的不是答案是线索。每个指标对应一条优化路径你在实际项目中只需要按图索骥。6.2 几个我验证过的实用优化动作针对上面映射表里的高价值动作扩展一下具体落地方案。H2D/D2H拷贝最小化。GPU profiling里最容易被忽视的开销就是CPU与GPU之间的数据拷贝。很多人习惯每个step把tensor.cpu()拿回来打印一下loss多几次这种操作拷贝就占了训练时间的1/3。优化思路是批量同步、异步拷贝、让拷贝和非依赖计算在不同CUDA stream上重叠。nsys时间线里如果看到cudaMemcpy和kernel是串行的那说明stream使用有优化空间。CUDA Graphs是小kernel扎堆的终极解法。这个技术把一连串kernel launch在host侧录制成一个graph对象然后一次性提交执行免去每次launch的驱动开销。PyTorch里可以这样粗粒度地体验from torch.cuda.graphs import make_graphed_callables graphed_fn make_graphed_callables(my_model, sample_args)实测在大量小kernel的模型上整体速度提升10%到30%很正常。但注意CUDA Graph在动态shape、有数据依赖分支的场景下会有约束不适合无脑套用。混合精度不是降精度是提速手段。FP16/FP32混合精度训练能显著降低访存带宽压力对memory-bound的模型尤其有效。但要小心梯度下溢和精度损失PyTorch的torch.cuda.amp已经做了loss scaling遇到不收敛再逐渐关掉。用ncu对比一下开启混合精度前后DRAM吞吐的变化你会直观看到为什么它能提速。kernel融合的正确姿势。融合不是把所有逻辑堆到一个kernel里就行。我见过有人把不相干的逻辑硬融进去结果寄存器爆炸、occupancy暴跌反而更慢。正确的判断标准是要融合的操作之间有数据依赖一个的输出是另一个的输入且融合后每个线程的工作负载适中、不会导致资源超卖。用ncu比较融合前后kernel的SM吞吐和耗时用数据说话。6.3 优化闭环改完一定要再profile一次我犯过的最大错误是——改完代码觉得肯定更快了然后就没再跑profile直接上线。结果往往是被隐藏的问题在另一个维度爆发数据加载快了但GPU在等kernel同步kernel快了但显存碎片化导致OOM。我的习惯是每次优化改动之后必须跑一次和基线完全相同的profile命令对比关键指标。基线profile文件保留在项目目录里比如baseline_nsys.sqlite、baseline_ncu.ncu-rep改动后用同样的命令生成新报告两者用Nsight的diff功能对比或者自己盯core指标——总耗时、Top-5 kernel耗时、DRAM吞吐、occupancy。这种优化-复测的循环比任何一套优化口诀都重要。因为GPU程序的性能受硬件、驱动、数据shape、批大小影响太大没有基线对比你很难判断一次改动到底是变好了还是变坏了。7. 写在最后一点个人的实操体会用了这么多年GPU profiling工具我最大的体会是工具只是镜子照出问题的从来不是工具本身而是你对程序执行模型的判断力。nvidia-smi看一眼就能判断利用率高就是快当然简单但它会让你漏掉最核心的问题——GPU忙什么才是关键。如果让我给刚开始接触GPU profiling的朋友一个建议那就是从最小的单kernel开始建立基线。写一个简单的矩阵乘法或者归约kernel分别用nsys和ncu跑一遍把每个指标的含义对应到自己写的代码上。这个过程花不了半天但它建立的心智模型会让之后遇到GPU利用率低XID 79PyTorch识别不到GPU这些问题时第一反应是查哪一层、看哪个工具、用什么逻辑排除而不是去抖音搜玄学教程。这条路我自己就是这么走过来的确实值得你走一遍。
返回列表