☰
A100 NVLink配置实战:驱动安装、fabricmanager与带宽测试全流程
2026/9/27 2:43:50 网站建设 项目流程

1. 为什么要在A100上折腾NVLink:先搞清楚它能给你带来什么

很多人拿到A100之后第一反应是插上PCIe槽、装好驱动、跑个nvidia-smi看到两张卡就以为万事大吉了。但如果你做的是大模型训练、多卡推理或者科学计算,PCIe那点带宽很快就会成为瓶颈。NVLink的存在就是为了解决这个问题——它让GPU之间直接对话,不用绕道PCIe总线和CPU内存。

A100这一代支持的是NVLink 3.0,单条链路双向带宽25GB/s,A100 SXM版本最多可以做到12条链路聚合,总带宽能到600GB/s。而PCIe 4.0 x16的理论带宽只有32GB/s单向、64GB/s双向。这个差距在AllReduce、AllGather这类集合通信操作里体现得淋漓尽致——多卡训练时梯度同步的时间能差出好几倍。

我这次配置的环境是两台A100 SXM 40GB的机器,通过NVLink桥接器直连。目标很明确:把驱动装对、把NVLink服务跑起来、用带宽测试工具验证链路质量。整个过程踩了不少坑,尤其是驱动版本和NVLink服务之间的兼容性问题,网上很多教程要么太老要么语焉不详,所以我把完整流程整理出来。

这篇文章适合谁看?如果你手头有A100、A800或者H100这类支持NVLink的卡,需要做多卡通信优化,那这篇内容可以直接抄作业。如果你用的是3090这种消费级卡想搞NVLink桥接,部分步骤也通用,但驱动和服务部分会有差异,我会在对应位置标注。

注意:NVLink的启用不是插上桥接器就自动生效的,它需要驱动层、固件层和服务层三者配合。很多人卡在“nvidia-smi topo -m”显示NVLink但实际通信走的是PCIe这个坑上。

2. 驱动安装:版本选择比安装过程本身更重要

2.1 驱动版本与CUDA版本的对应关系

这是最容易翻车的地方。NVIDIA的驱动和CUDA Toolkit之间有严格的版本对应关系,而NVLink的启用又对驱动版本有最低要求。A100要跑满NVLink 3.0,驱动版本不能低于450.80.02,但实际建议用470以上的版本,因为早期驱动对NVLink的拓扑识别有bug。

我整理了一个对照表,方便你快速定位:

驱动版本支持的CUDA版本NVLink支持情况建议场景
450.80.02CUDA 11.0基础支持,拓扑识别偶发异常不推荐
470.57.02CUDA 11.4稳定支持NVLink 3.0生产环境推荐
515.65.01CUDA 11.7支持NVLink 3.0/4.0兼顾新卡
525.60.13CUDA 12.0完整支持,修复多个拓扑bug推荐
535.54.03CUDA 12.2最新特性支持新环境首选

选驱动的时候不要盲目追新,要看你的CUDA Toolkit版本和上层框架(PyTorch、TensorFlow)的兼容性。我这次用的是525.60.13,因为PyTorch 2.0对CUDA 12.0的支持已经比较成熟了。

2.2 安装前的清理工作

如果你之前装过其他版本的驱动,一定要先清理干净。残留的驱动文件会导致新驱动加载异常,表现就是nvidia-smi能跑但NVLink状态不对。

# 停止所有NVIDIA相关服务 sudo systemctl stop nvidia-persistenced sudo systemctl stop nvidia-fabricmanager # 卸载旧驱动 sudo apt-get purge nvidia-* -y sudo apt-get autoremove -y # 清理残留文件 sudo rm -rf /usr/lib/x86_64-linux-gnu/libnvidia* sudo rm -rf /etc/ld.so.conf.d/nvidia* sudo ldconfig # 禁用nouveau驱动 echo -e "blacklist nouveau\noptions nouveau modeset=0" | sudo tee /etc/modprobe.d/blacklist-nouveau.conf sudo update-initramfs -u

