Skip to content

第二部分 GPU 服务器与驱动环境(第 5~8 章)

本部分对应学习路线的第二阶段(第 3~4 周)。学完第一部分后,你已经理解了 GPU 硬件架构与 CUDA 生态的概念。从本部分开始,我们将进入"动手"阶段:从一台 GPU 服务器到货上架,到装好驱动、CUDA Toolkit、容器工具链,最终交付一个可以运行 GPU 容器的环境。这是 GPU 运维工程师最日常、最基础的工作,也是面试必问内容。


第 5 章 GPU 服务器硬件与上架检查

本章目标

  • 认识 GPU 服务器的常见形态和 8 卡机的内部结构
  • 理解 PCIe 拓扑与 NVLink/NVSwitch 拓扑的区别,读懂 nvidia-smi topo -m 输出
  • 掌握服务器到货验收的完整检查清单
  • 学会使用 BMC/IPMI 进行带外管理
  • 了解 GPU 服务器 BIOS 的推荐基线设置

5.1 GPU 服务器形态:1U/2U/4U 与 8 卡机典型结构

是什么:U(Unit)是机架服务器的高度单位,1U ≈ 4.45 cm。GPU 服务器按形态大致分为:

形态典型 GPU 数量GPU 安装方式典型场景
1U/2U1~4 张 PCIe 卡PCIe 插槽推理、轻量训练、开发机
4U4~10 张 PCIe 卡PCIe 插槽(机箱更高,散热更好)训练、推理
4U/6U/8U8 张 SXM 卡SXM 模组 + NVSwitch 底板大模型训练(NVIDIA HGX 8 卡机)

PCIe 卡与 SXM 卡的区别(重要概念):

  • PCIe 卡:长得像普通显卡,插在主板 PCIe 插槽上,卡间默认走 PCIe 总线通信,部分型号可选配 NVLink 桥接器。
  • SXM 卡:无金手指的模组形态,直接安装在专用底板(Baseboard)上,供电散热能力更强,原生支持完整 NVLink + NVSwitch 互联。数据中心旗舰卡(A100/H100 SXM 版)都是这种形态。

典型 8 卡训练服务器(HGX 架构)的内部组成

  • GPU 底板区:8 张 SXM GPU + 若干颗 NVSwitch 高速互联芯片
  • 主机区:2 颗 x86 CPU、1~2TB 内存、4~8 张 400G/800G 网卡(InfiniBand/RoCE)、NVMe SSD
  • 供电散热区:多个冗余电源模块(N+N)、暴力风扇墙或液冷管路

运维要点:

  • 电源冗余:8 卡机满载功耗可达数千瓦(具体以厂商规格为准),机房供电和 PDU 规划必须提前确认,通常是多路供电分别接入不同 PDU。
  • 散热:高功耗意味着高热量,机房冷通道温度、风道组织直接影响 GPU 是否降频。
  • 网卡配比:大模型训练通常要求"GPU : 网卡 = 1 : 1"(如 8 卡配 8 张 400G IB 网卡),第五部分会详细讲。

5.2 GPU 互联拓扑详解:nvidia-smi topo -m 逐行解读

为什么重要:分布式训练时 GPU 之间要频繁交换梯度数据。两张卡之间走 NVLink 还是走 PCIe、是否跨 NUMA 节点,通信带宽可能相差数倍。NCCL 会根据拓扑自动选择通信路径,运维人员需要能看懂拓扑来判断"这台机器的卡间通信是否健康"。

两类典型拓扑

  1. PCIe 拓扑:GPU 挂在 PCIe Switch 或 CPU 的 PCIe Root Complex 下,卡间通信走 PCIe 总线。同交换机下的卡通信较快,跨 CPU(跨 NUMA)最慢。
  2. NVLink/NVSwitch 拓扑:SXM 卡之间通过 NVLink 直连或经 NVSwitch 全互联,任意两卡之间带宽一致且远高于 PCIe。

查看拓扑

bash
nvidia-smi topo -m

NVSwitch 8 卡机的典型输出(示意):

        GPU0  GPU1  GPU2  ...  CPU Affinity  NUMA Affinity
GPU0     X    NV18  NV18       0-95           0
GPU1    NV18   X    NV18       0-95           0
GPU2    NV18  NV18   X         96-191         1
...

图例(Legend)各标识的含义:

标识含义通信质量
X自己(Self)
NV#通过 NVLink 互联,# 为链路数(如 NV18 表示 18 条链路)最优
NODE同一 NUMA 节点内(不跨 PCIe 主机桥)较好
PHB经过 PCIe 主机桥(Host Bridge),同一 CPU 下一般
PXB经过多个 PCIe Switch(同一主机桥)一般
PIX经过一个 PCIe Switch较好(PCIe 机型中算好的)
SYS跨 NUMA 节点,需经过 CPU 间互联(如 UPI)最差

