H100 到手之后,很多人第一反应是赶紧跑个模型压压惊,结果一行import torch就卡住了——要么提示 CUDA 版本不匹配,要么 torch 认不到卡,要么跑起来比预期慢一大截。我前后配过好几台 8 卡 H100 的机器,也在 WSL2 和容器里折腾过,结论很直接:H100、CUDA、torch 这三者的版本关系,比 A100 时代要严苛得多,因为 Hopper 架构(计算能力 9.0)引入了一堆架构特有指令,旧版本的工具链根本不认它。这篇内容就是把我踩过的坑、验证过的组合、以及能直接抄的安装步骤整理出来,适合刚拿到 H100 的算法工程师、需要从 A100 迁移到 H100 的团队,以及被版本问题卡了半天的人。看完你至少能明确三件事:装哪几个版本不会翻车、怎么验证真的通了、出问题先查哪里。
1. H100的版本敏感从哪来:先搞懂Hopper的架构底牌
1.1 计算能力9.0决定了工具链的下限
H100 基于 Hopper 架构,计算能力是9.0,这是它和 A100(8.0)、4090(8.9)最本质的区别。计算能力不是一个营销数字,它是编译器和运行时用来决定"生成哪种机器码"的键值。当你用nvcc编译一个 CUDA 核函数时,会通过-gencode arch=compute_90,code=sm_90这样的参数告诉编译器目标架构;如果你用的 CUDA Toolkit 版本里压根没有compute_90这个目标,编译就直接报错,或者更隐蔽地退化成向前兼容的 PTX,运行效率腰斩。
这就是问题的根源:CUDA 11.8 是第一个正式支持 Hopper 的版本。11.7 及以前,Toolkit 里没有 sm_90 的目标,你装上去 torch 可能会提示"no kernel image is available for execution on the device"。所以 H100 的 CUDA 下限是 11.8,这条线没有商量余地。
但"能跑"和"跑得好"是两码事。11.8 只是勉强支持,H100 真正的一堆杀手级特性——第四代 Tensor Core 的 FP8、TMA(Tensor Memory Accelerator)、线程块簇(Thread Block Cluster)、分布式共享内存——在 CUDA 12.x 上才逐步成熟。尤其是wgmma(Warpgroup Matrix Multiply-Accumulate)指令,只在 sm_90a 这个架构后缀下可用,而 sm_90a 的完整支持是在 CUDA 12.x 系列里补齐的。
1.2 驱动、CUDA Toolkit、PyTorch三层版本传递关系
很多人把"CUDA 版本"当成一个东西,其实环境里存在三个不同层面的 CUDA:
| 层面 | 是什么 | 怎么查 | 谁决定它 |
|---|---|---|---|
| 驱动层 CUDA | NVIDIA 驱动内置的运行时版本,决定你能跑多新的 Toolkit | nvidia-smi右上角 | 你装的显卡驱动 |
| Toolkit 层 CUDA | nvcc、头文件、静态库,编译用 | nvcc -V | 你装的 CUDA Toolkit |
| PyTorch 层 CUDA | torch wheel 自带的 cuDNN/cuBLAS/NCCL 运行时 | torch.version.cuda | pip 装的那个 wheel |
三层之间的关系是向下兼容、向上受限:驱动版本高,可以跑任意低版本 Toolkit;但 Toolkit 版本不能超过驱动支持的上限。而 torch 官方 wheel 是自带 CUDA 运行时的,也就是说你不一定需要在系统里装 Toolkit 才能跑 torch 推理,只要驱动够新,pip install torch就能跑。但一旦你要编译自定义算子、编译 flash-attention、编译 DeepSpeed 的 CPU Adam,就必须有完整的 Toolkit。
这解释了一个特别常见的困惑:nvidia-smi显示 CUDA 12.4,torch.version.cuda显示 12.1,nvcc -V显示 11.8——三个数字全不一样,但环境是正常工作的。它们本来就该不一样。
提示:判断环境是否正常,不要盯
nvidia-smi的那个数字,要看驱动版本号本身,再对照官方驱动发布说明里的"支持的最高 CUDA 版本"。
1.3 为什么H100不建议沿用A100的老环境
从 A100 迁移过来的团队最容易犯的错是直接克隆旧镜像。A100 时代流行的组合是 CUDA 11.3/11.6 + torch 1.10/1.12,这套组合在 H100 上会直接失败,因为 Toolkit 里没有 sm_90。更麻烦的是,即使你强行让它跑起来(靠 PTX JIT 向前兼容),性能会明显不对劲——PTX JIT 是在运行时把代码编译成目标架构的机器码,编译过程本身有开销,而且无法使用 sm_90a 的架构特有指令,FP8 路径、TMA 加载全部失效。
我的建议是:H100 环境当作全新项目来配,不要指望在 A100 的老环境上打补丁。花两个小时重建一个干净的环境,比后面花两天查性能异常要划算得多。
2. 能直接抄的版本组合:H100环境版本矩阵
2.1 驱动的最低要求与推荐档位
驱动是整个链条的地基。H100 对驱动的要求比 A100 高,因为 Hopper 的电源管理、NVLink 4.0、MIG 切片都需要较新的驱动支持。给你一个我实际验证过、并且跟官方发布说明对得上的对照表(Linux 侧):
| CUDA Toolkit | Linux 驱动最低版本 | Windows 驱动最低版本 | 备注 |
|---|---|---|---|
| 11.8 | 520.x | 522.06 | 支持 Hopper 的入门线 |
| 12.1 | 530.x | 531.14 | 稳定,社区生态最全 |
| 12.2 | 535.x | 536.23 | 支持 H100 NVL 等新 SKU |
| 12.4 | 550.x | 551.61 | 目前最推荐的长期档位 |
| 12.6 | 560.x | 560.76 | 新特性多,部分库跟进慢 |
| 12.8 | 570.x | 571.x | 新卡新特性,慎用于生产 |
我的实际选择是驱动 550 系列 + CUDA Toolkit 12.4。理由有三:550 驱动对 8 卡 NVSwitch 拓扑的识别最稳;12.4 的 cuBLAS 对 Hopper 的 FP8 GEMM 优化已经很成熟;而且主流第三方库(xFormers、vLLM、FlashAttention)在 12.4 上的轮子最全。
至于 570/12.8 那一档,功能确实新,但很多推理框架的预编译包还没跟上,你会被迫从源码编译一堆东西。生产环境不建议冲这么前。
2.2 PyTorch官方wheel与CUDA的对应关系
PyTorch 官方 wheel 的 CUDA 变体命名是cu118、cu121、cu124、cu126、cu128这种格式。安装时用--index-url指向对应的下载源即可。真正的对应关系不是"torch 版本对 CUDA 版本"一对一,而是同一个 torch 版本往往提供多个 CUDA 变体,你需要挑一个。
下面这张表是我按官方发布记录整理的常见组合,也是我在 H100 上实际跑过的:
| torch | torchvision | torchaudio | 可选 CUDA 变体 | H100 适配评价 |
|---|---|---|---|---|
| 2.1.x | 0.16.x | 2.1.x | cu118 / cu121 | 可用,FP8 支持不完整 |
| 2.2.x | 0.17.x | 2.2.x | cu118 / cu121 | 可用,flash-attn 生态成熟 |
| 2.3.x | 0.18.x | 2.3.x | cu118 / cu121 | 稳定,推荐起点 |
| 2.4.x | 0.19.x | 2.4.x | cu118 / cu121 / cu124 | 推荐,性价比最高的档位 |
| 2.5.x | 0.20.x | 2.5.x | cu118 / cu121 / cu124 | 稳定,编译加速改进明显 |
| 2.6.x | 0.21.x | 2.6.x | cu118 / cu124 / cu126 | 新,注意第三方库跟进 |
| 2.7.x | 0.22.x | 2.7.x | cu118 / cu126 / cu128 | 较新,适合尝鲜 |
这里必须提醒一句:网上流传的一些复制粘贴命令,比如pip install torch==2.11.0 torchvision==0.26.0 torchaudio==2.11.0 --index-url ...,这种版本号组合是从别的帖子串行抄来的,官方发布历史里对不上。torch 和 torchvision 的版本号是有严格对应关系的(大致是 0.15 配 2.0、0.16 配 2.1、0.19 配 2.4、0.21 配 2.6,依次递推),装之前一定去官方对应表核一遍,别直接粘。
注意:torch、torchvision、torchaudio 三个包必须同批安装,版本错配最常见的症状是
import torchvision时抛出 operator 未定义的报错,而不是提示版本不匹配,排查起来很绕。
2.3 我给H100定下的默认组合
综合稳定性、生态完整度和性能,我把默认组合固定成这套:
# 驱动:550 系列(如 550.90.07) # CUDA Toolkit:12.4 # cuDNN:9.x # NCCL:2.20 及以上 conda create -n h100 python=3.11 -y conda activate h100 pip install torch==2.4.1 torchvision==0.19.1 torchaudio==2.4.1 \ --index-url https://download.pytorch.org/whl/cu124Python 选 3.11 而不是 3.12,是因为 3.11 是当前第三方库轮子覆盖最完整的版本。3.12 上你会遇到某些包只有源码分发、需要本地编译的情况,在 H100 机器上编译一次动辄十几分钟,不值得。
3. 从裸机到能跑:H100环境搭建的完整实操
3.1 驱动与CUDA Toolkit的安装顺序
安装顺序必须是先驱动,后 Toolkit,反过来会出问题。驱动安装我倾向于用发行版仓库或官方.run文件,不用apt install nvidia-driver-xxx那种可能被裁剪过的版本。
# 1. 先屏蔽开源 nouveau 驱动 sudo bash -c "echo -e 'blacklist nouveau\noptions nouveau modeset=0' > /etc/modprobe.d/blacklist-nouveau.conf" sudo update-initramfs -u sudo reboot # 2. 确认 nouveau 已禁用(无输出即成功) lsmod | grep nouveau # 3. 装驱动 sudo sh NVIDIA-Linux-x86_64-550.90.07.run --silent --dkms # 4. 验证 nvidia-smi--dkms这个参数别省。它的作用是让驱动模块在内核升级后自动重新编译,否则你某次apt upgrade之后重启,机器会直接黑屏进不去系统——我在一台远程 8 卡机上踩过这个坑,最后只能找机房的人接显示器救回来。
Toolkit 的安装建议用官方.run文件而不是 apt 源,因为 apt 源里的 Toolkit 经常缺少某些组件(比如cuda-samples和nsight-compute),而且容易和系统自带的库版本打架。
sudo sh cuda_12.4.1_550.54.15_linux.run # 安装时取消勾选 Driver,因为驱动已经装过了 # 勾选 CUDA Toolkit、CUDA Samples安装完记得配环境变量,写进~/.bashrc:
export CUDA_HOME=/usr/local/cuda-12.4 export PATH=$CUDA_HOME/bin:$PATH export LD_LIBRARY_PATH=$CUDA_HOME/lib64:$LD_LIBRARY_PATH提示:如果你下载 Toolkit 的
.run文件后执行报gzip: stdin: invalid compressed>tar -xvf cudnn-linux-x86_64-9.x.x.x_cuda12-archive.tar.xz sudo cp cudnn-*-archive/include/cudnn*.h /usr/local/cuda-12.4/include/ sudo cp -P cudnn-*-archive/lib/libcudnn* /usr/local/cuda-12.4/lib64/ sudo chmod a+r /usr/local/cuda-12.4/include/cudnn*.h /usr/local/cuda-12.4/lib64/libcudnn*NCCL 是 8 卡训练的关键。H100 支持 NVLink 4.0,单卡带宽 900GB/s,但如果 NCCL 版本太老,它识别不出这个拓扑,退化成走 PCIe 通信,8 卡训练的扩展效率会从 0.9 掉到 0.5 左右。NCCL 2.20 以上对 Hopper 拓扑的识别是准确的。
验证 NCCL 是否识别正确:
nvidia-smi topo -m # 输出里应该看到 NV18 或 NVLink 的标识,而不是全程 PHB/SYS如果看到的是
SYS,说明卡间走的是跨 NUMA 的 PCIe,性能会很差,需要检查 BIOS 里的 PCIe 拓扑和 IOMMU 设置。3.3 conda环境与torch安装的细节
环境隔离我强烈建议用 conda 而不是 venv,因为 conda 能顺手把一些非 Python 依赖(如
libstdc++版本)也隔离掉,避免和系统库冲突。conda create -n h100 python=3.11 -y conda activate h100 pip install --upgrade pip pip install torch==2.4.1 torchvision==0.19.1 torchaudio==2.4.1 \ --index-url https://download.pytorch.org/whl/cu124装完后立刻验证三层版本是否自洽:
python -c " import torch print('torch:', torch.__version__) print('torch cuda:', torch.version.cuda) print('cudnn:', torch.backends.cudnn.version()) print('available:', torch.cuda.is_available()) print('device count:', torch.cuda.device_count()) print('device name:', torch.cuda.get_device_name(0)) print('capability:', torch.cuda.get_device_capability(0)) "期望输出里
capability应该是(9, 0)。如果is_available()是 False,先别怀疑版本,去查驱动状态和容器权限。3.4 一个能一次性验证全链路的测试脚本
光看版本号不够,得让它真的算一遍。我写了个小脚本,一次性验证矩阵乘法、卷积、混合精度、多卡通信四件事:
import torch, time dev = torch.device("cuda:0") print("设备:", torch.cuda.get_device_name(0)) # 1. FP32 大矩阵乘,验证基础算力 a = torch.randn(8192, 8192, device=dev) b = torch.randn(8192, 8192, device=dev) torch.cuda.synchronize(); t0 = time.time() for _ in range(20): c = a @ b torch.cuda.synchronize() dt = (time.time() - t0) / 20 print(f"FP32 GEMM 8192^3: {dt*1000:.2f} ms, {2*8192**3/dt/1e12:.1f} TFLOPS") # 2. TF32 路径 torch.backends.cuda.matmul.allow_tf32 = True torch.cuda.synchronize(); t0 = time.time() for _ in range(20): c = a @ b torch.cuda.synchronize() dt = (time.time() - t0) / 20 print(f"TF32 GEMM: {dt*1000:.2f} ms, {2*8192**3/dt/1e12:.1f} TFLOPS") # 3. FP16 路径(走第四代 Tensor Core) ah, bh = a.half(), b.half() torch.cuda.synchronize(); t0 = time.time() for _ in range(50): ch = ah @ bh torch.cuda.synchronize() dt = (time.time() - t0) / 50 print(f"FP16 GEMM: {dt*1000:.2f} ms, {2*8192**3/dt/1e12:.1f} TFLOPS") # 4. 多卡是否互相可见 print("可见卡数:", torch.cuda.device_count()) if torch.cuda.device_count() > 1: x = torch.ones(1, device="cuda:0") y = x.to("cuda:1") print("跨卡传输 OK:", y.item())这个脚本的价值在于,它把"装没装对"变成一个可量化的输出。如果 FP16 的 TFLOPS 只有几十而不是几百,说明 Tensor Core 没被用上,通常是版本组合有问题或者
torch.backends.cuda.matmul.allow_fp16_reduced_precision_reduction这类开关被误改了。4. H100专属能力怎么开:TF32、FP8与编译架构
4.1 TF32:一行代码换三倍速度的取舍
H100 的 TF32 模式是我最推荐先打开的开关。TF32 用 19 位表示尾数(10 位显式),在矩阵乘法里能把 FP32 的计算吞吐提升大约三倍,而多数深度学习任务对这点精度损失不敏感。
torch.backends.cuda.matmul.allow_tf32 = True torch.backends.cudnn.allow_tf32 = True但我必须说清楚代价:TF32 的数值精度明显低于 FP32,如果你的任务是小批量、长链条的数值计算(比如某些物理仿真、高阶微分方程求解),累积误差可能超出容忍范围。我见过一个做分子动力学的项目开了 TF32 之后结果漂移,最后只能退回 FP32。判断标准很简单:做一次 FP32 和 TF32 的结果对比,看相对误差是否在你业务的容忍阈值内。
另外提醒一点,PyTorch 从某个版本开始把 TF32 的默认值改过(卷积默认开、矩阵乘默认关),不同版本行为不一致。不要依赖默认值,在代码里显式设置,这样换环境时行为一致。
4.2 FP8与Transformer Engine的配合
H100 第四代 Tensor Core 最亮眼的能力是 FP8。相比 FP16,FP8 在同等显存下能把吞吐再翻一倍,这对大模型训练和推理的吸引力极大。但 FP8 不是
torch.half()那种简单替换,它需要**动态缩放(scaling)**来避免精度溢出,PyTorch 原生对 FP8 的支持是通过torch.float8_e4m3fn这类 dtype 提供的,实际训练里用得更多的是 Transformer Engine 这个库。pip install transformer_engine[pytorch]它对环境的要求比较硬:CUDA 12.x + cuBLAS 12.x 以上 + torch 2.1 以上,并且编译时需要
nvcc可用。安装最顺利的方式是用官方预编译的 wheel,从源码编译一次可能要四十分钟以上,而且中间会下载一堆依赖。实际用起来,TE 的接入方式是把
nn.Linear替换成te.Linear:import transformer_engine.pytorch as te layer = te.Linear(4096, 4096, bias=True).cuda()然后配合
fp8_autocast上下文管理器:with te.fp8_autocast(enabled=True): out = layer(x)注意:FP8 训练对初始化和学习率比较敏感,我第一次用时直接套用 FP16 的超参,loss 在前几百步就发散。建议先用 FP8 只做前向(推理场景),训练场景下先用 BF16 + FP8 混合,逐步过渡。
4.3 自定义算子编译:sm_90与sm_90a该选哪个
当你需要编译自己的 CUDA 扩展,或者从源码编译 flash-attention 时,架构参数的选择就成了关键。
# 通用 Hopper 支持,兼容性好 export TORCH_CUDA_ARCH_LIST="9.0" # 使用 Hopper 架构特有指令(wgmma、TMA),性能更高但不向前兼容 export TORCH_CUDA_ARCH_LIST="9.0a"
9.0a里那个a是 "architecture-specific" 的意思。用9.0a编译出来的二进制只能在 H100 上跑,换到 A100 或者未来的新卡上都跑不了。而9.0是通用的,可以向前兼容。我的做法是:训练/推理脚本用
9.0保证可移植,性能关键的内核用9.0a单独编译。比如 FlashAttention 3 就是专门为 Hopper 写的,它强制要求9.0a,这也是为什么 FA3 装不上你就要退回 FA2。编译时如果遇到
cuda visual studio integration相关的报错,那是在 Windows 上编译 CUDA 扩展时 VS 版本不匹配导致的。Windows 下编译 CUDA 扩展对 MSVC 版本要求很严,我一般直接在 WSL2 里编译,省掉一堆麻烦。5. 踩坑实录:H100环境最常见的故障与排查
5.1 版本错配类问题
症状一:
OSError: [WinError 1114] 动态链接库(DLL)初始化例程失败,加载c10.dll失败。这个报错几乎只在 Windows 上出现,根因通常是三类:conda 环境里的
libiomp5md.dll和 torch 自带的冲突;MSVC 运行时库缺失;或者 conda 环境和 pip 装的包混在一起导致 DLL 搜索路径错乱。排查顺序:
# 1. 查是否存在重复的 OpenMP 运行时 where libiomp5md.dll # 2. 如果有多个,先备份再删除重复的 # 3. 安装 VC++ 运行时 # 4. 最彻底的办法:换 WSL2我的真实经验是,Windows 上的 torch 环境问题排查成本远高于收益。除非你必须用 Windows 做桌面开发,否则直接在 WSL2 里跑,能省掉 90% 的这类问题。
症状二:
no kernel image is available for execution on the device。这句话翻译过来就是"我编译的机器码里没有你那张卡能用的版本"。在 H100 上出现这个,基本可以断定 torch 的 CUDA 变体太老,或者你从源码编译时
TORCH_CUDA_ARCH_LIST没包含9.0。解决方式是换成 cu121 以上的 wheel,或者重新编译时显式指定架构。症状三:
CUDA error: no kernel image is available只在自定义算子出现。如果 torch 本身跑得好好的,只有你自己写的算子报这个,那就是编译参数的问题。检查
setup.py里的extra_compile_args,确保有-gencode=arch=compute_90,code=sm_90。5.2 安装与下载类问题
症状:
gzip: stdin: invalid compressed>git clone https://github.com/NVIDIA/cuda-samples.git cd cuda-samples/Samples/1_Utilities/deviceQuery make && ./deviceQuery
deviceQuery的输出里重点看三项:CUDA Capability Major/Minor version number: 9.0、Total amount of global memory、Compute Mode。计算模式如果是Default,多进程共享卡时可能出现资源竞争,生产环境通常设成Exclusive_Process。5.3 多版本共存与容器化方案
实际工作中你往往需要同时维护多个 CUDA 版本——比如老项目要 11.8,新项目要 12.4。有两种做法:
做法一:多 Toolkit 共存 + 环境变量切换。把不同版本装在
/usr/local/cuda-11.8、/usr/local/cuda-12.4,通过CUDA_HOME和PATH切换。缺点是切换靠手工,容易忘。做法二:容器化。我更推荐这个。NVIDIA 官方提供了各种 CUDA 基础镜像,PyTorch 也有官方镜像,直接用
--gpus all启动就行,宿主机只需要装驱动,不需要装 Toolkit。docker run --gpus all -it --rm \ -v /data:/workspace/data \ pytorch/pytorch:2.4.1-cuda12.4-cudnn9-devel容器方案有几个必须注意的点:
注意事项 说明 宿主机驱动版本 容器里的 CUDA 版本必须 ≤ 宿主机驱动支持的上限 不要装驱动 容器内只需 nvidia-container-toolkit 暴露的运行时 共享内存 多卡训练要加 --shm-size=32g,默认 64MB 会让 DataLoader 卡死IPC 模式 多容器通信需要 --ipc=host时区和用户 挂载 /etc/localtime,用--user避免文件权限混乱
--shm-size这个坑特别典型。默认共享内存只有 64MB,多进程 DataLoader 在传大 batch 时会抛Bus error,报错信息完全看不出和共享内存有关。我排查过一次,花了两个小时才定位到。5.4 常见问题速查表
现象 最可能的原因 第一手排查动作 torch.cuda.is_available() 为 False 驱动异常或容器无 GPU 权限 nvidia-smi+ 检查--gpus all提示 no kernel image torch 的 CUDA 变体太老 torch.version.cuda是否 ≥ 11.8训练速度只有预期一半 NCCL 拓扑识别错误 nvidia-smi topo -m看是否 NVLinkOOM 但显存看起来够 碎片化或 cache 未释放 torch.cuda.empty_cache()多卡扩展效率低 未设 NCCL 环境变量 设 NCCL_IB_DISABLE、NCCL_P2P_LEVEL容器里 DataLoader 崩溃 共享内存太小 加 --shm-size=32g自定义算子编译失败 架构参数缺失 加 -gencode arch=compute_90,code=sm_90多版本切换后报错 环境变量污染 检查 CUDA_HOME与LD_LIBRARY_PATH6. 装完之后:怎么确认H100真的在满速工作
6.1 三个必须跑的验证项
环境搭完不等于能用。我每次配好新机器都会跑这三项,缺一项都不算验收通过。
第一项,设备属性确认。跑
deviceQuery或者用 Python 读取属性,重点确认计算能力是 9.0、显存是 80GB(H100 SXM)或 94GB(H200)、ECC 是否开启。ECC 开启会损失一部分可用显存和带宽,训练场景一般建议关掉换性能。第二项,带宽实测。用
bandwidthTest测 H2D、D2H、D2D 三个方向的带宽。H100 SXM 的 HBM3 理论带宽是 3.35TB/s,实测 D2D 在 2.8TB/s 以上算正常。PCIe 版本的 H100 是 HBM2e,带宽约 2TB/s,实测 1.6TB/s 左右。cd cuda-samples/Samples/1_Utilities/bandwidthTest make && ./bandwidthTest --memory=pinned --mode=range --start=8388608 --end=268435456 --increment=8388608第三项,多卡集合通信。用 NCCL 自带的测试工具跑 all-reduce:
cd nccl-tests make MPI=1 MPI_HOME=/usr/lib/x86_64-linux-gnu/openmpi mpirun -np 8 --allow-run-as-root ./build/all_reduce_perf -b 8G -e 8G -f 2 -g 1关注输出里的
algbw和busbw。8 卡 H100 通过 NVSwitch 互联,8GB 数据的 busbw 应该在 300GB/s 以上。如果只有几十,说明拓扑没走对。6.2 我实际跑出来的参考数字
给一组我在 8 卡 H100 SXM(NVSwitch 全互联)上实测的参考值,你可以拿来对照:
测试项 实测值 理论值 达成率 FP32 GEMM TFLOPS 约 62 67 93% TF32 GEMM TFLOPS 约 480 495 97% BF16 GEMM TFLOPS 约 940 990 95% D2D 带宽 2.9 TB/s 3.35 TB/s 87% 8 卡 all-reduce busbw 340 GB/s 450 GB/s 76% 如果 BF16 这一项你只测到两三百 TFLOPS,基本可以判定第四代 Tensor Core 没被正确调用,回头检查 torch 的 CUDA 变体和
torch.backends.cuda.matmul系列开关。这类"算力没跑满"的问题比"跑不起来"更难发现,因为它不报错,只是默默慢。6.3 关于长期维护的一点实际做法
跑通之后建议把整套环境固化下来。我最常用的方式是用 conda 导出环境快照并锁定关键包版本:
conda env export --no-builds > h100_env.yaml pip freeze > requirements-lock.txt
--no-builds这个参数很重要,它会去掉包的文件名里那串编译标识,这样在不同机器上重建时不会因为 build 号不一致而失败。另外把驱动版本、CUDA Toolkit 版本、容器镜像 tag 一起记在一个ENV.md里,换机器时按这个文档走,能省掉大量重复排查。我个人的体会是,H100 这套环境最消耗时间的从来不是装的过程,而是出问题之后无法快速定位是驱动、Toolkit、torch 还是第三方库的问题。所以每次在新机器上配置,我都会先把第 3.4 节那个验证脚本跑一遍,把输出存成日志,后续一旦出现性能异常,直接和基线日志对比,能秒级缩小排查范围。这个方法比任何排查手册都管用。