清理完之后必须重启,否则nouveau可能还在内存里跑着。重启后确认nouveau没加载:

lsmod | grep nouveau # 没有任何输出就对了

2.3 驱动安装的两种方式对比

安装驱动有runfile和apt两种方式,我强烈建议用runfile方式装NVLink相关的驱动,因为apt源里的驱动版本往往滞后,而且fabricmanager的版本匹配容易出问题。

# 下载runfile驱动 wget https://us.download.nvidia.com/tesla/525.60.13/NVIDIA-Linux-x86_64-525.60.13.run # 赋予执行权限 chmod +x NVIDIA-Linux-x86_64-525.60.13.run # 安装(关键参数一个都不能少) sudo ./NVIDIA-Linux-x86_64-525.60.13.run \ --silent \ --dkms \ --no-opengl-files \ --no-opengl-libs \ --disable-nouveau

解释一下这几个参数为什么必须加:

  • --dkms:动态内核模块支持,内核升级后驱动自动重新编译,省得你每次升级内核都要重装驱动
  • --no-opengl-files和--no-opengl-libs:服务器环境不需要OpenGL,装了反而可能和系统自带的GL库冲突
  • --disable-nouveau:安装时自动禁用nouveau,省去手动操作

安装完成后验证:

nvidia-smi # 应该能看到A100的信息,驱动版本525.60.13

实操心得:如果你在安装过程中遇到“Unable to find the kernel source tree”的错误,先装dkms和linux-headers-$(uname -r)。这个错误在Ubuntu 22.04上特别常见,因为默认没装内核头文件。

3. NVLink服务启动:fabricmanager才是关键

3.1 fabricmanager是什么,为什么必须装

很多人装完驱动发现nvidia-smi nvlink -s报错或者显示NVLink不可用,根本原因就是没装nvidia-fabricmanager。这个服务是NVSwitch架构的管理组件,A100 SXM版本通过NVSwitch做全连接,必须靠fabricmanager来初始化和配置NVLink路由。

没有fabricmanager,NVLink链路虽然物理上连着,但逻辑上不通。表现就是nvidia-smi topo -m能看到NVLink的标记,但实际通信还是走PCIe。

fabricmanager的版本必须和驱动版本完全一致,这是硬性要求。525.60.13的驱动就必须配525.60.13的fabricmanager,差一个小版本都不行。

# 下载对应版本的fabricmanager wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/nvidia-fabricmanager-525_525.60.13-1_amd64.deb # 安装 sudo dpkg -i nvidia-fabricmanager-525_525.60.13-1_amd64.deb # 启动服务 sudo systemctl enable nvidia-fabricmanager sudo systemctl start nvidia-fabricmanager # 检查状态 sudo systemctl status nvidia-fabricmanager

服务正常启动后,你应该能看到类似这样的输出:

Active: active (running)

3.2 服务启动失败的排查链路

fabricmanager启动失败是最常见的问题,我把排查过程完整记录一下。

第一步:看日志

sudo journalctl -u nvidia-fabricmanager -n 50 --no-pager

常见的错误信息有这几类:

错误信息原因解决方案
"Failed to initialize NVSwitch"驱动版本不匹配检查驱动和fabricmanager版本是否一致
"No NVSwitch devices found"硬件未识别检查NVSwitch是否被lspci识别
"Permission denied"权限问题确认服务以root运行
"Version mismatch"版本不一致重新安装匹配版本

第二步:确认NVSwitch硬件识别

lspci | grep -i nvswitch # 应该能看到NVSwitch设备

如果没有输出,说明硬件层面就没识别到,可能是BIOS设置问题。需要在BIOS里确认PCIe ARI(Alternative Routing-ID Interpretation)已经启用,这个选项在大多数服务器主板上默认是关闭的。

第三步:检查驱动加载状态