运维关注点

  • 8 卡 SXM 机正常应显示 NV# 全互联。如果出现 PHB/SYS,说明 NVLink 链路掉了或 NVSwitch 异常(结合第七部分的 XID 错误排查)。
  • CPU Affinity 列表示该 GPU 亲和的 CPU 核与 NUMA 节点,绑核、绑网卡都要参考它。

搭配查看 NVLink 状态:

bash
nvidia-smi nvlink --status      # 每张卡的 NVLink 链路状态
nvidia-smi nvswitch -l          # NVSwitch 状态(仅 NVSwitch 机型)

5.3 上架与验收检查清单

GPU 服务器单价高昂,到货验收一定要留痕。推荐按以下清单执行:

1. 外观与物流验收:外包装无破损受潮,开箱拍照;机身无磕碰变形;核对序列号(SN)与采购合同一致:

bash
sudo dmidecode -t system | grep -E "Manufacturer|Product Name|Serial Number"

2. 硬件配置核对:GPU 数量与型号、CPU、内存、磁盘、网卡:

bash
lspci | grep -i nvidia | wc -l     # 应等于采购的 GPU 数量
lspci | grep -i nvidia | head -3   # 查看型号(装好驱动后可用 nvidia-smi -L)
lscpu | grep -E "Model name|^CPU\(s\)" && free -h && lsblk
lspci | grep -i -E "ethernet|infiniband"

3. 固件版本记录:记录 BIOS、BMC、GPU VBIOS、NVSwitch、网卡固件版本,与厂商基线比对:

bash
sudo dmidecode -t bios | grep -E "Version|Release Date"   # BIOS 版本
nvidia-smi -q | grep -i -E "VBIOS|Firmware"               # GPU 固件(需先装驱动)

4. 上电与散热检查

  • 多路供电分别接入不同 PDU,逐一断电测试冗余电源切换正常
  • 风扇自检无异常噪音,进风口无遮挡
  • 空载运行 30 分钟,观察 BMC 温度传感器无高温告警(见 5.4 节)
  • 有条件时跑一轮 GPU 压测(如 gpu-burn),确认满载温度不触顶、不降频

5.4 带外管理:BMC/IPMI 基础

是什么:BMC(Baseboard Management Controller,基板管理控制器)是服务器主板上的一颗独立芯片,有独立的网口和固件。即使操作系统死机、甚至机器关机(接了电),你依然可以通过 BMC 远程查看状态、开关机、挂载 ISO 装系统——这就叫"带外管理"。IPMI 是与 BMC 通信的标准协议,常用工具是 ipmitool

为什么重要:GPU 机房的服务器一旦死机(GPU 运维中并不罕见),没有带外管理就得跑机房。BMC 是所有远程运维操作的基础。

bash
sudo apt install -y ipmitool

以下命令中 -H 是 BMC 管理 IP,-U/-P 是 BMC 账号密码(新机请第一时间修改默认密码!):

bash
BMC="ipmitool -I lanplus -H 192.168.1.100 -U admin -P 'password'"

$BMC power status                 # 查看电源状态
$BMC power on                     # 远程开机(off/soft/reset 分别为关机/优雅关机/硬重启)
$BMC sdr type temperature         # 温度传感器(重点关注 CPU/GPU 进风温度)
$BMC sensor list | head -30       # 全部传感器(风扇转速、电压等)
$BMC sel list | tail -20          # 硬件事件日志 SEL:掉电、过热、内存 ECC 错误都在这里

提示:除 IPMI 外,现代服务器还支持 Redfish API(基于 HTTPS/JSON),更适合自动化;各厂商 BMC 均有 Web 管理界面(如 iDRAC、iLO、XClarity),建议熟悉。

5.5 基线固化:BIOS 设置建议

新服务器交付前,应将 BIOS 配置固化为基线,保证同一批次机器行为一致。GPU 训练服务器的常见建议(不同厂商菜单名称略有差异,以厂商手册为准):

设置项建议值原因
电源/性能模式(Power Profile)Performance节能模式导致 CPU/GPU 降频,训练性能抖动
C-States / P-States(CPU 节能)关闭或限制避免 CPU 频率波动影响数据加载
Above 4G Decoding开启GPU 显存 BAR 空间巨大,不开会导致多卡机认不全卡(常见坑)
Resizable BAR按 GPU/主板支持情况开启允许 CPU 访问完整显存
IOMMU(VT-d / AMD-Vi)默认关闭;做 GPU 直通时开启可能影响 GPUDirect RDMA,按需配置(第三部分细讲)
ACS做直通时关注ACS 会阻止同 IOMMU 组设备拆分,PCIe 拓扑规划要注意
NUMA开启训练任务要利用 NUMA 亲和性
串口重定向(SOL)按需开启无 KVM 时可通过串口排查系统问题

实践建议:用 Redfish API 或厂商批量工具导出一份"标准 BIOS 配置",新机到货直接导入,避免逐台手工设置。

