6.12 AI 基础设施基础——GPU、CUDA 与模型服务
预计阅读时间:14 分钟
📖 目录
学习目标
学完本章后,你将能够:
- 理解 GPU 的硬件架构和 CUDA 软件栈的层次关系
- 在 Linux 上安装 NVIDIA 驱动并验证 GPU 可用性
- 使用 NVIDIA Container Toolkit 让 Docker 容器访问 GPU
- 部署 vLLM 和 Triton Inference Server 提供推理服务
- 使用 nvidia-smi 和 DCGM 监控 GPU 健康状态和性能
- 排查常见的 GPU/CUDA 错误和性能瓶颈
核心知识
- GPU(Graphics Processing Unit)——最初为图形渲染设计的并行处理器,因大量 CUDA 核心适合矩阵运算,成为 AI 加速的核心硬件
- CUDA(Compute Unified Device Architecture)——NVIDIA 的并行计算平台和编程模型,允许开发者用 C/C++ 直接调用 GPU 进行计算
- cuDNN(CUDA Deep Neural Network Library)——NVIDIA 针对深度神经网络优化的 GPU 加速库,提供卷积、归一化、激活函数等高性能实现
- NVIDIA Driver——操作系统与 GPU 硬件之间的通信层,包含内核模块(nvidia.ko)和用户空间库(libcuda.so)
- NVIDIA Container Toolkit——在容器中暴露 GPU 设备文件的工具链,核心是 nvidia-container-runtime 和 nvidia-container-cli
- vLLM——高性能 LLM 推理引擎,核心创新是 PagedAttention(分页显存管理),支持连续批处理和流式输出
- Triton Inference Server——NVIDIA 官方的多模型推理服务框架,支持 TensorRT/ONNX/PyTorch 等多种后端
- DCGM(Data Center GPU Manager)——NVIDIA 的数据中心 GPU 管理工具,提供比 nvidia-smi 更细粒度的遥测和健康检查
知识关联
- 前置知识:了解 Linux 包管理(apt/yum)、Docker 基本用法(3.1:Docker 容器入门)、命令行基础
- 后续影响:本章的 GPU 环境是运行 LLM 训练/推理、模型微调、生成式 AI 应用的硬件基础
- 配套技术:nvidia-smi/DCGM 用于监控,可配合 Prometheus/Grafana 构建 GPU 仪表盘
- 在整个体系中的位置:AI 基础设施的底层——GPU 硬件层 → 驱动/CUDA 层 → 容器运行时 → 推理框架 → 上层应用
原理讲解
1. GPU 硬件架构——从图形卡到 AI 加速器
GPU 与传统 CPU 的设计哲学截然不同:CPU 追求低延迟串行执行(几十个强大核心),GPU 追求高吞吐并行计算(数千个精简核心)。
| 维度 | CPU | GPU |
|---|---|---|
| 核心数量 | 4-64 个 | 数千个(如 A100 含 6912 个 CUDA 核心) |
| 设计目标 | 低延迟,单线程性能最大化 | 高吞吐,大量线程同时执行 |
| 内存架构 | 大容量 DDR(几十 GB) | 高带宽 HBM(几十 GB,带宽可达 2TB/s) |
| 适合任务 | 分支密集、延迟敏感的控制逻辑 | 数据并行、计算密集的矩阵运算 |
| 典型功耗 | 65-300W | 150-700W |
NVIDIA GPU 内部以 SM(Streaming Multiprocessor) 为基本计算单元。每个 SM 包含一组 CUDA 核心、共享内存、寄存器文件和 warp 调度器。以 A100 为例:108 个 SM × 64 个 CUDA 核心/SM = 6912 CUDA 核心。GPU 在执行矩阵乘法(AI 推理的核心算力)时,数千个线程同时计算,做到"乘法比加法还快"的并行效果。
2. CUDA 软件栈——从驱动到框架的四层结构
在 Linux 上运行 AI 模型,涉及从硬件到应用的完整软件栈:
| 层 | 组件 | 作用 |
|---|---|---|
| 应用层 | vLLM / PyTorch / TensorFlow | 调用 cuBLAS/cuDNN 执行 AI 计算 |
| 加速库层 | cuBLAS / cuDNN / TensorRT | 封装底层 CUDA 调用,提供高度优化的矩阵运算 |
| CUDA 运行时层 | CUDA Runtime API / Driver API | 管理 GPU 内存、启动 kernel、设备管理 |
| 驱动层 | NVIDIA Kernel Driver (nvidia.ko) | OS 与 GPU 硬件的通信通道 |
关键认知:驱动是唯一需要直接安装在宿主机上的组件。CUDA 工具链和加速库可以装在 Docker 容器内(通过 NVIDIA Container Toolkit 暴露驱动),这就是"驱动在宿主机、CUDA 在容器"的最佳实践。
3. nvidia-smi 指标解读——读懂 GPU 健康状态
nvidia-smi 是运维 GPU 服务器最常用的工具。理解每一列的真正含义比跑出数字更重要:
| 指标 | 含义 | 正常范围 | 警示值 |
|---|---|---|---|
| GPU-Util | GPU 计算核心利用率(非显存带宽利用率) | 0-100% | 持续 100% 不释放(死循环) |
| Memory-Usage | 已用显存 / 总显存 | 模型大小 + 10-20% 余量 | >95%(OOM 风险) |
| Temp | GPU 核心温度 | 30-80°C | >85°C(降频阈值) |
| Pwr:Usage/Cap | 当前功耗 / 最大功耗 | 30-100% | 接近但低于 Cap 正常 |
| Volatile Uncorr. ECC | 无法纠正的显存错误计数 | 0 | >0(显存可能损坏) |
| Persistence-M | 持久化模式(初始化状态保持) | On | Off(首次调用慢) |
4. vLLM 推理架构——PagedAttention 与连续批处理
vLLM 是目前最流行的 LLM 推理引擎。它的两个核心创新让 GPU 显存利用率大幅提升:
PagedAttention:传统方案为每个请求的 KV Cache 预分配连续显存(类似内存碎片问题),PagedAttention 像操作系统的分页机制——将 KV Cache 分成固定大小的 block,按需分配、非连续存储,消除了内部碎片。
Continuous Batching:传统方案等一批请求全部完成后才切换下一批;Continuous Batching 在每个推理 step 后动态调度——已完成请求离开、新请求加入队列,最大化 GPU 利用。
5. 多卡并行——模型放不下单张卡时的三种切法
大模型(70B+)单卡放不下时,需要把模型或数据拆分到多张 GPU。三种主流并行方式对应三种"切法":
| 并行方式 | 切什么 | 通信需求 | 典型场景 |
|---|---|---|---|
| 数据并行(DP) | 复制模型到每张卡,分片喂数据 | 低(每 step 同步梯度) | 训练加速,卡数越多吞吐越高 |
| 张量并行(TP) | 把单层矩阵切成 N 块放到 N 张卡 | 高(每层都要 AllReduce) | 推理+训练,模型必须能放进单节点 |
| 流水线并行(PP) | 按层切段:卡 0 跑第 1-20 层,卡 1 跑 21-40 层 | 中(段间传输激活值) | 超大规模训练,跨节点扩展 |
vLLM 推理场景通常只涉及 张量并行(--tensor-parallel-size),因为它对显存的改善最直接。注意两个反直觉点:
- TP 不省总显存:7B 模型在 1 张 24G 卡上放不下时,切成 TP=2 每张卡各放一半模型权重(≈4GB)——但 KV Cache 也要按比例分配,总显存需求仍是"模型全部权重 + KV Cache"
- TP 越高通信开销越大:TP=8 时每层 attention 都要跨卡通信,PCIe 带宽会成为瓶颈。同节点优先用 NVLink;跨节点做 TP 性能会显著下降
# vLLM 多卡启动(2 张 A100 跑 70B 模型)
docker run --gpus '"device=0,1"' \
-p 8000:8000 -v /models:/models \
vllm/vllm-openai:v0.6.0 \
--model /models/Qwen2.5-70B-Instruct \
--tensor-parallel-size 2 \
--gpu-memory-utilization 0.9
# 显存放不下时的降级路径(按性价比排序):
# ① 量化:AWQ/GPTQ 4bit(显存减半,精度损失小)→ 首选
# ② 减小 max-model-len(限制 KV Cache 上限)
# ③ 减小 gpu-memory-utilization 并加 --swap-space(CPU offload,变慢)
# ④ 换更大显存卡 / 增加 TP 卡数
示例代码
NVIDIA 驱动安装与验证
# 检查 GPU 型号
lspci | grep -i nvidia
# 输出: NVIDIA Corporation GA102 [GeForce RTX 3080]
# 查看推荐驱动版本
ubuntu-drivers devices
# 输出:
# driver : nvidia-driver-570 - third-party non-free recommended
# driver : nvidia-driver-535 - third-party non-free
# 安装推荐驱动
apt update && apt install -y nvidia-driver-570
reboot
# 验证驱动
nvidia-smi
# 输出:
# +-----------------------------------------------------------------------------+
# | NVIDIA-SMI 550.xx Driver Version: 550.xx CUDA Version: 12.4 |
# |-------------------------------+----------------------+----------------------+
# | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
# | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
# | 0 GeForce RTX 3080 Off | 00000000:01:00.0 On | N/A |
# | 30% 65°C P0 120W / 320W| 2048MiB / 10240MiB | 45% Default |
# +-------------------------------+----------------------+----------------------+
NVIDIA Container Toolkit 配置
# 安装 NVIDIA Container Toolkit
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \
sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -sL 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
apt update && apt install -y nvidia-container-toolkit
systemctl restart docker
# 验证 GPU 在容器中可访问
docker run --gpus all nvidia/cuda:12.4-runtime-ubuntu22.04 nvidia-smi
# 指定特定 GPU
docker run --gpus '"device=0"' nvidia/cuda:12.4-runtime-ubuntu22.04 nvidia-smi
# 检查 nvidia-container-cli 是否正常工作
nvidia-ctk cdi list
# 输出: nvidia.com/gpu=0 (列出可用 GPU)
vLLM 推理服务部署
# 启动 vLLM(Docker)
docker run --gpus all \
-p 8000:8000 \
-v /path/to/models:/models \
vllm/vllm-openai:v0.6.0 \
--model /models/Qwen2.5-7B-Instruct \
--tensor-parallel-size 1 \
--gpu-memory-utilization 0.9 \
--max-model-len 8192
# 调用推理接口(兼容 OpenAI API)
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen2.5-7B-Instruct",
"messages": [{"role": "user", "content": "用文言文写一段 Linux 的简介"}],
"temperature": 0.7,
"max_tokens": 512
}'
GPU 监控——nvidia-smi 与 DCGM
# 实时监控
watch -n 1 nvidia-smi
# 详细指标(DCGM)
apt install -y datacenter-gpu-manager
dcgmi group -c all
dcgmi dmon -e 1001,1002,1003,1004
# 输出: GPU 温度、功耗、显存带宽利用率
# Prometheus GPU Exporter(容器化)
docker run -d --gpus all --restart unless-stopped \
-p 9835:9835 \
nvidia/dcgm-exporter:latest
# Prometheus 抓取: http://localhost:9835/metrics
# 关键指标: DCGM_FI_DEV_GPU_UTIL, DCGM_FI_DEV_MEM_COPY_UTIL, DCGM_FI_DEV_POWER_USAGE
Triton Inference Server 配置
# docker-compose.yml
services:
triton:
image: nvcr.io/nvidia/tritonserver:24.06-py3
command: tritonserver --model-repository=/models --http-port=8000 --grpc-port=8001
ports:
- "8000:8000"
- "8001:8001"
volumes:
- ./models:/models
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
GPU 故障排查流程——从现象到根因
# 场景:模型推理突然报错或变慢,按以下顺序排查
# 第一步:确认 GPU 还在不在(驱动层面)
nvidia-smi
# 失败 → 驱动问题:dmesg | grep -i nvidia 查内核报错,重启或重装驱动
# 成功 → 看 Perf 列:P0(全速)/ P2-P3(降频)/ P8(空闲)
# 第二步:确认硬件健康(温度/功耗/ECC)
nvidia-smi -q -d TEMPERATURE,POWER,ECC
# 温度 > 85°C → 散热问题(清灰/机房空调/降功耗 nvidia-smi -pl 250)
# Uncorr ECC > 0 → 显存损坏,申请换卡
# 第三步:确认是"算不动"还是"等数据"(计算 vs 带宽)
nvidia-smi --query-gpu=utilization.gpu,utilization.memory --format=csv
# gpu 高 + memory 低 → 计算密集,正常(如训练)
# gpu 低 + memory 高 → 显存带宽瓶颈(如长序列推理)
# 两者都低 → 进程在等 CPU/磁盘/网络(数据加载慢、单请求串行)
# 第四步:确认进程与显存占用
nvidia-smi --query-compute-apps=pid,used_memory --format=csv
fuser -v /dev/nvidia0 # 谁占用了 GPU 0
# 显存碎片化:重启推理服务进程是最快的清理手段
# 第五步:核对日志与配置
# 推理服务日志中找 CUDA OOM / NCCL timeout / DRIVER version mismatch
# NCCL timeout → 多卡通信异常:检查 NVLink 状态(nvidia-smi nvlink -s)
常见错误
| 错误 | 原因 | 解决方案 |
|---|---|---|
nvidia-smi: command not found | 驱动未安装或 PATH 未包含 | apt install nvidia-driver-* 或检查 /usr/lib/nvidia-*/bin |
NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver | 驱动加载失败或内核升级后驱动未重编译 | 重启;或 modprobe nvidia,必要时重装驱动 |
docker: Error response from daemon: could not select device driver "" with capabilities: [[gpu]] | NVIDIA Container Toolkit 未安装或 docker 未重启 | apt install nvidia-container-toolkit && systemctl restart docker |
| CUDA 版本不兼容(应用要求 CUDA 12.x 但宿主机只装了 11.x) | 宿主机只装驱动,容器内 CUDA 版本可以不同 | 宿主机只需驱动版本 >= 容器 CUDA 的最低驱动需求;检查 nvidia-smi 的 CUDA Version 字段 |
CUDA out of memory | 模型 + KV Cache + 框架开销超过显存总量 | 减小 --max-model-len、减小 --gpu-memory-utilization、使用量化(4bit/8bit) |
Volatile Uncorr. ECC 计数 > 0 | 显存出现不可纠正的硬件错误 | 运行 nvidia-smi -q -d ECC 确认错误位置;联系云厂商换卡或申请 RMA |
| GPU-Util 持续 0% 但推理慢 | 显存带宽瓶颈或数据传输(PCIe 带宽不足) | 检查 nvidia-smi 的 Mem Copy Util;换用更高带宽的 GPU 型号 |
最佳实践
| # | 实践 | 说明 |
|---|---|---|
| 1 | 宿主机只装驱动,CUDA 走容器 | 驱动是唯一必须装在宿主机上的组件。CUDA 工具链、cuDNN、PyTorch 都放 Docker 镜像,环境隔离、版本管理灵活 |
| 2 | 开启 Persistence Mode | nvidia-smi -pm 1 保持 GPU 初始化状态,避免每次调用 nvidia-smi 时重新初始化 |
| 3 | 推理时留 10-15% 显存余量 | --gpu-memory-utilization 设为 0.85-0.9,给内核、驱动和框架临时分配留空间 |
| 4 | 监控 Volatile ECC 计数器 | 定期检查 nvidia-smi -q -d ECC,>=0 时换卡,避免推理结果被显存错误污染 |
| 5 | tensor-parallel-size = GPU 数量 | 多卡推理时设置 TP = 卡数,注意显存总量 > 模型大小 × 卡数 |
| 6 | 使用 DCGM Exporter 接入 Prometheus | 生产环境不要只靠 nvidia-smi,用 dcgm-exporter 指标构建 Grafana 仪表盘 |
| 7 | 内核升级后重装驱动 | Linux 内核升级后 NVIDIA 内核模块需要重新编译。建议 apt 安装(自动处理 DKMS)而非 .run 包 |
练习题
- (概念)解释 GPU 和 CPU 在架构设计上的根本差异。为什么 GPU 适合 AI 推理而 CPU 不适合?
- (概念)"驱动在宿主机、CUDA 在容器"是什么意思?这样做的好处是什么?
- (概念)解释 vLLM 的 PagedAttention 如何提高显存利用率。
- (实操)在 Linux 上安装 NVIDIA 驱动,运行
nvidia-smi并记录输出的 GPU 型号、驱动版本、CUDA 版本、显存总量。 - (实操)部署 NVIDIA Container Toolkit,运行
docker run --gpus all nvidia/cuda:12.4-runtime-ubuntu22.04 nvidia-smi验证容器内 GPU 可用。 - (实操)使用 Docker 部署 vLLM(任意支持的小模型如 Qwen2.5-7B),通过 curl 调用
/v1/chat/completions接口完成一次对话。 - (探究 🔍)查看
nvidia-smi -q -d ECC的输出,确认你的 GPU 是否有 ECC 内存和当前错误计数。 - (探究 🔍)在容器内外分别运行
nvidia-smi,对比输出差异。思考:为什么nvidia-smi命令本身在容器内也能工作?
点击查看答案
- CPU 少量强核,侧重低延迟串行计算;GPU 大量弱核,侧重高吞吐并行计算。AI 推理本质是矩阵乘法的并行计算,GPU 可同时处理数千线程,CPU 受限于核数。
- NVIDIA 驱动(内核模块 nvidia.ko + libcuda.so)装在宿主机上直接管理 GPU 硬件。容器内通过 NVIDIA Container Toolkit 将 nvidia 设备挂载进去,无需在容器内装驱动。好处:容器镜像更小、驱动版本由宿主机统一管理、多容器共享 GPU 资源。
- 传统 KV Cache 预分配连续显存导致碎片和浪费。PagedAttention 将 KV Cache 分页管理(类似虚拟内存),按需分配页,消除内部碎片,支持 page sharing(同一 prompt 的多条请求共享 prefix 页),显存利用率从 ~40% 提升到 ~95%。
- nvidia-smi 输出示例:GPU 0: NVIDIA A100-SXM4-80GB, Driver 550.54.15, CUDA 12.4, Memory 81920 MiB。
- 容器内 nvidia-smi 应看到与宿主机相同的 GPU 信息(驱动版本、GPU 型号)。区别:容器无法看到 process name。
- vLLM Docker 启动后 POST
{"model":"Qwen2.5-7B","messages":[{"role":"user","content":"Hello"}]}到/v1/chat/completions,返回 id/choices/usage 等字段。 - ECC 开启时 Current 和 Pending 错误计数应为 0。非零表示有可纠正或不可纠正的显存错误,需联系云服务商换卡。
- nvidia-smi 本身不是 GPU 程序——它通过 libnvidia-ml.so 访问 NVML 库,NVIDIA Container Toolkit 将 /usr/lib/x86_64-linux-gnu/libnvidia-ml.so 挂载进容器,所以容器内也能调用。
学习检查点
学完本章后,请检验自己是否掌握以下内容:
| 检查项 | 自测问题 | 验证方法 |
|---|---|---|
| 概念理解 | 能用自己的话解释 AI 基础设施的 GPU 调度和模型服务架构 | 尝试向他人讲解 |
| 命令操作 | 能不查文档完成 NVIDIA GPU Operator 安装和模型部署 | 在终端实际执行 |
| 原理掌握 | 能说出 GPU 共享、显存管理和模型推理优化原理 | 画出流程图 |
| 故障排查 | 能独立排查 GPU 资源不足或模型服务 OOM 的问题 | 模拟故障并修复 |
| 最佳实践 | 能说明为什么需要为 AI 工作负载配置专用节点池 | 对比不同方案 |
本章总结
GPU 是 AI 时代最核心的计算硬件。在 Linux 上运行 AI 推理的完整路径:
- 硬件层——NVIDIA GPU(CUDA 核心 + HBM 显存),通过 PCIe 与主机通信
- 驱动层——NVIDIA 驱动(nvidia.ko + libcuda.so),唯一需要装在宿主机上的组件
- 容器运行时层——NVIDIA Container Toolkit,让 Docker 暴露 GPU 设备到容器
- 推理框架层——vLLM(PagedAttention + Continuous Batching)或 Triton Inference Server
- 监控层——nvidia-smi(即时)、DCGM Exporter + Prometheus(持续)
速查表
| 操作 | 命令 |
|---|---|
| 查看 GPU 状态 | nvidia-smi |
| 实时监控 | watch -n 1 nvidia-smi |
| 查看 ECC 错误 | nvidia-smi -q -d ECC |
| 持久化模式 | nvidia-smi -pm 1 |
| 设置最大功耗 | nvidia-smi -pl 250 |
| DCGM 详细监控 | dcgmi dmon -e 1001,1002,1003,1004 |
| DCGM Prometheus 导出 | docker run -d --gpus all -p 9835:9835 nvidia/dcgm-exporter |
下一步:掌握本章的 GPU 基础设施后,可以继续学习模型微调(LoRA/QLoRA)、多机多卡推理部署、以及 GPU 虚拟化/分片技术。
延伸阅读
- NVIDIA Driver Installation Quickstart Guide——NVIDIA 官方驱动安装文档
- NVIDIA Container Toolkit 安装指南——官方安装和配置文档
- vLLM 官方文档——PagedAttention、Continuous Batching 等核心机制详解
- Triton Inference Server GitHub——NVIDIA Triton 推理服务器仓库和示例
- NVIDIA DCGM 官方页面——Data Center GPU Manager 完整文档
- 书籍推荐:《Programming Massively Parallel Processors》(David Kirk & Wen-mei Hwu)——CUDA 编程经典教材