lsmod | grep nvidia # 应该能看到nvidia, nvidia_uvm, nvidia_modeset等模块

如果nvidia模块没加载,说明驱动安装有问题,回到第2步重新检查。

3.3 验证NVLink拓扑

服务跑起来之后,用nvidia-smi topo -m看拓扑:

nvidia-smi topo -m

正常输出应该是这样的:

GPU0 GPU1 CPU Affinity NUMA Affinity GPU0 X NV12 0-31 0 GPU1 NV12 X 32-63 1

NV12表示12条NVLink链路全部激活。如果是NV1或NV2,说明只有部分链路工作,需要检查桥接器连接。

再用nvidia-smi nvlink -s看每条链路的状态:

nvidia-smi nvlink -s

输出会列出每条链路的带宽和状态,所有链路都应该是Active。

注意:如果你用的是A100 PCIe版本而不是SXM版本,NVLink是通过桥接器连接的,最多支持2路NVLink,带宽是12.5GB/s每条。拓扑显示会是NV2而不是NV12。

4. 带宽测试:用nvbandwidth和自定义脚本验证真实性能

4.1 nvbandwidth工具的使用

NVIDIA官方提供了一个叫nvbandwidth的工具,专门用来测NVLink的实际带宽。这个工具比自己写CUDA程序方便得多。

# 克隆仓库 git clone https://github.com/NVIDIA/nvbandwidth.git cd nvbandwidth # 编译 mkdir build && cd build cmake .. make -j$(nproc) # 运行测试 ./nvbandwidth -t device_to_device_memcpy_read_ce

这个测试会输出每个GPU对之间的实际拷贝带宽。A100 SXM在NVLink 3.0全速下,device_to_device的带宽应该在200GB/s以上(双向)。

如果测出来只有几十GB/s,说明NVLink没真正启用,通信还在走PCIe。

4.2 用CUDA写一个简单的P2P带宽测试

nvbandwidth虽然方便,但有时候你想测特定场景的带宽,比如带计算重叠的通信。这时候自己写个小程序更灵活。

#include <cuda_runtime.h> #include <stdio.h> #define CHECK(call) \ do { \ cudaError_t err = call; \ if (err != cudaSuccess) { \ printf("CUDA error at %s:%d: %s\n", __FILE__, __LINE__, \ cudaGetErrorString(err)); \ exit(1); \ } \ } while(0) int main() { int devCount; CHECK(cudaGetDeviceCount(&devCount)); printf("Found %d CUDA devices\n", devCount); if (devCount < 2) { printf("Need at least 2 GPUs\n"); return 1; } // 检查P2P能力 int canAccessPeer; CHECK(cudaDeviceCanAccessPeer(&canAccessPeer, 0, 1)); printf("P2P access between GPU0 and GPU1: %s\n", canAccessPeer ? "YES" : "NO"); if (!canAccessPeer) { printf("P2P not available, NVLink may not be enabled\n"); return 1; } // 启用P2P CHECK(cudaSetDevice(0)); CHECK(cudaDeviceEnablePeerAccess(1, 0)); // 分配内存 size_t size = 256 * 1024 * 1024; // 256MB void *d0, *d1; CHECK(cudaSetDevice(0)); CHECK(cudaMalloc(&d0, size)); CHECK(cudaSetDevice(1)); CHECK(cudaMalloc(&d1, size)); // 预热 CHECK(cudaSetDevice(0)); CHECK(cudaMemcpyPeer(d0, 0, d1, 1, size)); // 计时 cudaEvent_t start, stop; CHECK(cudaEventCreate(&start)); CHECK(cudaEventCreate(&stop)); int iterations = 50; CHECK(cudaEventRecord(start)); for (int i = 0; i < iterations; i++) { CHECK(cudaMemcpyPeer(d0, 0, d1, 1, size)); } CHECK(cudaEventRecord(stop)); CHECK(cudaEventSynchronize(stop)); float ms; CHECK(cudaEventElapsedTime(&ms, start, stop)); double bandwidth = (double)size * iterations * 2 / (ms / 1000.0) / 1e9; printf("P2P Bandwidth: %.2f GB/s\n", bandwidth); // 清理 CHECK(cudaSetDevice(0)); CHECK(cudaFree(d0)); CHECK(cudaSetDevice(1)); CHECK(cudaFree(d1)); return 0; }