本章小结

  • GPU 服务器分为 PCIe 卡机型(1U~4U)和 SXM + NVSwitch 8 卡机(HGX 架构),后者是大模型训练主力。
  • nvidia-smi topo -m 中的 NV#/NODE/PHB/PXB/PIX/SYS 描述卡间通信路径质量,NVSwitch 机型应全 NV# 互联。
  • 验收要留痕:外观、序列号、硬件配置、固件版本、电源冗余、散热压测缺一不可。
  • BMC/IPMI 是带外管理基础,ipmitool 的电源控制、传感器、SEL 日志是日常必备命令。
  • BIOS 基线要固化,特别注意 Above 4G Decoding 必须开启,否则多卡机认不全卡。

动手实验

  1. 在有 GPU 的机器上执行 nvidia-smi topo -m,对照图例说明你的机器属于哪种拓扑;再执行 nvidia-smi nvlink --status 查看链路状态。
  2. 执行 lspci | grep -i nvidiasudo dmidecode -t system,记录 GPU 数量、厂商、序列号,写一份"验收记录"Markdown 文档。
  3. 安装 ipmitool,浏览 ipmitool help 各子命令;如有真实 BMC 权限,完成一次远程开关机和 SEL 日志查看。
  4. 进入一次 BIOS 设置界面(或查阅厂商文档),找到 Above 4G Decoding 和电源模式选项,理解其作用。

第 6 章 NVIDIA 驱动安装与管理

本章目标

  • 理解 NVIDIA 驱动的类型与选择原则
  • 掌握 Ubuntu 安装驱动的三种方式,独立完成生产推荐的仓库安装
  • 逐项读懂 nvidia-smi 首屏输出
  • 掌握驱动升级、回滚、DKMS 与内核升级后驱动失效的处理
  • 能排查 Secure Boot、nouveau 冲突等常见安装问题

6.1 驱动类型:先搞清楚装的是什么

按内核模块开放程度分

  • 专有(闭源)内核模块:传统方式,NVIDIA 提供预编译二进制内核模块。
  • 开源内核模块(Open GPU Kernel Modules):NVIDIA 自 R515 起开源了内核模块部分(用户态库仍闭源)。Turing 及以后架构两种都支持;Hopper(H100)及更新架构推荐开源模块,部分新特性依赖它。生产选择遵循 NVIDIA 官方对所用 GPU 架构的建议。

按产品线/发布分支分

  • 数据中心驱动(Data Center Driver):面向 T4/V100/A100/H100 等数据中心 GPU,提供 LTSB(长期支持分支),更新慢、稳定,生产环境首选
  • 桌面/GeForce 驱动:面向消费级显卡,更新频繁。
  • "Tesla 驱动":NVIDIA 早年对数据中心产品线叫 Tesla,老文档里的"Tesla 驱动"就是数据中心驱动。

关键认知:驱动版本号(如 535.xx、550.xx、570.xx)决定能支持的最高 CUDA 版本(见 8.4 节)。生产选版本原则:数据中心 LTSB 分支 + 满足业务所需 CUDA 版本 + 全集群统一

6.2 Ubuntu 安装驱动的三种方式

