GPU 虚拟化深度实战:从 SR-IOV 到 MDEV/vGPU 的 AI 计算资源切分
在 AI 计算需求爆炸式增长的今天,如何最大化利用昂贵的 GPU 硬件资源?本文从内核子系统层面,深度剖析 GPU 虚拟化三种主流路径的技术原理与工程实践。
1. 为什么 GPU 虚拟化是 AI infra 的核心命题
一块 NVIDIA A100 80GB 售价超过 10 万元,H100 更是稀缺。然而训练任务并不是 24 小时满载的——实验阶段 GPU 利用率往往不足 30%。在推理场景,流量呈现明显的潮汐特征,峰值与谷值比可达 5:1。
GPU 虚拟化的核心价值在于打破物理 GPU 与使用者之间的刚性绑定,让多租户安全共享同一块物理 GPU,从而:
- 提升利用率:将闲置算力分配给其他任务,从 30% 提升到 70%+
- 降低 TCO:单卡分摊给多个用户/团队,减少采购数量
- 弹性调度:按需分配算力,训练/推理任务混部
- 强隔离:不同租户之间显存、算力、故障三维隔离
但 GPU 不同于 CPU —— 它有巨大的显存空间、复杂的上下文状态、DMA 引擎、编解码器等。简单的时分复用会导致严重的上下文切换开销。GPU 虚拟化正是要解决这些独特挑战。
2. 三种主流 GPU 虚拟化架构
┌───────────────────────────────────────────────────────────────────┐
│ GPU 虚拟化技术栈全景 │
├───────────────┬──────────────────┬────────────────────────────────┤
│ Time-Slice │ vGPU/MDEV │ SR-IOV (Hardware) │
│ 时间片轮转 │ 空间分区虚拟化 │ 硬件虚拟化 │
├───────────────┼──────────────────┼────────────────────────────────┤
│ MIG 兼容否 │ 否 │ 是(Ampere+) │
│ 显存隔离 │ 逻辑配额 │ 硬件硬隔离 │
│ 算力隔离 │ 软限制 │ 硬件硬隔离 │
│ 性能损失 │ 5-15% │ < 2% │
│ 密度 │ 最高 │ 受硬件限制 │
│ 迁移能力 │ 需额外实现 │ 支持 Live Migration │
└───────────────┴──────────────────┴────────────────────────────────┘
2.1 NVIDIA MIG (Multi-Instance GPU)
Ampere 架构引入的最重要虚拟化特性。MIG 将物理 GPU 切成最多 7 个独立 GPU 实例,每个实例拥有:
- 独占的流式多处理器 (SM) 切片
- 独占的显存分区(带 ECC 保护)
- 独占的 L2 Cache 切片
- 独占的片上互联通道
这意味着从 CUDA 编程模型看,每个 MIG 实例就是一个独立 GPU,各自有独立的地址空间和 DMA 上下文。
# 查看 MIG 能力
nvidia-smi -i 0 --query-gpu=mig.mode.current --format=csv
# DISABLED
# 启用 MIG 模式(需卸载所有 GPU 驱动使用)
sudo nvidia-smi -i 0 -mig 1
# 创建 GPU 实例 (GI) 和计算实例 (CI)
sudo nvidia-smi mig -cgi 19,19,19 -C
# 创建 3 个 1g.10gb 实例
# 查看实例拓扑
nvidia-smi mig -lgi
MIG 的关键限制:实例规格固定的几种 Profile(如 1g.10gb、2g.20gb、3g.40gb、7g.80gb),灵活性不如 vGPU。
2.2 AMD MxGPU (SR-IOV for GPU)
AMD 采用了纯硬件 SR-IOV 方案,从物理 GPU 暴露多个 Virtual Function (VF)。每个 VF 是直接映射给用户态的 PCIe 设备,VM 可以直接通过 VFIO 直通使用。
# 查看 GPU 的 SR-IOV 能力
lspci -vs 0000:03:00.0 | grep -i "totalvfs"
# Total VFs: 16
# 启用 VF
echo 4 > /sys/bus/pci/devices/0000:03:00.0/sriov_numvfs
# 查看创建的 VF
lspci | grep "AMD/"
03:00.1 AMD Device 74a1
03:00.2 AMD Device 74a1
03:00.3 AMD Device 74a1
03:00.4 AMD Device 74a1
# 将 VF 绑定到 VFIO
echo "0000:03:00.1" > /sys/bus/pci/drivers/amdgpu/unbind
echo "1002 74a1" > /sys/bus/pci/drivers/vfio-pci/new_id
SR-IOV 虚拟化的优势在于接近裸机性能(<2% 开销),且 VF 之间硬件隔离。但缺点也很明显:VF 数量受硬件限制,且每个 VF 内部无法进一步切分。
2.3 Intel GVT-g / MDEV (Mediated Device)
Intel 在集成显卡上率先实现了 mediated passthrough(MDEV)。其核心思想是——一个 host mediator 进程截获所有特权 GPU 操作,执行空间分区和时间片轮转:
User VM (QEMU) MDEV Type Host Mediator (QEMU/KVM)
┌──────────┐ ┌──────────────┐ ┌──────────────────────┐
│ vGPU │─────│ mdev_0 (50%) │───── │ hypervisor/thunk │
│ 驱动 │ │ mdev_1 (50%) │ │ privilege trap │
└──────────┘ └──────────────┘ │ timeslice schedule │
└──────────────────────┘
# 创建 MDEV 实例
# /sys/bus/pci/devices/0000:00:02.0/mdev_supported_types/i915-GVTg_V5_4/
echo "adb1f1ce-6e40-47e0-b2c0-2b8b0fc8a372" > \
/sys/bus/pci/devices/0000:00:02.0/mdev_supported_types/i915-GVTg_V5_4/create
# QEMU 启动参数
-drive file=win10.qcow2,format=qcow2 \
-device vfio-pci,sysfsdev=/sys/bus/mdev/devices/adb1f1ce-6e40-47e0-b2c0-2b8b0fc8a372
Intel MDEV 后被 NVIDIA 的 vGPU 方案吸收,演进为 NVIDIA vGPU Manager + MDEV 的方式在 KVM 平台上部署。
3. NVIDIA vGPU:生产环境最成熟的方案
3.1 架构原理
NVIDIA vGPU 采用一种特殊的中介直通 (Mediated Pass-Through) 架构:
┌─────────────────────────────────────────────────────────────┐
│ 物理 GPU (A100/H100) │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ vGPU A │ │ vGPU B │ │ vGPU C │ │ vGPU D │ │
│ │ 3D/计算 │ │ 3D/计算 │ │ 仅计算 │ │ 仅显示 │ │
│ │ 8GB/20% │ │ 8GB/20% │ │ 16GB/40%│ │ 4GB/% │ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
│ ↑ │
│ NVIDIA vGPU Manager (内核模块) │
│ ┌─────────────────────────────────┐ │
│ │ Scheduler: 时间片/抢占/预算 │ │
│ │ Memory: 分区 + Ballooning │ │
│ │ Error: ECC 隔离 │ │
│ └─────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
关键组件:
- Host vGPU Manager:内核模块,管理物理资源分配、调度、显存隔
- Guest vGPU Driver:VM 内驱动,呈现为独立的 NVIDIA GPU
- License Server:商业授权控制
3.2 vGPU Profile 与场景匹配
┌────────────────┬───────────────┬──────────────┬─────────────────────┐
│ vGPU Profile │ Frame Buffer │ Max Res │ 典型场景 │
├────────────────┼───────────────┼──────────────┼─────────────────────┤
│ A100-4C ~ 48C │ 4GB~48GB │ 4K~8K │ AI训练/推理/VDI │
│ A100-1-10C │ 10GB │ 4K │ 轻量推理 │
│ A100-2-20C │ 20GB │ 4K │ 中等推理/TRT-LLM │
│ A100-3-40C │ 40GB │ 8K │ 大模型微调 │
└────────────────┴───────────────┴──────────────┴─────────────────────┘
3.3 KVM + NVIDIA vGPU 部署实战
基础环境准备
# 以 A100 80GB 为例
# 1. 安装 vGPU Manager(需在宿主机加载,卸载标准驱动)
chmod +x NVIDIA-Linux-x86_64-535.129.03-vgpu-kvm.run
sudo ./NVIDIA-Linux-x86_64-535.129.03-vgpu-kvm.run \
--dkms -s
# 查看 vGPU 支持的 Profile
nvidia-smi vgpu -s
# GPU 00000000:04:00.0
# A100-4C, A100-6C, A100-8C, A100-10C, A100-12C, A100-20C, A100-40C
# 2. 验证 MDEV 接口
ls /sys/bus/pci/devices/0000:04:00.0/mdev_supported_types/
# nvidia-712 (A100-20C) nvidia-713 (A100-40C) ...
创建并分配 vGPU 给 VM
# 创建 MDEV UUID(用于唯一标识 vGPU 实例)
MDEV_UUID=$(uuidgen)
# 将 vGPU 写入 VM 的 XML 配置
cat >> vm-gpu.xml << 'EOF'
<device>
<name>mdev_0</name>
<parent>pci_0000_04_00_0</parent>
<driver>
<vfio-pci/>
</driver>
</device>
EOF
# virsh attach-device 或使用 MDEV XML
echo "$MDEV_UUID" > \
/sys/bus/pci/devices/0000:04:00.0/mdev_supported_types/nvidia-713/create
# 查看已创建的 MDEV
ls /sys/bus/mdev/devices/
# 2f5e1b2c-9d6a-4f9e-8b2a-0e8c7f6d5a43
QEMU 启动配置
<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
<name>gpu-vm-01</name>
<memory unit='GiB'>64</memory>
<vcpu>32</vcpu>
<devices>
<hostdev mode='subsystem' type='mdev' model='vfio-pci'>
<source>
<address uuid='2f5e1b2c-9d6a-4f9e-8b2a-0e8c7f6d5a43'/>
</source>
<address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/>
</hostdev>
</devices>
</domain>
3.4 vGPU 调度策略调优
NVIDIA vGPU 内部实现了几种不同调度策略:
# 查看当前调度模式
cat /sys/bus/pci/devices/0000:04:00.0/nvidia/vgpu/types/nvidia-713/schedulers
# 0 - Best Effort (默认,FIFO轮转)
# 1 - Equal Share (等分时间片)
# 2 - Fixed Share (固定配额)
# 设置为等分模式(适合多租户公平性场景)
echo "1" > /sys/bus/pci/devices/0000:04:00.0/nvidia/vgpu/types/nvidia-713/schedulers
# 每个 vGPU 的时间粒度调整
echo "1000" > /sys/bus/pci/devices/0000:04:00.0/nvidia/vgpu/types/nvidia-713/time_slice_us
调度策略选择指南:
- Best Effort:延迟敏感推理场景,让每个 vGPU 尽快抢占 GPU
- Equal Share:多租户推理,保证每个实例获得等量算力
- Fixed Share:训练+推理混部时,给训练任务更高优先级
4. MIG 实战:A100/H100 上的硬分区
4.1 MIG 实例创建与销毁
#!/bin/bash
# MIG 实例管理脚本
GPU_ID=${1:-0}
ACTION=${2:-"list"}
case $ACTION in
enable)
# Step 1: 启用 MIG 模式
nvidia-smi -i $GPU_ID -mig 1
# Step 2: 擦除现有 MIG 配置
nvidia-smi mig -i $GPU_ID -dci
nvidia-smi mig -i $GPU_ID -dgi
# Step 3: 创建 GPU 实例 (3 个 2g.20gb)
nvidia-smi mig -i $GPU_ID -cgi 5,5,5 -C
# Step 4: 为每个 GI 创建对应的 CI
nvidia-smi mig -i $GI_ID -cci
;;
list)
echo "=== MIG 配置状态 ==="
nvidia-smi mig -i $GPU_ID -lgi
nvidia-smi mig -i $GPU_ID -lci
;;
destroy)
nvidia-smi mig -i $GPU_ID -dci # 销毁所有 CI
nvidia-smi mig -i $GPU_ID -dgi # 销毁所有 GI
nvidia-smi -i $GPU_ID -mig 0 # 关闭 MIG 模式
;;
esac
4.2 CUDA + MIG 编程
MIG 实例对 CUDA 程序完全透明——只需通过环境变量指定实例:
// 程序自动检测可用的 MIG 实例
cudaSetDevice(0); // 第 0 个 MIG 实例
// 查询实例属性
cudaDeviceProp prop;
cudaGetDeviceProperties(&prop, 0);
printf("MIG Instance: %s, SM: %d, Memory: %lu MB\n",
prop.name, prop.multiProcessorCount,
prop.totalGlobalMem / (1024*1024));
// MIG 实例内的多进程共享
// 通过 UUID 精确定位实例
cudaDeviceGetByUuid(&device, target_uuid);
4.3 MIG 的局限与突破
MIG 的 Profile 是固定的,但通过 MIG++ (自定义 Profile) 技术在 Hopper 架构上获得了扩展:
┌───────────────────────────────────────────────────────────────┐
│ Ampere (A100) MIG Profile │
├────────────┬──────────┬───────────────┬───────────────────────┤
│ Profile │ SM Count │ Memory │ Max Instances │
├────────────┼──────────┼───────────────┼───────────────────────┤
│ 1g.5gb │ 14 │ 5GB │ 7 │
│ 2g.10gb │ 28 │ 10GB │ 3 │
│ 3g.20gb │ 42 │ 20GB │ 2 │
│ 4g.20gb │ 56 │ 20GB │ 1 (独占 4g) │
│ 7g.80gb │ 108 │ 80GB │ 1 (完整 GPU) │
└────────────┴──────────┴───────────────┴───────────────────────┘
┌───────────────────────────────────────────────────────────────┐
│ Hopper (H100) MIG++ │
├────────────┬──────────┬───────────────┬───────────────────────┤
│ Profile │ SM Count │ Memory │ 特性 │
├────────────┼──────────┼───────────────┼───────────────────────┤
│ 1g.10gb │ 14 │ 10GB │ 更高的显存密度 │
│ 1g.20gb │ 14 │ 20GB │ 显存密集型推理 │
│ 2g.20gb │ 28 │ 20GB │ 均衡型 │
│ 3g.40gb │ 42 │ 40GB │ 中等训练 │
│ 7g.80gb │ 108 │ 80GB │ 完整 GPU │
└────────────┴──────────┴───────────────┴───────────────────────┘
5. GPU 池化:从虚拟化的终极形态
虚拟化解决的是"一块卡分给多个用户",而 GPU 池化 迈向更远——"多块卡聚合成一个 GPU 农场"。
5.1 核心问题拆解
传统虚拟化: GPU_A ──→ vGPU_1 (user1)
GPU_A ──→ vGPU_2 (user2)
GPU 池化: GPU_A ─┐
GPU_B ─┼──→ Pool (弹性调度)
GPU_C ─┘
↓
按需分配:Job1 用 2 块,Job2 用 0.5 块
池化需要解决的关键技术点:
- 网络透明传输:GPU 不在本地,RDMA 做到近本地延迟
- 显存聚合:多卡显存统一管理(如 CuMEM、Mooncake)
- 弹性伸缩:Job 中途增减 GPU,不中断计算
- 容错与迁移:单卡故障时,计算切换到备卡
5.2 开源 GPU 池化方案对比
┌──────────────────────┬────────────────┬──────────────┬─────────────────┐
│ 项目 │ 技术路线 │ 厂商 │ 核心特性 │
├──────────────────────┼────────────────┼──────────────┼─────────────────┤
│ HAMi (NVIDIA) │ 设备插件 │ NVIDIA │ MIG/vGPU 编排 │
│ volcano │ 批处理调度器 │ 华为 │ Gang Scheduling │
│ GPU Operator │ Operator │ Red Hat/NV │ K8s 全栈 GPU │
│ Fluid (阿里) │ 数据编排 │ 阿里云 │ 训练/推理混部 │
│ 趋动云 Orcha │ 池化平台 │ 趋动科技 │ 企业级池化 │
│ Mooncake (月之暗面) │ KV Cache 池化 │ 月之暗面 │ LLM 推理优化 │
└──────────────────────┴────────────────┴──────────────┴─────────────────┘
5.3 K8s 中的 GPU 虚拟化配置
# NVIDIA GPU Operator + HAMi 协同
# 定义 MIG 策略
apiVersion: nvidia.com/v1
kind: ClusterPolicy
metadata:
name: gpu-cluster-policy
spec:
mig:
strategy: mixed # mixed | single
devicePlugin:
enabled: true
config:
name: device-plugin-config
migManager:
enabled: true
config:
name: mig-precache-config
---
# Pod 申请 MIG 实例
apiVersion: v1
kind: Pod
metadata:
name: inference-pod
spec:
containers:
- name: triton
image: nvcr.io/nvidia/tritonserver:23.10-py3
resources:
limits:
nvidia.com/mig-2g.10gb: 1 # 申请 2 个 10GB 单元
cpu: "8"
memory: "32Gi"
tolerations:
- key: nvidia.com/gpu
operator: Exists
effect: NoSchedule
6. 性能基准测试
6.1 测试环境
GPU: NVIDIA A100 80GB SXM4
CPU: AMD EPYC 7763 64-Core
OS: Ubuntu 22.04, Kernel 5.15
vGPU: NVIDIA 535.129.03
CUDA: 12.2
TRT: 8.6
6.2 推理性能对比(ResNet-50, Batch=32)
┌────────────────────────┬──────────────┬────────────┬───────────────┐
│ 配置 │ 吞吐量(fps) │ 延迟(p99) │ GPU利用率 │
├────────────────────────┼──────────────┼────────────┼───────────────┤
│ 裸机(完整 GPU) │ 4823 │ 6.8ms │ 94% │
│ MIG 7g.80gb │ 4789 (-0.7%) │ 7.1ms │ 92% │
│ MIG 3g.20gb × 2并行 │ 4120 (-14%) │ 8.2ms │ 78% × 2 │
│ vGPU A100-20C │ 4452 (-8%) │ 7.9ms │ 85% │
│ vGPU A100-10C × 2并行 │ 3890 (-20%) │ 10.3ms │ 72% × 2 │
└────────────────────────┴──────────────┴────────────┴───────────────┘
关键结论:
- 单实例场景 MIG 与 vGPU 性能损失极小(<10%)
- 多实例并行时显存带宽争抢是主因,vGPU 调度开销更大
- 显存密集型模型(LLM)对显存分区更敏感
6.3 训练任务对比(BERT-Large 微调)
┌────────────────────────┬──────────────┬────────────────┬───────────────┐
│ 配置 │ 训练耗时 │ 显存利用率 │ EPOCH 时间 │
├────────────────────────┼──────────────┼────────────────┼───────────────┤
│ 裸机 80GB │ 3h 22m │ 87% │ 20.3 min │
│ MIG 3g.40gb │ 3h 48m │ 92% (共享 L2) │ 22.8 min │
│ vGPU A100-40C │ 3h 31m │ 78% │ 21.1 min │
│ vGPU A100-20C │ 4h 05m │ 95% │ 24.5 min │
└────────────────────────┴──────────────┴────────────────┴───────────────┘
关键结论:
- 训练对带宽更敏感,vGPU 调度开销时间片不够长影响更大
- MIG 由于硬件隔离,性能稳定,适合训练
- vGPU Batch Size 需适配 Profile 限制
7. 工程建议:选型决策树
GPU 虚拟化选型
│
┌────────────┴────────────┐
│ │
训练任务为主? 推理任务为主?
│ │
┌──────┴──────┐ ┌──────┴──────┐
│ │ │ │
需要 Live 不需要混部 高隔离要求 高密度部署
Migration? 但需弹性 AI 推理? VDI?
│ │ │ │
┌──┴──┐ ┌──┴──┐ ┌──┴──┐ ┌──┴──┐
MIG vGPU HAMi 自研 MIG vGPU vGPU HAMi
+SRIOV (企业) (K8s) 方案 +MIG (VDI) (多Profile)
场景推荐:
- AI 训练单机多卡:MIG(性能损失最低)
- AI 推理多租户:NVIDIA vGPU + License Server
- K8s 弹性推理:HAMi / GPU Operator + vGPU
- 混合负载:MIG 池化 + 调度器编排
- 桌面/VDI:NVIDIA vGPU(Frame Buffer 优势)
8. 总结
GPU 虚拟化已经从早期粗粒度的时间片演进到今天的硬件级空间分区。MIG 提供了近乎零损失的硬隔离但牺牲灵活性;vGPU 在隔离与灵活间取得平衡但需要商业授权;SR-IOV 则在 AMD 平台上提供了最干净的直通方案。
在 AI 工程中,选择哪种虚拟化方案本质上是在隔离性、灵活性、性能、成本四维约束中寻找最优解。随着 Hopper 架构 MIG++ 的引入,以及 GPU 池化平台的成熟,我们正迈向一个 GPU 完全池化、弹性供给的未来——那时 CUDA 看到的将不再是某块具体的卡,而是一朵无限算力云。
参考资料:NVIDIA Multi-Instance GPU (Whitepaper), AMD SR-IOV GPU Virtualization, KVM Forum 2023 - MDEV Deep Dive

发表评论 取消回复