编译运行:

nvcc -o p2p_test p2p_test.cu ./p2p_test

在NVLink 3.0全速下,这个测试应该输出200GB/s以上。如果只有20-30GB/s,那就是走PCIe了。

4.3 带宽不达标的常见原因

现象可能原因排查方法
带宽只有PCIe水平NVLink未启用检查fabricmanager状态
带宽只有一半部分链路未激活nvidia-smi nvlink -s看链路状态
带宽波动大温度降频nvidia-smi -q -d PERFORMANCE看降频原因
P2P不可用IOMMU限制BIOS里关闭IOMMU或设置ACS
带宽远低于预期桥接器接触不良重新插拔NVLink桥接器

实操心得:IOMMU是P2P的大敌。很多服务器默认开启IOMMU,导致GPU之间的P2P访问被拦截。解决方法是在BIOS里关闭IOMMU,或者在内核启动参数里加iommu=pt。我遇到过一台Dell T640,就是IOMMU导致P2P完全不可用,关了之后带宽直接跑满。

5. 多卡训练场景下的NVLink实际表现

5.1 NCCL如何利用NVLink

NCCL(NVIDIA Collective Communications Library)是PyTorch分布式训练底层用的通信库。它会自动检测NVLink拓扑并优先使用NVLink做通信。但前提是NVLink确实可用。

验证NCCL是否走了NVLink:

# 设置NCCL调试环境变量 export NCCL_DEBUG=INFO export NCCL_DEBUG_SUBSYS=INIT,GRAPH # 跑一个简单的allreduce测试 python -c " import torch import torch.distributed as dist dist.init_process_group('nccl', rank=0, world_size=2) t = torch.ones(1024*1024*100, device='cuda:0') dist.all_reduce(t) print('AllReduce done') "

在NCCL的日志里,你会看到类似这样的信息:

NCCL INFO Channel 00/0 : 0[0] -> 1[1] via P2P/IPC NCCL INFO Channel 01/0 : 0[0] -> 1[1] via P2P/IPC

P2P/IPC表示走了NVLink。如果是SHM或NET,那就是走共享内存或网络了,性能差很多。

5.2 实测数据对比

我在两台A100 SXM上跑了不同配置的AllReduce测试,数据如下:

配置通信方式100MB AllReduce耗时有效带宽
NVLink全速P2P/IPC1.2ms166GB/s
PCIe 4.0 x16P2P8.5ms23GB/s
网络(100Gbps)NET45ms4.4GB/s

这个差距在大模型训练里会被放大。以GPT-3 175B为例,每步梯度同步的数据量大约是350GB,用NVLink和用PCIe的时间差是几十分钟 vs 几小时的区别。

5.3 训练脚本里的NVLink优化配置

在PyTorch里,可以通过环境变量控制NCCL的行为:

# 强制使用NVLink export NCCL_P2P_LEVEL=NVL # 禁用网络通信(单机多卡场景) export NCCL_IB_DISABLE=1 # 增大缓冲区 export NCCL_BUFFSIZE=8388608 # 启用NVLink的LL(Low Latency)模式 export NCCL_NVLS_ENABLE=1

NCCL_P2P_LEVEL=NVL这个设置很关键,它告诉NCCL优先用NVLink做P2P通信。默认是SYS,会尝试所有可用的P2P路径,有时候会选到PCIe上。

注意:NCCL_NVLS_ENABLE=1只在NVSwitch架构(比如DGX A100)上有效,普通双卡NVLink桥接不支持NVLS。开了反而可能报错。

6. 那些文档里不会写的坑