方式做法优点缺点适用
发行版 apt(ubuntu-driversUbuntu 官方仓库的 nvidia-driver-xxx最简单版本偏旧桌面、快速实验
NVIDIA 官方 CUDA 仓库添加 NVIDIA apt 仓库后安装版本新且全、有 DKMS、可精确选版本需配置仓库生产推荐
runfile(.run 安装包)官网下载直接执行离线可用不走包管理,升级卸载麻烦离线隔离环境

生产建议:统一使用 NVIDIA CUDA 仓库方式,用 Ansible 等工具固化流程,保证全集群驱动版本一致。

6.3 完整安装示例(NVIDIA 仓库方式,Ubuntu 22.04)

以下流程假设全新安装的 Ubuntu 22.04。驱动包名请替换为目标版本(如 nvidia-driver-570-server 数据中心分支,具体可用版本以仓库为准)。

第 1 步:禁用 nouveau(开源 NVIDIA 驱动,与官方驱动冲突):

bash
cat <<EOF | sudo tee /etc/modprobe.d/blacklist-nouveau.conf
blacklist nouveau
options nouveau modeset=0
EOF
sudo update-initramfs -u && sudo reboot

lsmod | grep nouveau    # 重启后验证:无输出即成功

第 2 步:安装内核头文件与编译工具(DKMS 编译驱动模块需要):

bash
sudo apt update
sudo apt install -y build-essential linux-headers-$(uname -r) dkms

第 3 步:添加 NVIDIA CUDA 官方仓库(24.04 请把 ubuntu2204 换成 ubuntu2404):

bash
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.1-1_all.deb
sudo dpkg -i cuda-keyring_1.1-1_all.deb
sudo apt update

第 4 步:安装驱动并重启

bash
apt-cache search nvidia-driver | grep -E "nvidia-driver-[0-9]+" | sort   # 查看可用版本
sudo apt install -y nvidia-driver-570-server    # 数据中心服务器分支,版本以仓库为准
sudo reboot

第 5 步:验证——执行 nvidia-smi,能看到 GPU 列表即成功;失败则看 6.6 节排查。

6.4 验证与版本管理:nvidia-smi 首屏逐项解读

nvidia-smi 是 GPU 运维的第一命令,首屏每个字段都要能看懂:

+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 570.86.15    Driver Version: 570.86.15    CUDA Version: 12.8               |
|-----------------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M | Bus-Id        Disp.A | Volatile Uncorr. ECC          |
| Fan  Temp  Perf  Pwr:Usage/Cap |         Memory-Usage | GPU-Util  Compute M.          |
|=================================+======================+======================|
|   0  NVIDIA A100-SXM...    On   | 00000000:10:00.0 Off |                    0          |
| N/A   32C    P0    60W / 400W  |      0MiB / 40960MiB |      0%      Default          |
+--------------------------------+----------------------+----------------------+
| Processes: ...                                                                        |
+---------------------------------------------------------------------------------------+
字段含义运维关注点
Driver Version当前内核驱动版本故障定位首先要报这个号
CUDA Version该驱动最高支持的 CUDA 版本(不是已装 Toolkit 版本!)判断容器/程序能否运行的关键(见 8.4)
Persistence-M持久模式是否开启(见 7.5)生产建议 On
Bus-IdGPU 的 PCI 总线地址定位物理卡、掉卡排查要用
Uncorr. ECC不可纠正 ECC 错误计数(Volatile=重启清零)非 0 要警惕,配合 XID 排查
Fan / Temp风扇转速 / 核心温度数据中心卡多为被动散热显示 N/A;接近阈值会降频
Perf性能状态 P0(最高)~P12(最低)空载长期 P0 可能浪费电
Pwr:Usage/Cap当前功耗 / 功耗上限触顶说明功耗墙限制
Memory-Usage显存占用 / 总显存日常盯得最紧的指标
GPU-UtilGPU 利用率(采样周期内有 kernel 执行的时间占比)高利用率 ≠ 高效利用(第八部分细讲)
MIG M.MIG 模式开关(仅 A100/H100 等支持)第三部分细讲
Processes占用 GPU 的进程及显存排查"显存被谁占了"

常用进阶查询:

bash
# 只查关键指标,适合写巡检脚本
nvidia-smi --query-gpu=index,name,temperature.gpu,utilization.gpu,memory.used,memory.total,power.draw --format=csv
watch -n 1 nvidia-smi    # 持续监控

6.5 驱动升级与回滚、DKMS、内核升级后驱动失效

DKMS 是什么:DKMS(Dynamic Kernel Module Support)是"动态内核模块支持"框架。NVIDIA 驱动包含内核模块,必须与当前内核版本匹配编译。DKMS 的作用就是:每次系统内核升级后,自动为新内核重新编译 NVIDIA 内核模块——这就是 6.3 节要先装 dkms 和内核头文件的原因。

升级驱动(仓库方式):建议停掉 GPU 业务后操作。

bash
apt-cache policy nvidia-driver-570-server        # 查看可升级版本
sudo apt update && sudo apt install -y nvidia-driver-570-server
sudo reboot

回滚驱动

bash
sudo apt purge -y "nvidia-driver-*" "nvidia-dkms-*" && sudo apt autoremove -y
sudo apt install -y nvidia-driver-550-server     # 目标旧版本需在仓库中存在
sudo reboot

生产建议:操作前记录当前版本(nvidia-smi --query-gpu=driver_version --format=csv,noheader),先单台验证再批量。

内核升级后驱动失效:典型症状是重启后 nvidia-smiNVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver。排查修复:

bash
dkms status
# 正常应显示: nvidia/570.xx, 6.8.0-xx-generic, x86_64: installed
# 若只有 added 没有 installed,说明没为新内核编译

sudo apt install -y linux-headers-$(uname -r)    # 常见原因:新内核头文件没装
sudo dkms autoinstall                            # 手动触发 DKMS 重新编译
sudo modprobe nvidia && nvidia-smi               # 加载模块验证

预防措施:生产环境建议锁定内核版本sudo apt-mark hold linux-image-generic linux-headers-generic),内核升级作为有计划的维护操作,随驱动一起验证。

6.6 常见安装问题

问题 1:Secure Boot 导致驱动加载失败

症状:驱动安装成功、DKMS 显示 installed,但 nvidia-smi 连不上驱动;dmesg | grep -i nvidia 可见模块签名错误。原因:UEFI Secure Boot 要求内核模块必须签名,DKMS 本地编译的模块默认未签名。

bash
mokutil --sb-state    # 查看 Secure Boot 状态(enabled/disabled)
# 处理:进 BIOS 关闭 Secure Boot(数据中心推荐);
# 或安装时按提示注册 MOK 密码,重启时在蓝色 MOK 界面完成 Enroll

