大规模深度学习性能调优:自顶向下的五件套

news2026/5/14 19:34:44
GPU 利用率上不去显存莫名 OOM分布式训练卡死不动这些问题不能靠再加一张卡解决必须靠 Profiling 把瓶颈找出来。性能调优的正确顺序是自顶向下先在框架层看哪个算子慢再下到系统层看 CPU/GPU 时间线最后下到 GPU 芯片内部看微架构。每一层都有专属工具越往下越精细但开销也越大。错用工具——比如用 Nsight Compute 跑整个训练循环——会让程序慢上百倍得不偿失。下面这五件套覆盖了从框架到硬件的全栈是我日常排查的标准武器库。一、PyTorch Profiler第一手排查工具什么时候用90% 的性能问题用 PyTorch Profiler 就能定位。典型场景不知道哪个算子最耗时怀疑 DataLoader 读图太慢导致 GPU 在空等GPU Starvation显存峰值排查OOM 原因它的优势是几乎不用改代码套个 Context Manager 就行。用法一导出给 TensorBoard 看图形化import torch prof torch.profiler.profile( activities[ torch.profiler.ProfilerActivity.CPU, torch.profiler.ProfilerActivity.CUDA, ], # 预热1步,记录2步,避免Profiler本身带来过大开销 scheduletorch.profiler.schedule(wait1, warmup1, active2, repeat1), on_trace_readytorch.profiler.tensorboard_trace_handler(./log/resnet_profile), record_shapesTrue, # 记录Tensor形状 profile_memoryTrue, # 记录显存分配 ) prof.start() for step, data in enumerate(dataloader): train_step(data) prof.step() prof.stop()然后tensorboard --logdir./log/resnet_profile。重点看三个视图Trace 视图找DataLoader Wait时间块。如果 GPU 时间线上有大段空白多半是数据加载拖了后腿Operator 视图看Self CUDA Time排行榜谁排第一谁就是嫌疑犯Memory 视图显存随时间的曲线OOM 之前一定有异常的尖峰用法二直接在终端打印表格轻量、快速懒得开 TensorBoard 时,直接 print 一张表更快:import torch import torchvision.models as models model models.resnet18().cuda() inputs torch.randn(16, 3, 224, 224).cuda() # 预热,让GPU初始化完成 for _ in range(3): model(inputs) torch.cuda.synchronize() with torch.profiler.profile( activities[ torch.profiler.ProfilerActivity.CPU, torch.profiler.ProfilerActivity.CUDA, ], record_shapesTrue, ) as prof: with torch.profiler.record_function(my_resnet_forward): outputs model(inputs) # 打印表格,sort_by可以是cuda_time_total / self_cuda_time_total / cpu_time_total print(prof.key_averages().table(sort_bycuda_time_total, row_limit10))终端输出长这样----------------------- ---------- ---------- ---------- ---------- ---------- Name Self CPU % Self CPU Self CUDA % Self CUDA # of Calls ----------------------- ---------- ---------- ---------- ---------- ---------- my_resnet_forward 2.50% 1.200ms 0.00% 0.000us 1 aten::conv2d 0.15% 72.000us 0.00% 0.000us 20 aten::cudnn_convolution 1.50% 720.000us 75.00% 11.400ms 20 aten::batch_norm 0.10% 48.000us 10.00% 1.520ms 20 ... ----------------------- ---------- ---------- ---------- ---------- ---------- Self CPU time total: 48.000ms Self CUDA time total: 15.200ms怎么读懂这张表四个维度必须分清Nameaten::xxx是 PyTorch 底层 C 算子aten::conv2d是卷积aten::add是加法自己用record_function(xxx)打的标签也会出现在这里Self vs Total这是最容易搞混的一对Total Time算子从开始到结束的总耗时包含其内部调用的所有子算子时间。比如aten::conv2d内部会调aten::convolution → aten::cudnn_convolution它的 Total 把底层全包进去了Self Time剔除子调用后该算子自己消耗的时间排查瓶颈时盯紧Self Time。Total 高没意义——它可能只是个壳Self 高才说明这一行真的慢。CPU vs CUDACPU列CPU 下发指令Launch kernel或纯 CPU 算子的耗时CUDA列GPU 真正在硅片上算的时间深度学习场景主要看Self CUDA。# of Calls调用次数。轻量级算子调用上万次,累加起来也很恐怖。比如某个 element-wise 算子单次只有 5us但被调用 50000 次就是 250ms。实战技巧sort_byself_cuda_time_total排序前两三行通常就是罪魁祸首。最常见的惊喜包括自定义的 Attention 实现、低效的 LayerNorm、忘了 fuse 的 element-wise 操作。二、Nsight Systems (nsys)系统级时间线什么时候用PyTorch Profiler 告诉你哪个算子慢nsys 告诉你整个系统在干什么。当你怀疑CPU 准备数据和 GPU 计算没重叠H2DHost to Device数据拷贝阻塞了计算分布式训练里 NCCL 通信和计算没并行就该上 nsys 了。怎么用不用改代码但建议在关键代码段加torch.cuda.nvtx.range(MyOp)打标签nsys 会显示出来。# 标准用法:生成报告文件,本地用GUI打开 nsys profile -t cuda,nvtx,osrt -o my_profile python train.py # 终端汇总用法:加 --statstrue 直接打印文本表格 nsys profile -t cuda,nvtx --statstrue python train.py终端输出--statstrue跑完后 nsys 在终端打印两类核心表格CUDA API 统计CPU 端发出的指令耗时Time (%) Total Time (ns) Num Calls Avg (ns) Name -------- --------------- --------- ---------- -------------------- 45.2% 1,250,000,000 100 12,500,000 cudaMemcpy (H2D) 30.5% 850,000,000 5000 170,000 cudaLaunchKernel ...这个例子里 H2D 拷贝占了 45%瓶颈很清楚——数据搬运太重要么 pin memory、要么改 DataLoader、要么用 prefetch。CUDA Kernel 统计GPU 端真正执行的耗时Time (%) Total Time (ns) Instances Avg (ns) Name -------- --------------- --------- -------- ---------------------- 60.1% 500,000,000 1000 500,000 volta_sgemm_128x64_nn 15.2% 126,000,000 2000 63,000 layer_norm_kernel ...矩阵乘法占 60% 是健康的计算密集型任务理应如此如果某个不起眼的 element-wise kernel 占到 30%那就有问题。GUI 界面看什么终端表格只有汇总真正的价值在 GUI 的时间线。把.nsys-rep下载到本地用 Nsight Systems GUI 打开会看到一张多行时间线CPU 行每个核心在做什么数据预处理、Python 解释器、Kernel LaunchCUDA HW 行GPU 实际执行的 Kernel按 Stream 分行PCIe / Memcpy 行H2D / D2H 数据拷贝NVTX 行你自己打的标签NCCL 行分布式通信AllReduce / AllGather / ReduceScatter排障时盯三件事GPU 时间线有没有空白。空白 GPU 在发呆多半是 CPU 算太慢或 H2D 拷贝阻塞NCCL 色块和计算色块上下重不重叠。不重叠 通信被串行化了扩展性会很差AllGather / ReduceScatter 占多大比例。FSDP / ZeRO-3 训练里AllGather 是 GPU 在计算前临时把分片参数借齐ReduceScatter 是计算后把梯度规约并打散回各 GPU。这两个色块如果占据时间线一大半说明通信成为瓶颈要考虑梯度累积、offload、或更高带宽的互连三、Nsight Compute (ncu)Kernel 级显微镜什么时候用前两步定位到某个 Kernel 慢——比如自己写的 FlashAttention 跑得不如预期——但你不知道它为什么慢是被显存带宽卡住了算力没喂饱还是寄存器溢出ncu 就是干这个的。它会告诉你这个 Kernel 在 GPU 芯片内部的真实状态。⚠️ 重要警告绝对不要用 ncu 跑整个训练循环。它会对每个 Kernel 做极细粒度的硬件计数器采样开销是 50~200 倍。我见过有人ncu python train.py然后程序跑了三天没动——以为是死锁其实是 ncu 在尽职工作。正确姿势精准狙击# 只profile名字包含layer_norm的kernel,只采集1次,输出完整指标 ncu --kernel-regex layer_norm -c 1 --set full -o report python test_kernel.py通常的做法是把要测的算子单独剥离出来写个 mini 脚本不要带训练循环。终端输出解读ncu 的输出是一块块 Section最关键的有三个1. Speed of Light光速模型— 一眼看懂瓶颈类型Section: GPU Speed Of Light Throughput ----------------------------- ---------- --------------- Memory Throughput % 85.20 ← 访存接近打满 Compute (SM) Throughput % 22.10 ← 算力只跑到22% ----------------------------- ---------- --------------- WRN This kernel exhibits low compute performance and is memory bound.这种情况叫Memory Bound算子在等内存读取算力单元闲着。优化方向是 fuse 算子、用更大 block 提高数据复用、或者改成 FP16 减少访存量。反过来如果 Compute % 高、Memory % 低就是Compute Bound瓶颈在算力本身能做的不多除非换更高效的算法。2. Memory Workload — 看缓存命中率Section: Memory Workload Analysis ----------------------------- ---------- ------- L1/TEX Hit Rate % 45.50 L2 Hit Rate % 88.20 ----------------------------- ---------- -------L1 命中率低意味着同一块数据被反复从 L2 / 显存读取——典型的访存模式问题。Tile 大小、shared memory 的使用方式都会影响这个。3. Occupancy — 线程块配置合不合理Section: Occupancy ----------------------------- ---------- ------- Theoretical Active Warps/SM warp 32.00 Achieved Active Warps/SM warp 12.50 Occupancy Ratio % 39.06 ← 只跑到理论值的39% ----------------------------- ---------- -------Occupancy 低有几种原因寄存器用太多每线程占资源多能起的 Warp 就少、Block 太大或太小、shared memory 用太多。GUI 里有交互式工具能告诉你减到什么程度能提升。Roofline ModelGUI 里最直观的视图GUI 会画一张 Roofline 图横轴是算术强度FLOP / Byte纵轴是吞吐。每个 Kernel 是图上一个点。点落在斜线带宽屋顶下方 → Memory Bound点落在水平线算力屋顶下方 → Compute Bound点离屋顶有多远就是优化空间有多大四、NCCL_DEBUGINFO分布式通信排障什么时候用DDP / FSDP / ZeRO 训练突然 hang 住、超时、或者多机扩展效率差到不能看。这些问题大概率出在通信层但报错信息往往一脸懵——这时候打开 NCCL 的调试日志就对了。怎么用export NCCL_DEBUGINFO export NCCL_DEBUG_SUBSYSINIT,GRAPH # 可选:只看初始化和图构建 torchrun --nproc_per_node8 train.py重点看三件事1. 网卡选择日志会有这种行NCCL INFO NET/IB : Using [0]mlx5_0:1/IB如果看到mlx5_xxx是 InfiniBand速度正确。如果看到eth0或更糟的docker0那就是走错网卡了——多机训练性能直接腰斩。常见的修法是显式指定NCCL_SOCKET_IFNAMEeth1或NCCL_IB_HCAmlx5。2. 连接方式单机内 GPU 之间textNCCL INFO Channel 00 : 0[3000] - 1[4000] via P2P/IPC NCCL INFO Channel 00 : 0[3000] - 4[7000] via SYSNVL/P2P/IPC走 NVLink 或 NVSwitch最快PHB走 PCIe Host Bridge差一档SYS跨 NUMA 走 CPU 内存最慢A100 / H100 服务器理论上 GPU 之间应该全是NVL如果出现SYS说明拓扑或绑核出了问题。3. 拓扑构建textNCCL INFO Trees [0] 1/-1/-1-0--1 NCCL INFO Channel 00/02 : Ring : 0 - 1 - 2 - 3 - 0NCCL 会构建 Ring 或 Tree 拓扑做 AllReduce。这块日志卡住或反复重试多半是 GPU 之间不通要去查 IB 网络或 GPU Fabric Manager。五、nvidia-smi topo / dmon硬件层监控最后这套是基本功训练前先做体检训练中做轻量监控。nvidia-smi topo -m查看 GPU 拓扑nvidia-smi topo -m输出一张矩阵GPU0 GPU1 GPU2 GPU3 GPU4 GPU5 GPU6 GPU7 GPU0 X NV12 NV12 NV12 NV12 NV12 NV12 NV12 GPU1 NV12 X NV12 NV12 NV12 NV12 NV12 NV12 GPU2 NV12 NV12 X NV12 NV12 NV12 NV12 NV12 ...字符含义NV#NVLink 直连数字越大带宽越高A100 是 NV12H100 是 NV18PIX/PXB/PHB走 PCIe 不同层级依次变慢NODE/SYS跨 NUMA 节点最慢部署多卡训练前先看一遍。如果两张卡之间是SYS那把它们放进同一个 process group 就是性能灾难。nvidia-smi dmon实时监控nvidia-smi dmon -s ucm -d 1-s ucm Utilization Compute Memory-d 1 每秒采样。输出像这样# gpu sm mem enc dec mclk pclk # Idx % % % % MHz MHz 0 30 90 0 0 1593 1410 1 95 45 0 0 1593 1410GPU0 的sm才 30%但mem跑到 90%——典型的访存密集特征算力被显存带宽拖住。这种 Kernel 拿去 ncu 分析多半会确认 Memory Bound。GPU1 的sm95% /mem45% 是计算密集的健康状态。完整排查工作流把这五件套串起来遇到性能问题的标准流程是nvidia-smi dmon先看一眼— sm 利用率多少是不是有卡在睡觉PyTorch Profiler 跑一轮— 找 Self CUDA Time 排行榜的 Top 3怀疑数据加载或通信上 nsys— 看 GPU 时间线有没有空白、NCCL 有没有重叠某个 Kernel 死活优化不动上 ncu— Roofline 看是 Memory Bound 还是 Compute Bound分布式训练 hang 住开 NCCL_DEBUGINFO— 检查网卡、连接方式、拓扑工具的开销是金字塔上面便宜下面贵。能在第 2 步解决的问题不要拖到第 4 步——绝大多数训练性能问题PyTorch Profiler nsys 这一组合就够用了。真正需要下到 ncu 的场景是写自定义 CUDA Kernel 或榨取理论峰值那是另一个层级的工作。至于 NCCL 和拓扑相关的——这些问题往往不是性能问题而是能不能跑起来的问题等到训练 hang 了再开始查就晚了所以首次部署时先topo -m看一眼、单机多卡和多机各跑一次 NCCL_DEBUG是值得的预防性投入。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2601699.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…