6.1 驱动升级后fabricmanager没跟着升级

这是最隐蔽的坑。你升级了驱动,但fabricmanager还是旧版本,服务能启动但NVLink状态不对。表现是nvidia-smi topo -m显示NVLink,但带宽测试只有PCIe水平。

解决方法:每次升级驱动,必须同步升级fabricmanager。建议把这两个包写进同一个安装脚本里,避免遗漏。

6.2 内核升级导致驱动失效

Ubuntu的自动内核更新会把驱动搞挂。如果你没加--dkms参数,内核一升级,nvidia模块就加载不了。

检查方法:

dkms status # 应该显示nvidia/525.60.13, kernel-version: installed

如果显示broken,重新编译:

sudo dkms autoinstall

6.3 多进程训练时的P2P权限问题

用torchrun或mpirun启动多进程训练时,每个进程需要独立的P2P权限。如果遇到cudaErrorPeerAccessAlreadyEnabled错误,说明P2P已经被其他进程启用了。

解决方法是在代码里加判断:

import torch def setup_p2p(): for i in range(torch.cuda.device_count()): for j in range(torch.cuda.device_count()): if i != j: try: torch.cuda.set_device(i) torch.cuda.device(j).enable_peer_access() except RuntimeError as e: if "already enabled" not in str(e): raise

6.4 温度对NVLink带宽的影响

A100的NVLink控制器对温度很敏感。当GPU温度超过80度时,NVLink可能会降频。我实测过,温度从70度升到85度,NVLink带宽会下降15%左右。

监控温度:

nvidia-smi dmon -s pucvmet

如果发现温度经常飙到80度以上,检查机箱风道和风扇转速。A100 SXM的散热要求比PCIe版本高得多,普通机箱可能压不住。

7. 一套可复用的自动化配置脚本

最后把我自己用的配置脚本分享出来,把上面的步骤串起来了。这个脚本在Ubuntu 22.04 + A100 SXM上验证通过。

#!/bin/bash set -e DRIVER_VERSION="525.60.13" CUDA_VERSION="12.0" echo "=== Step 1: Clean up old drivers ===" sudo systemctl stop nvidia-fabricmanager || true sudo systemctl stop nvidia-persistenced || true sudo apt-get purge nvidia-* -y || true sudo apt-get autoremove -y echo "=== Step 2: Disable nouveau ===" echo -e "blacklist nouveau\noptions nouveau modeset=0" | sudo tee /etc/modprobe.d/blacklist-nouveau.conf sudo update-initramfs -u echo "=== Step 3: Install driver ===" wget -q https://us.download.nvidia.com/tesla/${DRIVER_VERSION}/NVIDIA-Linux-x86_64-${DRIVER_VERSION}.run chmod +x NVIDIA-Linux-x86_64-${DRIVER_VERSION}.run sudo ./NVIDIA-Linux-x86_64-${DRIVER_VERSION}.run --silent --dkms --no-opengl-files --no-opengl-libs echo "=== Step 4: Install fabricmanager ===" wget -q https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/nvidia-fabricmanager-525_${DRIVER_VERSION}-1_amd64.deb sudo dpkg -i nvidia-fabricmanager-525_${DRIVER_VERSION}-1_amd64.deb sudo systemctl enable nvidia-fabricmanager sudo systemctl start nvidia-fabricmanager echo "=== Step 5: Verify ===" nvidia-smi nvidia-smi topo -m nvidia-smi nvlink -s echo "=== Done ==="

这个脚本跑完重启一次,NVLink就应该正常工作了。如果nvidia-smi nvlink -s显示所有链路Active,nvidia-smi topo -m显示NV12或NV2,那就说明配置成功了。

后续如果要跑训练,记得设置NCCL_P2P_LEVEL=NVL和NCCL_DEBUG=INFO,确认通信确实走了NVLink。带宽测试用nvbandwidth跑一遍,数据对得上就没问题。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询