问题 2:nouveau 冲突——lsmod | grep nouveau 有输出。处理:回到 6.3 节第 1 步,确认黑名单文件存在、执行过 update-initramfs -u 并重启。

问题 3:gcc / 内核头文件缺失——DKMS 编译失败,日志在 /var/lib/dkms/nvidia/*/build/make.log。处理:

bash
sudo apt install -y build-essential linux-headers-$(uname -r) && sudo dkms autoinstall

问题 4:装了桌面驱动而非服务器驱动——数据中心卡应装 -server 后缀分支。装错时 purge 后重装即可。

本章小结

  • 驱动分开源/闭源内核模块、数据中心/桌面分支;生产选数据中心 LTSB 分支,全集群版本统一。
  • 三种安装方式中 NVIDIA CUDA 仓库方式最适合生产;完整流程:禁 nouveau → 装头文件和 DKMS → 加仓库 → 装驱动 → 重启验证。
  • nvidia-smi 首屏的 CUDA Version 是"驱动支持的最高 CUDA";ECC 错误数、功耗、显存是日常关注点。
  • DKMS 负责内核升级后自动重编驱动模块;失效时先补内核头文件再 dkms autoinstall;生产建议锁定内核。
  • Secure Boot、nouveau、缺头文件是三大经典安装坑。

动手实验

  1. 在一台带 NVIDIA 显卡的 Ubuntu 机器上,完整走一遍 6.3 节仓库安装流程,记录每步输出。
  2. 执行 nvidia-smi,对照 6.4 节表格,把首屏每个字段的含义用自己的话写进笔记。
  3. 执行 6.4 节 --query-gpu 命令,把输出保存为 CSV,模拟一次"巡检"。
  4. 执行 dkms statusmokutil --sb-state,理解当前机器 DKMS 与 Secure Boot 状态。
  5. 思考题:机房不允许联网时,如何给 100 台新服务器装驱动?(提示:runfile + 本地 apt 镜像 + Ansible)

第 7 章 CUDA Toolkit 与 Fabric Manager

本章目标

  • 独立安装 CUDA Toolkit 并配置环境变量
  • 会用 CUDA Samples 验证 GPU 计算与带宽
  • 掌握多版本 CUDA 共存与切换
  • 理解 Fabric Manager 的作用场景与版本匹配要求
  • 掌握持久模式与 GPU 时钟管理

7.1 CUDA Toolkit 安装与环境变量

是什么、为什么:驱动(第 6 章)只解决"内核认识 GPU";CUDA Toolkit 提供编译器 nvcc、CUDA 运行时库(libcudart 等)、数学库和开发工具。需要在本机编译 CUDA 程序、裸金属跑训练的开发机需要装它。

注意区分:宿主机只跑 CUDA 容器时不需要装 CUDA Toolkit(容器自带运行时,见第 8 章),只有驱动是必需的。

安装(接续第 6 章已配好的仓库):

bash
sudo apt install -y cuda-toolkit-12-4    # 只装 Toolkit,不含驱动,便于独立控制驱动版本
# 想一步到位装"驱动+Toolkit"可用 meta 包:sudo apt install -y cuda-12-4

环境变量配置

bash
cat <<'EOF' | sudo tee /etc/profile.d/cuda.sh
export PATH=/usr/local/cuda/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH
EOF
source /etc/profile.d/cuda.sh

nvcc --version    # 验证,输出示例:Cuda compilation tools, release 12.4, V12.4.xxx

再次提醒:nvcc --version 显示的是本机安装的 Toolkit 版本nvidia-smi 右上角是驱动支持的最高 CUDA 版本。两者不要求一致,规则见 8.4 节。

7.2 用 CUDA Samples 验证:deviceQuery / bandwidthTest

CUDA Samples 是 NVIDIA 官方示例程序集,装完环境后跑一遍,可同时验证"编译链可用、GPU 能算、带宽正常"。新版 Samples 托管在 GitHub,需自行编译:

bash
sudo apt install -y git cmake
git clone https://github.com/NVIDIA/cuda-samples.git
cd cuda-samples/Samples/1_Utilities/deviceQuery
make -j$(nproc) && ./deviceQuery

deviceQuery 输出 GPU 型号、计算能力(Compute Capability)、SM 数量、显存等,最后打印 Result = PASS 即正常。

带宽测试(关键交付指标):

bash
cd ../bandwidthTest && make -j$(nproc) && ./bandwidthTest

它输出 Host↔Device(内存到显存)带宽。验收对照:PCIe 4.0 x16 理论约 32 GB/s(双向 64),实测略低于理论值属正常;如果只有几百 MB/s,往往是插在了低速插槽、Above 4G Decoding 没开或硬件故障——这是新机器交付前的必测项,具体数值以官方规格和实测为准。

多卡机可用 p2pBandwidthLatencyTest(位于 Samples/5_Domain_Specific)验证 GPU↔GPU 通信,NVLink 机型应远高于 PCIe 机型。

7.3 多版本 CUDA 共存管理

现实场景:老业务要 CUDA 11.8,新业务要 CUDA 12.4,同一台机器怎么办?

方案:多版本并存 + 软链接切换。apt 安装的不同版本 Toolkit 放在 /usr/local/cuda-11.8/usr/local/cuda-12.4 等目录,/usr/local/cuda 是软链接:

bash
ls -l /usr/local/ | grep cuda
# lrwxrwxrwx  cuda -> /usr/local/cuda-12.4
# drwxr-xr-x  cuda-11.8/
# drwxr-xr-x  cuda-12.4/

sudo ln -sfn /usr/local/cuda-11.8 /usr/local/cuda    # 切换默认版本
nvcc --version                                       # 确认已切换

更好的实践:让用户/任务在自己的环境或作业脚本中显式指定版本,而不是改全局软链接:

bash
export PATH=/usr/local/cuda-11.8/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda-11.8/lib64:$LD_LIBRARY_PATH

生产经验:能容器化的业务尽量用容器隔离 CUDA 版本(第 8 章),宿主机保持单一 Toolkit 甚至不装,管理成本最低。

7.4 Fabric Manager:NVSwitch 机型必装组件

是什么、为什么:Fabric Manager 是 NVIDIA 的系统服务(nvidia-fabricmanager),负责初始化 NVSwitch 交换矩阵,让 8 张 GPU 通过 NVSwitch 全互联。适用机型:采用 NVSwitch 的 SXM 8 卡机,如 HGX A100 / HGX H100 / DGX 系列。PCIe 卡机型不需要安装

不装的后果:驱动能装上、nvidia-smi 也能看到 8 张卡,但 NVLink 不通,多卡训练报错或退化——nvidia-smi topo -m 里看不到 NV# 互联。

版本必须严格匹配:Fabric Manager 版本号必须与驱动完全一致(驱动 570.86.15 对应 Fabric Manager 570.86.15),否则服务启动失败。用同一仓库安装可自动对齐:

bash
sudo apt install -y nvidia-fabricmanager-570        # 与驱动同版本
sudo systemctl enable --now nvidia-fabricmanager    # 启动并开机自启
sudo systemctl status nvidia-fabricmanager          # Active: active (running) 即正常
nvidia-smi topo -m                                  # 验证:8 卡之间应全为 NV# 互联

升级驱动时必须同步升级 Fabric Manager,否则重启后服务起不来——这是生产常见事故点,升级脚本里务必把两个包一起更新。

7.5 持久模式与 GPU 时钟

持久模式(Persistence Mode):默认情况下,没有进程使用 GPU 时,Linux 会卸载 GPU 驱动状态以省电,下次使用时重新初始化,带来数百毫秒级延迟。开启持久模式让驱动常驻:

bash
sudo nvidia-smi -pm 1                          # 开启(-i 可指定单卡)
nvidia-smi -q -d PERFORMANCE | grep -i persistence    # 查看

生产建议:所有 GPU 服务器开启持久模式。重启保持方式:写入 systemd 单元或启动脚本(新驱动也可使用 nvidia-persistenced 服务)。

GPU 时钟管理:GPU 时钟会根据负载、温度、功耗动态调整。对性能有严格要求的场景可以锁定:

bash
nvidia-smi -q -d SUPPORTED_CLOCKS      # 查看支持的时钟范围(单位 MHz,以实际输出为准)
sudo nvidia-smi -lgc 1500,1980         # 锁定 Graphics 时钟区间
sudo nvidia-smi -lgc 1980,1980         # 锁死最高频率
sudo nvidia-smi -lmc 1215,1215         # 锁定显存时钟
sudo nvidia-smi -rgc && sudo nvidia-smi -rmc    # 恢复自动调节

应用时钟(Application Clocks):指定 GPU 运行应用时的目标时钟,与 -lgc(锁定范围)不同:

bash
sudo nvidia-smi -ac 1215,1410    # <显存时钟,图形时钟>

运维建议:

  • 性能基准测试/交付验收时锁定时钟,保证结果可复现;日常生产一般不锁死最高频(费电、发热大)。
  • 发现 GPU 莫名变慢,先查 nvidia-smi -q -d PERFORMANCE 里的 Clocks Event Reasons(降频原因:温度、功耗、空闲等)。

本章小结

  • CUDA Toolkit 提供 nvcc 与运行时库;裸金属开发/编译需要装,纯跑容器可以不装。装后配置 PATHLD_LIBRARY_PATH,用 nvcc --version 验证。
  • deviceQuerybandwidthTest 验证计算与带宽;带宽明显偏低要查插槽、Above 4G Decoding 和硬件。
  • 多版本 CUDA 通过 /usr/local/cuda-x.y 共存,软链接或环境变量切换;更推荐容器隔离。
  • NVSwitch 机型必须装 Fabric Manager,版本与驱动严格一致,用 systemd 管理,升级驱动时同步升级。
  • 生产开启持久模式(nvidia-smi -pm 1);时钟可锁定(-lgc)用于基准测试,异常变慢先查降频原因。

动手实验

  1. 安装 CUDA Toolkit,配置环境变量,执行 nvcc --version 并与 nvidia-smi 的 CUDA Version 对比,解释两者区别。
  2. 编译运行 deviceQuerybandwidthTest,记录 GPU 型号、计算能力和实测带宽,判断是否符合 PCIe 代际预期。
  3. 安装两个版本的 cuda-toolkit,练习用软链接和环境变量两种方式切换 nvcc 版本。
  4. 执行 sudo nvidia-smi -pm 1 并验证;思考如何让它开机自动生效(写一个 systemd unit)。
  5. 执行 nvidia-smi -q -d PERFORMANCE,查看当前时钟与降频原因字段。

第 8 章 NVIDIA Container Toolkit(容器运行 GPU)

本章目标

  • 理解容器使用宿主机 GPU 的原理
  • 独立完成 nvidia-container-toolkit 安装与 containerd/Docker 配置
  • 掌握 GPU 容器验证命令与 NVIDIA_VISIBLE_DEVICES 卡分配控制
  • 讲清楚容器内 CUDA 版本与宿主机驱动的兼容性规则
  • 掌握生产镜像选择与"容器里不装驱动"的原则

8.1 原理:容器如何使用宿主机 GPU

问题背景:容器本质是宿主机上隔离的进程,共享宿主机内核。容器里的 CUDA 程序要访问 GPU,需要两样东西:

  1. 设备文件/dev/nvidia0/dev/nvidia1(每张卡一个)、/dev/nvidiactl/dev/nvidia-uvm 等,由宿主机驱动创建。
  2. 用户态驱动库libcuda.so 等,版本必须与宿主机内核驱动完全匹配

nvidia-container-toolkit 的作用:启动容器时,它作为"钩子"自动把宿主机上的设备文件和驱动库注入容器,容器内程序就能像物理机一样调用 GPU。

记住两条铁律

  • 驱动只装在宿主机,容器镜像里绝不装驱动
  • 容器内自带 CUDA Runtime(在镜像里),宿主机驱动决定"最高支持到哪个 CUDA"。

8.2 安装 nvidia-container-toolkit 与配置运行时

安装(Ubuntu 22.04/24.04)

bash
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
  sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list

sudo apt update && sudo apt install -y nvidia-container-toolkit

配置 Docker 运行时

bash
sudo nvidia-ctk runtime configure --runtime=docker    # 自动修改 /etc/docker/daemon.json
sudo systemctl restart docker

配置 containerd 运行时(K8s 节点常用):

bash
sudo nvidia-ctk runtime configure --runtime=containerd    # 自动修改 /etc/containerd/config.toml
sudo systemctl restart containerd

在 Kubernetes 集群中,第四部分会讲用 NVIDIA GPU Operator 自动完成这一切;但手动安装的原理必须掌握,排错时用得上。

8.3 验证与 GPU 分配控制

基础验证

bash
docker run --rm --gpus all nvidia/cuda:12.4.1-base-ubuntu22.04 nvidia-smi

能打印出宿主机 GPU 列表即成功。

控制容器能看到哪些卡

bash
docker run --rm --gpus '"device=0"' nvidia/cuda:12.4.1-base-ubuntu22.04 nvidia-smi     # 只分配 0 号卡
docker run --rm --gpus '"device=0,2"' nvidia/cuda:12.4.1-base-ubuntu22.04 nvidia-smi   # 分配 0 和 2 号卡

NVIDIA_VISIBLE_DEVICES 环境变量(底层机制,K8s Device Plugin 注入的也是它):

bash
# 效果等同 --gpus '"device=1"'
docker run --rm -e NVIDIA_VISIBLE_DEVICES=1 nvidia/cuda:12.4.1-base-ubuntu22.04 nvidia-smi

# 经典坑:设成 none 后即使 --gpus all 也看不到卡
docker run --rm --gpus all -e NVIDIA_VISIBLE_DEVICES=none nvidia/cuda:12.4.1-base-ubuntu22.04 nvidia-smi
# 输出:Failed to initialize NVML ...

注意:容器内 nvidia-smi 显示的 GPU 编号是重映射后的(容器内从 0 开始),与宿主机编号不一定一致。排查任务占错卡时,用 NVIDIA_VISIBLE_DEVICES 的值对照宿主机编号。

8.4 容器内 CUDA 版本与宿主机驱动的兼容性规则

核心规则(务必记住)

  1. 宿主机驱动决定上限nvidia-smi 右上角 CUDA Version 是驱动支持的最高 CUDA 版本。容器内 CUDA Runtime 版本 该值即可运行。
  2. 小版本兼容(Minor Version Compatibility):同一 CUDA 大版本内(如 12.x),低版本 Toolkit 编译的程序可在更高版本驱动上运行;跨大版本不行(CUDA 12 的镜像不能在只支持 CUDA 11 的老驱动上跑)。
  3. 向前兼容包(Forward Compatibility):老驱动跑新 CUDA 的特例方案,通过 cuda-compat 包实现,主要用于特定场景(如 vGPU),不作为常规手段。

实操检查方法:

bash
nvidia-smi | grep "CUDA Version"          # 宿主机驱动支持的最高 CUDA
docker run --rm nvidia/cuda:12.4.1-base-ubuntu22.04 bash -c "cat /usr/local/cuda/version.json | head -5"

运维决策:升级业务镜像(CUDA 更高)前,先确认全集群驱动支持;驱动升级计划要先盘点容器镜像的 CUDA 需求。兼容性矩阵以 NVIDIA 官方文档(CUDA Compatibility)为准。

8.5 生产建议:镜像选择与"不要往容器里装驱动"

nvidia/cuda 官方镜像的 tag 构成nvidia/cuda:<CUDA版本>-<类型>-<系统>,三种类型:

类型内容体积适用
base最小 CUDA Runtime(libcudart 等)最小运行已编译好的 CUDA 程序
runtimebase + CUDA 数学库(cuBLAS、cuDNN 等)跑深度学习框架,生产镜像首选基础
develruntime + nvcc 编译器、头文件最大编译期使用(多阶段构建的 builder 阶段)

典型做法(多阶段构建,编译与运行分离):

dockerfile
FROM nvidia/cuda:12.4.1-devel-ubuntu22.04 AS builder    # 编译阶段用 devel
COPY . /src
RUN make -C /src

FROM nvidia/cuda:12.4.1-runtime-ubuntu22.04             # 运行阶段用 runtime,镜像小、攻击面小
COPY --from=builder /src/app /usr/local/bin/app
CMD ["app"]

生产建议清单

  • [ ] 镜像基于官方 nvidia/cuda 或 NGC(nvcr.io)框架镜像(如 nvcr.io/nvidia/pytorch:xx.xx-py3),不要自己从零组装 CUDA。
  • [ ] 绝不在 Dockerfile 里 apt install nvidia-driver-* 或执行 .run 驱动包——驱动必须且只能来自宿主机注入。镜像里装驱动导致库版本错乱,是最经典的新手事故。
  • [ ] 镜像 tag 锁定到具体版本(不用 latest),保证可复现。
  • [ ] 推理服务优先用 TensorRT-LLM / Triton 等 NGC 优化镜像。
  • [ ] 镜像安全扫描纳入 CI;devel 镜像不进生产运行时。

本章小结

  • 容器用 GPU 的原理:宿主机驱动创建 /dev/nvidia* 设备文件,nvidia-container-toolkit 在容器启动时注入设备文件和匹配的用户态驱动库。
  • 安装 nvidia-container-toolkit 后用 nvidia-ctk runtime configure 配置 docker/containerd;用 docker run --rm --gpus all nvidia/cuda:... nvidia-smi 验证。
  • --gpus device=NNVIDIA_VISIBLE_DEVICES 控制卡分配,容器内卡号会重映射。
  • 兼容性铁律:容器 CUDA Runtime 版本不超过驱动支持的最高 CUDA(跨大版本不行);镜像升级与驱动升级要互相盘点。
  • 镜像选 runtime 跑业务、devel 做编译;容器里永远不装驱动。

动手实验

  1. 在装好驱动的机器上安装 nvidia-container-toolkit,配置 Docker,执行 docker run --rm --gpus all nvidia/cuda:12.4.1-base-ubuntu22.04 nvidia-smi 并记录输出。
  2. --gpus '"device=0"'NVIDIA_VISIBLE_DEVICES 各做一次单卡分配实验,观察容器内 nvidia-smi 卡号变化。
  3. 找一个含 PyTorch 的镜像,执行 python -c "import torch; print(torch.cuda.is_available())",验证框架可用 GPU。
  4. 查看宿主机 nvidia-smi 的 CUDA Version,再分别拉一个 CUDA 11.8 和 CUDA 12.x 镜像跑 nvidia-smi,用实验验证 8.4 节兼容性规则。
  5. 思考题:为什么 K8s 里通过 resources.limits.nvidia.com/gpu: 1 申请 GPU 的 Pod,最终也是靠 NVIDIA_VISIBLE_DEVICES 实现分配的?(预习第四部分)

本部分回顾

至此,你已经完成了一台 GPU 服务器从到货上架、验收检查、BIOS 基线、驱动安装、CUDA Toolkit、Fabric Manager 到容器运行 GPU 的完整环境搭建。这套流程是 GPU 运维工程师的"基本功",后续第三部分(虚拟化与共享)和第四部分(Kubernetes GPU 调度)都建立在这个环境之上。

下一部分预告:一张昂贵的 A100/H100 只跑一个小任务太浪费——第三部分将学习 GPU 直通、vGPU、MIG、MPS、时间片共享等技术,让一张卡安全高效地服务多个用户。