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 块

池化需要解决的关键技术点:

  1. 网络透明传输:GPU 不在本地,RDMA 做到近本地延迟
  1. 显存聚合:多卡显存统一管理(如 CuMEM、Mooncake)
  1. 弹性伸缩:Job 中途增减 GPU,不中断计算
  1. 容错与迁移:单卡故障时,计算切换到备卡

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

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部