资讯详情

GPU利用率低?六大瓶颈排查清单与优化实战

📅 2026/11/2 9:17:31 | 华诺云谱 👁 阅读
GPU利用率低?六大瓶颈排查清单与优化实战
前段时间我在排查一个训练任务loss掉得很慢跑了好几天还在高位震荡。打开nvidia-smi一看GPU利用率只有20%出头显存占用倒是很高但SM流处理器大部分时间在闲着。最让人头疼的是这任务看起来还在跑就是进度条纹丝不动整个团队都在等我给个说法。这种情况如果你也遇到过那几乎可以确定问题不在模型本身而在“模型外面”——数据供给、CPU预处理、内核调度、显存管理、多卡通信、资源竞争这六个环节随便卡一个GPU都会饿到干等。做AI训练的人每天盯GPU利用率但利用率低这件事从来不是只看GPU就能解决的。这篇文章我会把自己实际排查时用到的思路、命令、工具和避坑经验整理成一份清单帮助你一步步定位瓶颈到底在哪里而不是瞎调BatchSize或盲目加卡。因为实际排查GPU利用率低关键不是“把数值调高”而是搞清楚“GPU的时钟周期到底花在了哪里”。一个真正可用的排查思路是从GPU观察到的现象出发沿数据流方向逐一排除最后用Profile工具确认根因。下面直接进入正题。1. 先用NVIDIA工具定位“时间去哪了”——利用率指标别只盯着一个数1.1 nvidia-smi显示的数字到底是什么意思很多人的第一反应是打开终端跑一句nvidia-smi看到Utilization只有20%就开始怀疑GPU坏了。但这里有个常见的误解nvidia-smi显示的GPU-Util指的是一段时间内GPU上有计算指令执行的百分比它不区分是在跑你的核心业务逻辑还是在空转刷显存。举个例子如果你的代码里频繁调用一次很小的kernelGPU可能一直在执行指令nvidia-smi显示利用率不低但实际上大量时间浪费在了内核启动和同步等待上。更要命的是nvidia-smi默认是每1秒采样一次实时性还可以但看不到单个kernel的长短和间隔。想定位瓶颈第一步就要养成熟练查看这些工具的习惯不仅是nvidia-smi还要会用nvtop这种按进程实时展示SM、显存、编码器占用率的工具。当然它们只能告诉你“GPU忙不忙”无法回答“GPU忙得值不值”。真正要判断“值不值”必须看到时间线上的数据流CPU在做什么、数据传输用了多久、kernel执行时长和间隔。这也是为什么我建议所有跑训练的人都应该掌握NVIDIA Nsight Systems的基础用法它是定位瓶颈的第一利器。1.2 用Nsight Systems给训练任务拍一张“时间轴照片”Nsight Systems通常简称nsys能记录CPU、GPU、CUDA API、内存拷贝、内核执行等事件生成一张时间线。我第一次用的时候看到时间线上CPU侧一大片蓝色等待、GPU侧零星几个小尖峰整个问题瞬间清晰了根本不用猜。常用命令是这样的# 截取训练前几百个iteration分析 nsys profile --tracecuda,nvtx,osrt --outputprofile_report -f true \ python train.py --max-steps 200跑完之后会生成一个.nsys-rep文件用Nsight Systems GUI打开。重点看两个东西CPU侧的CUDA API调用时长。如果cudaMemcpy、cudaLaunchKernel之间的间隔特别长说明数据准备或Python调度卡住了。GPU侧每个kernel的执行时长和相邻kernel之间有没有明显空隙。如果kernel间空隙远大于kernel本身说明GPU在等CPU喂数据或等同步。如果你连GUI都不想装也可以用nsys stats快速输出汇总统计nsys stats --reportcuda_gpu_trace --formatcsv profile_report.nsys-rep然后按kernel总时长排序基本能锁定是哪个算子占用最多。不过要注意Nsight Systems会显著拖慢训练速度我只建议在测试场景或前几十个iteration做不要在正式训练时开。1.3 从时间线快速判断瓶颈类型我总结过一套简单的判断方法非常直观分享给你时间线特征可能的瓶颈CPU侧密集GPU侧稀疏数据加载、Python预处理、GIL锁GPU侧有kernel但kernel间空隙巨大CPU指令发射慢、数据拷贝慢、等待同步单个kernel执行时间长且利用率高算子本身计算密集需考虑算子优化或换更快的实现多GPU训练中GPU之间互相等待通信瓶颈、负载不均、AllReduce开销显存占用高但SM占用低BatchSize过大导致频繁换页或模型内含大量稀疏/空白计算从这一步开始你就不再是盲目猜了。接下来围绕最常见的六个瓶颈一点一点拆解。2. 瓶颈一数据供给跟不上——Dataset和DataLoader是首个嫌疑人2.1 为什么数据加载会成为GPU饿肚子的根源训练循环的本质是CPU把数据从磁盘或内存取出来做预处理然后拷到GPU显存GPU算完再取下一批。如果一批数据要500毫秒才能准备好而GPU算一批只要100毫秒那GPU有80%的时间都在空转利用率自然上不去。尤其是现在图像、视频、大语言模型的token序列越来越大一个样本几MB甚至几十MB磁盘IO和预处理很快就成了短板。我自己踩过最典型的坑数据集存在机械硬盘上一个epoch要读取上千个文件DataLoader的num_workers已经调到16但GPU利用率始终上不去。后来用iostat -x 1一看磁盘util接近100%avgqu-sz排队长度惊人。换成NVMe固态盘之后同样的训练配置GPU利用率从45%直接跳到80%以上。你说问题在模型吗根本不在。2.2 数据瓶颈的排查命令与指标排查数据供给瓶颈比想象中简单。只需要开几个终端窗口同时监控这几个指标# 实时看磁盘IO重点看 %util、await、avgqu-sz iostat -x 1 # 看整体IO吞吐和CPU上下文切换 dstat -d -c -i 1 # 看进程实际状态如果有大量D状态进程说明在等待IO top -d 1如果你用的是PyTorch还可以在代码里给Dataset做更精细的记录单独测量单个样本读取时间单独测量预处理时间分别打印出来。很多时候瓶颈不在于磁盘而在预处理逻辑。比如我见过有人每次迭代都对大图做JPEG解码、随机裁剪、翻转、归一化这些全在CPU主线程里做GPU当然等你。这时候要用torch.utils.data.DataLoader里的num_workers和prefetch_factor把预处理并行化。一个实用的判断标准如果nvidia-smi显示GPU利用率低同时top显示多个python子进程CPU占用接近100%那数据管线大概率有并行度不够的问题。如果磁盘%util长期100%那就是存储系统扛不住了。2.3 数据管线优化手段和实操经验优化数据管线优先级我建议这样排把数据集放在NVMe固态盘或内存文件系统里别用机械硬盘或网络盘网络文件系统尤其坑随机小文件读取性能极差。使用DataLoader时设置合理num_workers一般建议等于CPU物理核数的一半到全部但别贪多太多反而会导致频繁切换上下文。用prefetch_factor预取多批数据默认是2可以适当调大。如果数据读取不需要实时最好把预处理结果落盘成缓存格式例如TFRecord、WebDataset、或者pickle打包减少重复解码。做实验时用合成数据random tensor跑一遍逻辑。如果合成数据下GPU利用率很高而真实数据下很低铁定是供给链路的问题。有一次我就是这么干的用torch.utils.data.DataLoader加载一堆随机Tensor跑GPU利用率94%换真实数据只有60%立刻定位到是数据侧。后来检查发现是数据集中有个字段每次都要从数据库查询执行一次要200ms把它改成启动时预载到内存后问题直接消失。这类问题如果只看GPU利用率根本发现不了。3. 瓶颈二CPU预处理和GPU之间的“流水线错位”3.1 num_workers的真相和常见误区数据管线优化时很多人喜欢把num_workers调到很大以为越大越快。但实际上这个参数控制的是“有多少个独立的进程同时去加载和预处理数据”不是“越多越好”。如果你的预处理本身很轻量开太多进程反而会因为进程间通信、内存拷贝的代价拖慢整体速度。我见过一个反直觉的案例把num_workers从8调到12GPU利用率不升反降因为每个子进程都在抢占CPU资源主进程反而拿不到足够的CPU来执行模型调度。正确做法是结合你自己的CPU核数和预处理复杂度来定。一个可行的起步点物理核数的1到2倍然后再观察调整。同时也要注意pin_memoryTrue是否开启这个参数可以把CPU内存中的数据页锁定加速CPU到GPU的拷贝很多时候打开它就能提升几个百分点的利用率。3.2 prefetch、pin_memory和流水线深度想象一条流水线读磁盘、预处理、传GPU、计算每一步都需要时间。如果每一步单独跑总耗时就是四段相加。但如果把它们放到不同进程/线程里重叠执行总耗时就能缩短到最慢的那一段。DataLoader的prefetch_factor控制“预先加载多少批数据到内存”其实就是加深流水线。默认2可能不够调成4或8可以缓解短时突发IO导致的等待。pin_memoryTrue的作用类似于为GPU传输专门准备了一条“直通车道”。正常CPU内存可以被换页而锁页内存不会被换出因此host到device的拷贝能跳过一部分地址转换开销。虽然它不是万能的但成本几乎为零建议默认打开。还有一点容易被忽略如果你的预处理里用了不兼容多进程的对象例如lambda函数或某些自定义类没有实现序列化PyTorch会退化成主进程加载——也就是num_workers全无效。我在代码里碰到过因为Dataset里持有threading.Lock导致多进程worker全部卡住GPU利用率掉到接近0。遇到这种问题建议在worker_init_fn里显式初始化避免把不可pickle的对象通过继承传到子进程。3.3 实战案例CPU占用低但GPU等待高有一次现场排查GPU利用率只有30%但CPU占用也才40%两边看起来都不忙这就非常奇怪了。后来用nsys看时间线发现GPU侧kernel执行正常但每次kernel之间都有一段“神秘间隔”而且CPU侧的cudaMemcpyAsync调用迟迟不返回。再往下查发现代码里用了tensor.item()去同步获取一个标量每步都触发了一次GPU到CPU的同步拷贝等于强制把流水线打断了。这种问题非常隐蔽因为tensor.item()在脚本里只是一个取值操作但它背后意味着设备到主机的同步等待。解决的方法也很简单把需要的标量放到GPU上用torch.Tensor操作或者聚合到一定步数后再同步取值。排查同步等待有一个小技巧在Nsight timeline里搜索Sync或cudaDeviceSynchronize标记一旦频繁出现基本就是在“假并行”。4. 瓶颈三内核启动与GPU利用率虚高——你的“利用率”可能不是有效计算4.1 内核启动开销为什么小算子堆起来的模型特别慢GPU和CPU不一样CPU喜欢顺序执行GPU则适合大规模并行。但每次把kernel发射到GPU上都有固定开销包括命令解析、上下文切换、依赖检查通常约为5到10微秒。单个kernel如果执行时间只有几微秒那启动开销占比就非常惊人。典型例子是小模型或推理场景或者模型中存在大量element-wise操作例如逐点激活、归一化、dropout mask生成。这类算子本身计算量不大但数量极多GPU在一层一层地调度中浪费时间。表现就是时间线上几十个短kernel连在一起每个都很短但间隔接近kernel自身长度。这种场景下的GPU利用率数字可能显示80%但实际“有效FLOPs”可能只有一两成。要判断这类问题最简单的方式是在Nsight Systems里看kernel平均时长。如果大量kernel时长小于5微秒就要考虑算子融合了。4.2 用Nsight Compute分析kernel内部的资源利用率Nsight Systems告诉你kernel占了多少时间Nsight Computencu则能钻进单个kernel内部看SM的占用率、warp占有率、内存流水线、分支发散等情况。用法大致是# 指定只profiler一个kernel用kernel name或序号 ncu --set full --launch-count 1 -k regex:matmul python train.py重点看SM Busy和Memory Throughput两个指标如果SM很忙但Memory很闲通常说明计算密度高可以尝试更高效的算法或降低精度。如果Memory很忙但SM较闲说明访存受限要考虑合并访问、数据结构紧凑化。如果两者都很低那可能是warp占有率不够也就是并行线程太少无法填满GPU延迟隐藏的能力。这里必须提一个核心概念GPU利用率低很多时候不是“不忙”而是“忙在等待上”。每个SM有最多可驻留的warp数量如果你的线程块太大或寄存器占用过多能驻留的warp变少当部分warp在等待显存返回时没有足够多的其他warp顶上SM就空转了。幸好现代深度学习框架中这种问题相对少但自定义算子或极端模型的层里很容易出现。4.3 减少内核启动开销算子融合、自动混合精度与cuDNN benchmark解决小算子爆炸和启动开销最直接的手段是算子融合。把多个相邻的逐元素操作合成一个kernel比如把add和relu合并成bias_relu可以由编译器自动完成也可以手写CUDA实现。框架层面最省事的做法是打开torch.compilePyTorch 2.0它会在后台做kernel fusion效果常常立竿见影。另外我建议训练时固定开启torch.backends.cudnn.benchmark True这会让cuDNN在第一次迭代时尝试多种卷积算法选出最快的一个缓存下来。如果你的输入尺寸固定这个设置几乎百利无一害但要注意如果输入尺寸频繁变化benchmark本身会增加额外开销这时反而要关掉。混合精度和TF32也是优化利器。在Ampere及以上架构的GPU上TF32能显著加快矩阵运算对很多模型精度影响很小。而FP16/BF16混合精度则是目前训练大模型的主流做法不仅省显存还能让GPU利用率更饱满。有不少人跑大模型训练利用率低其实是因为默认用了FP32显存带宽撞壁SM大部分时间在等数据。换成BF16混合精度后利用率立刻提升。关于“利用率虚高”我再分享一个经验有些框架比如TensorFlow老版本会把“GPU在执行kernel的时间占比”记为利用率即使kernel效率极低。所以排查时不要轻信面板上的数字一定要结合loss下降速度来评估。如果loss下降慢、kernel内部效率也不高那就要从计算密度和访存模式入手了。5. 瓶颈四显存不够导致的频繁换页与BatchSize误调5.1 OOM与显存溢出带来的“假训练”显存问题看似简单实际坑很多。最直接的情况是显存溢出OOM代码直接报错退出这个反而好排查。麻烦的是显存没爆但接近满载时GPU驱动为了给新数据腾空间可能把旧数据挪到主机内存或者执行缓慢的分配/释放。我的经验是如果nvidia-smi里显存占用长期在95%以上或者训练过程中显存数字在周期性大跳一定要警惕换页和碎片化。一个更隐蔽的场景你用了CUDA的unified memory或自定义了显存分配策略比如PyTorch的torch.cuda.memory_stats()可以看allocated_bytes.all.peak。我把这个值打出来之后发现模型权重和优化器状态占了一大半可用空间就剩一点每次分配新张量都触发cudaMalloccudaMalloc本身非常慢直接拖低GPU利用率。5.2 BatchSize和GPU利用率的关系很多人一看到GPU利用率低第一反应是调大BatchSize。大方向没错但不绝对。在数据管线正常的前提下调大BatchSize能让每个GPU iteration处理更多数据计算密度更高利用率随之提升。但BatchSize过大也会带来副作用显存不够、优化收敛变慢、batch内平均梯度不代表真实分布。我的建议是先观察“BatchSize增加后单iteration的总耗时如何变化”。如果耗时近似线性增加说明计算密集型主导可以继续加大如果耗时增加不明显说明瓶颈可能在数据管线或CPU侧加大BatchSize并不能解决问题。一个简单的测量方法# 在训练脚本里统计每个iteration耗时 python -c import torch, time # ... dummy model ... for i in range(20): t0time.time() loss.backward() optimizer.step() print((time.time()-t0)*1000) 用这个方法你可以快速建立“BatchSize-耗时”曲线。如果你发现从batch32调到batch128耗时只从100ms涨到120ms说明GPU计算还远未饱和主瓶颈在别处。反之如果耗时从100ms涨到350ms说明算力基本吃满了利用率没问题问题可能在于模型收敛策略。5.3 梯度累积的正确用法和常见误区梯度累积可以帮你突破“显存不够导致batch太小”的限制。比如你想用batch512但单卡显存只能塞下batch64那就可以每8步做一次优化器更新等效batch512。这在分布式训练中也常用。但务必注意梯度累积不等于每一小步的GPU利用率都会提高。它在逻辑上等价于把大的batch拆成多个小batch串行处理如果小batch的计算密度本身不够梯度累积只是缓解显存限制并不能解决利用率低的问题。而且梯度累积会引入额外的同步点如果每次累积后都调用optimizer.zero_grad()也会打断kernel流水线。建议用optimizer.zero_grad(set_to_noneTrue)比zero_grad()更省显存和带宽。如果显存足够我通常不建议过度使用梯度累积。对单卡训练而言有更干净的方法把BatchSize加大到显存允许的上限同时适当降低batch内样本的解析规模比如小图、短序列利用率自然就上去了。6. 瓶颈五多卡训练时的通信与负载不均6.1 AllReduce带来的等待GPU在等谁一旦进入多卡分布式训练GPU利用率低的原因又多了一类通信等待。最典型的是同步SGD中每张卡算完梯度后必须全局求平均这个过程就是AllReduce。假设8张卡每张卡算完的时间都不一样快卡必须等慢卡到了才能一起AllReduce。快卡算完了但没事干GPU利用率显示下降。再加上网络传输本身耗时通信占比可能远高于你的预期。先说个判断经验如果单卡训练时GPU利用率90%多卡训练只有60%那基本就是负载均衡或通信开销导致。先用nvidia-smi topo -m查看GPU之间的拓扑连接方式是NVLink、PCIe还是通过主机内存走QPI/UPI这决定了通信带宽上限。建议做一次NCCL的快速基准测试用官方脚本nccl-tests里的all_reduce_perf来测单机多卡的实际通信带宽# 在安装了NCCL的容器里运行 mpirun -np 8 ./build/all_reduce_perf -b 128M -e 1G -f 2 -g 1如果带宽远低于理论值优先看PCIe链路和NVLink是否降速。NVIDIA的nvidia-smi topo -m会输出一张拓扑表如果两张卡都在同一个PCIe Switch下通信会快很多如果跨NUMA节点通信要走CPU慢很多。6.2 通信占比与梯度压缩、梯度累积的取舍判定通信是不是瓶颈可以比较每个iteration里“通信时间”和“计算时间”。NCCL在训练日志里通常会有平均值或者你用nsys也能看到ncclKernel的时间占比。如果通信时间超过总时间的30%就值得优化。优化方向有几种一是用梯度压缩/稀疏化减少通信量二是用梯度累积让通信频率降低——比如本机每4个micro-batch才做一次AllReduce三是调整NCCL的环境变量例如NCCL_P2P_LEVEL、NCCL_BUFFSIZE在某些硬件组合下能明显改善四是用分桶通信把梯度的AllReduce和反向计算重叠。PyTorch DDP默认已经把梯度和反向计算重叠了一部分但如果你的网络层很多、每层梯度都小通信次数会爆炸可以设置bucket_cap_mb合并小张量。另一个容易被忽视的点多机训练时网卡质量直接决定上限。如果只有千兆网卡数据传输慢到让人崩溃至少需要25GbE或InfiniBand。如果只能走TCP那一定要打开NCCL的NCCL_SOCKET_IFNAME指定正确的网卡否则它可能走了错误的网络路径。6.3 负载不均的问题有些卡就是“偷懒”即使通信带宽没问题多卡利用率低也可能是各卡负载不均。常见的负载不均来源有数据采样不均衡有些worker拿到了特别长的样本需要计算时间更久、机器里有其他任务抢占资源、或者使用了非同步模式的Async SGD。检查方法也很简单在多卡训练时分别看每张卡的GPU利用率。如果是PyTorch DDP通常每张卡利用率应该非常接近。如果某张卡长期低于其他卡多半是它的CPU数据供给或者通信出了问题。可以用# 每0.5秒刷新一次带进程信息 watch -n 0.5 nvidia-smi或者写一个小脚本采样每张卡当前的sm利用率并画图。我排查过一个案例4卡训练中第3张卡一直只有40%另外三张卡95%。后来发现负责给第3张卡feed数据的CPU核心被别的任务占满了数据生成速度跟不上。把num_workers分散到其他NUMA节点CPU上后立刻恢复到90%以上。6.4 多卡调试的另一个经验设置环境变量是真的有讲究NCCL在不同硬件拓扑下的行为差异很大我建议在跑大规模训练前先用nccl-tests在不同环境变量组合下各跑一遍记录最优参数。比较常见的组合export NCCL_P2P_DISABLE0 export NCCL_IB_DISABLE0 export NCCL_P2P_LEVELPXB export NCCL_BUFFSIZE16777216但请记住这些参数没有普适最优解。有一回我们为了提升通信强制NCCL_P2P_LEVELNVLink结果因为某些节点GPU没有被NVLink连接反而走了更慢的路径性能降低一倍。所以任何环境变量修改都要用基准测试验证不要人云亦云。7. 瓶颈六资源竞争与后台杂讯——容易被忽略的“邻居噪音”7.1 CPU核心被抢占、内存带宽不够GPU利用率低但CPU侧检查了数据管线没问题通信也没问题这时候你就要把视野放到“整个机器”上了。最典型的敌人是共享机器上的其他任务。如果你在用公有云或内部K8s集群别的容器可能会抢CPU、占内存带宽、打满磁盘IO。有时你自己没申请那么多资源但宿主机的其他进程也会干扰你。排查命令# 看整体负载和核心使用 uptime top -E k # 看内存带宽压力需要perf工具 perf stat -e uncore_imc/data_reads/,uncore_imc/data_writes/ -a sleep 10 # 看NUMA均衡 numastat -p pid如果整体负载很高而你的进程CPU占用也不小但GPU就是等那就可能是内存带宽撞墙了。现代CPU核心越多但内存带宽是共享的。数据加载进程如果大量占用内存带宽GPU把数据从CPU内存搬到显存的速度就会受影响。7.2 多任务共享GPU时的利用率假象还有一种情况同一张GPU上跑了多个训练任务。从nvidia-smi看单张卡利用率100%但你的任务实际只分到了一部分SM。NVIDIA的MIG技术会做物理隔离但默认情况下多进程是共享GPU的每个任务能用的SM数量不固定。如果你的利用率显示低先检查是不是有其他任务占用了这块卡。用nvidia-smi --query-compute-appspid,used_memory,utilization.gpu --formatcsv可以查看当前GPU上有哪些进程在跑以及各自占的算力和显存。如果你发现自己任务显存占了几GB但utilization.gpu里都是别的进程那就说明你在“捡漏”式地共享GPU性能波动非常大。这个问题在团队共用训练服务器时尤其常见。我的建议是用CUDA_VISIBLE_DEVICES明确指定自己的GPU编号别让它自动选。如果有多张卡可以按任务类型划分训练任务独占卡推理任务用小号卡或MIG切片。如果不得不共享至少用torch.cuda.set_per_process_memory_fraction限制自己的显存上限防止一山不容二虎导致OOM。7.3 排查资源竞争的系统级命令速览这里我给一份适合在排查阶段轮流敲的命令清单命令查看内容适用场景top -d 1 -c进程CPU、内存占用找CPU吃满的进程htop更友好的CPU/内存视图快速确认NUMA核使用iostat -x 1磁盘IO等待数据盘慢dstat -c -d -m -n 1整体系统资源多维度概览free -h内存余量内存不足导致swapvmstat 1进程、内存、IO、CPU调度定位系统级饿死nvidia-smi -l 1GPU实时状态看GPU利用率波动nsys/ncu内核与时间线精确定位kernel问题另外不要忽略内核日志。如果GPU设备出现nvidia-smi里的“ERR”状态或者dmesg里有NVML报错那可能是驱动或硬件层面的问题。这种故障会让GPU利用率显示异常甚至拒绝执行kernel。遇到过几次后我的习惯是任何一次训练前先跑一个简单的CUDA向量加法脚本确保驱动和显卡通信正常。8. 一份可直接抄的GPU利用率排查清单含命令速查8.1 一页纸排查流程从现象到根源我把整个排查思路浓缩成六个步骤按顺序走基本能覆盖90%的利用率低问题确认“利用率低”是真的低看nvidia-smi、nvtop、loss下降速度排除利用率虚高。判断是单卡还是多卡单卡先看时间线多卡先看每卡利用率差异和通信。用Nsight Systems截取一小段训练时间线区分CPU等待、GPU执行、通信、拷贝四大块。针对时间线特征按前面五个瓶颈依次排查数据供给→CPU预处理/同步→kernel效率→显存占用→通信与负载。用Nsight Compute深入有嫌疑的kernel看SM Occupancy和Memory Throughput。修复后重新采集时间线对比优化前后同一阶段的时间开销。这套流程听起来很繁琐但实际上手很快。对绝大多数情况第3步的时间线已经能给出80%的结论后面所有操作都只是验证。8.2 常用命令速查表按瓶颈分类瓶颈类型核心命令关键指标数据供给iostat -x 1、dstat -d磁盘%util、await、avgqu-szCPU预处理top、htop、vmstat每个进程CPU%、上下文切换内核启动nsys stats --reportcuda_gpu_tracekernel平均时长、间隔显存问题nvidia-smi、torch.cuda.memory_stats()显存峰值、碎片、OOM多卡通信nccl-tests/all_reduce_perf、nvidia-smi topo -mAllReduce带宽、通信耗时占比资源竞争top、free -h、dmesg -T负载、内存、GPU错误8.3 我的几个压箱底习惯排查GPU利用率这件事其实考验的不是会不会敲命令而是对“整个数据流”有没有直觉。这里把我个人压箱底的几个习惯分享给你不一定适合所有人但至少给了不少同事帮助在训练脚本里每隔一定步数打印一次GPU利用率和iteration耗时做成日志。训练完再回看能发现很多“当时没注意”的规律。做任何大数据集实验前先跑100步随机数据建立该模型在“无供给瓶颈”时的GPU利用率基线。没有基线后面所有排查都无从谈起。修改参数时一次只改一个变量改完必须重新测时间。同时改num_workers、batchsize、混合精度出了问题你根本不知道谁导致的。遇到莫名其妙的利用率跳变先怀疑“定时任务”。我遇到过好几次训练利用率周期性掉到0最后发现是系统每小时跑一次updatedb磁盘IO爆炸把数据管线全部卡住了。排查这类问题vmstat里wa列会告诉你答案。看GPU利用率时同时看一眼nvidia-smi里的Volatile GPU-Util在部分新版驱动中已改叫utilization.gpu和Temperature。如果温度高到降频利用率再高也是白搭性能其实在打折。最后想多说一句很多人把GPU利用率低归结为“代码写得不行”但实际排查下来大部分问题都出在数据管线和系统环境上。如果你手里的模型本来就有大量小算子算子融合和降精度带来的收益往往比换更大显存的卡更直接。这就像一个熟练的机修工不会看到转速低就猛踩油门而是先检查是不是进气管堵了、是不是离合打滑了。对应到GPU训练你的进气管就是整个数据链路离合就是通信和内核调度。以后遇到“GPU利用率只有20%”的情况别急着发帖求助先对着这份清单过一遍。你会发现很多瓶颈根本不需要改模型结构只需要调整几个参数就能把利用率拉到80%以上。这个过程本身就是做AI工程最有意思的部分。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