MIG 分区实战把一个 GPU 切片给多个推理服务复用一、一块 A100 只跑一个 2GB 模型剩余 78GB 显存去哪了线上推理集群的 GPU 利用率常年低于 30%这是我们在 Prometheus 面板上看到的最令人不安的数据。检查发现大量在线推理服务每个容器独占一块完整的 NVIDIA A100-80GB GPU而实际加载的模型仅占用 2-6GB 显存。剩余的 70GB 显存和大量的 SM流式多处理器、内存带宽资源白白空转。基础设施不需要漂亮话GPU 利用率上不去就是资源浪费的直接证据。更麻烦的是一些中等规模模型如 13B 参数级单张 A100 放不下跨卡又引入通信开销。如何在不增加硬件投入的前提下用更精细的粒度切分 GPU 资源NVIDIA MIGMulti-Instance GPU提供了一个在硬件层面切分 GPU 的方案。MIG 可以将一块 GPU 从物理上切分为最多 7 个独立的 GPU 实例每个实例拥有独立的内存通道、L2 缓存和 SM 组。不是软件模拟不是虚拟化而是硬件隔离。这意味着一个推理容器 OOM不会影响同一张物理卡上的其他容器。这种故障隔离能力在多租户推理平台上是硬需求。二、MIG 切分机制从 SM 分区到显存隔离的硬件实现MIG 的核心原理是将 GPU 内部的计算单元GPC/TPC/SM和显存通道按预设策略切分为独立的 GPU 切片每个切片通过 PCIe 对外呈现为独立的 GPU 设备。操作系统和容器运行时看到的不再是/dev/nvidia0而是/dev/nvidia0、/dev/nvidia1直到/dev/nvidia6。graph TB subgraph NVIDIA A100-80GB 物理GPU GPC0[GPC Group 0br/14 SM L2 Cache] GPC1[GPC Group 1br/14 SM L2 Cache] GPC2[GPC Group 2br/14 SM L2 Cache] GPC3[GPC Group 3br/14 SM L2 Cache] GPC4[GPC Group 4br/14 SM L2 Cache] GPC5[GPC Group 5br/14 SM L2 Cache] GPC6[GPC Group 6br/14 SM L2 Cache] FB[Frame Bufferbr/80GB HBM2e] end MIG[MIG Mode Enabledbr/硬件分区控制器] subgraph GI 0: 3g.40gb GI0_SM[42 SM 12GB L2] GI0_MEM[40GB VRAM] end subgraph GI 1: 2g.20gb GI1_SM[28 SM 8GB L2] GI1_MEM[20GB VRAM] end subgraph GI 2: 1g.10gb GI2_SM[14 SM 4GB L2] GI2_MEM[10GB VRAM] end subgraph GI 3: 1g.10gb GI3_SM[14 SM 4GB L2] GI3_MEM[10GB VRAM] end GPC0 -- MIG GPC1 -- MIG GPC2 -- MIG GPC3 -- MIG GPC4 -- MIG GPC5 -- MIG GPC6 -- MIG FB -- MIG MIG -- GI0_SM MIG -- GI0_MEM MIG -- GI1_SM MIG -- GI1_MEM MIG -- GI2_SM MIG -- GI2_MEM MIG -- GI3_SM MIG -- GI3_MEM style MIG fill:#f9a825,stroke:#333,color:#000 style GI0_SM fill:#4caf50,color:#fff style GI1_SM fill:#2196f3,color:#fff style GI2_SM fill:#ff9800,color:#fff style GI3_SM fill:#9c27b0,color:#fffMIG 的粒度由gGPU Instance, GI和cCompute Instance, CI两级定义。GI 划分了计算资源和显存CI 则在 GI 内部进一步切分计算单元。上图中3g.40gb表示该实例拥有 3 组 GPC 的计算能力配 40GB 显存。在 A100-80GB 上支持的 GI Profile 包括1g.5gb、1g.10gb、2g.20gb、3g.40gb、4g.40gb、7g.80gb等组合。值得注意的是 MIG 的隔离级别。每个 GI 拥有独立的显存分区、L2 缓存分区和显存带宽配额。错误隔离Error Isolation确保一个 GI 的内存 ECC 错误不会波及同卡其他 GI。这是相比于 CUDA MPS 和时间片方案最核心的差异——后者是软件层面的隔离存在故障扩散风险。三、生产级 MIG 配置与 Kubernetes 集成以下是在 Kubernetes 集群中启用并分配 MIG 切片的完整流程。首先需要在 GPU 节点上开启 MIG 模式然后使用 NVIDIA GPU Operator 或手动配置 GI/CI。// mig_manager.go — MIG 配置管理客户端 // 职责通过 nvidia-smi 命令行工具管理 GPU 节点的 MIG 状态 // 注意nvidia-smi mig 子命令仅在 A100/A30/H100 等支持 MIG 的 GPU 上可用 package main import ( bytes context fmt os/exec strings time ) // MIGProfile 表示一个预定义的 MIG 切分配置 type MIGProfile struct { Name string // 例如 1g.10gb GICount int // GPU Instance 数量 CICount int // Compute Instance 数量通常与 GI 一致 } // MIGManager 封装 MIG 操作 type MIGManager struct { gpuIndex int // 目标 GPU 索引 timeout time.Duration } // NewMIGManager 创建 MIG 管理器 func NewMIGManager(gpuIndex int) *MIGManager { return MIGManager{ gpuIndex: gpuIndex, timeout: 30 * time.Second, } } // EnableMIG 在指定 GPU 上启用 MIG 模式 // 返回值需要重启节点才能使 MIG 模式生效 func (m *MIGManager) EnableMIG(ctx context.Context) error { ctx, cancel : context.WithTimeout(ctx, m.timeout) defer cancel() cmd : exec.CommandContext(ctx, nvidia-smi, -i, fmt.Sprintf(%d, m.gpuIndex), -mig, 1, ) var stderr bytes.Buffer cmd.Stderr stderr output, err : cmd.Output() if err ! nil { return fmt.Errorf(启用 MIG 模式失败 (GPU %d): %w, stderr: %s, m.gpuIndex, err, stderr.String()) } // MIG 模式切换后需要重启节点或执行 GPU reset if strings.Contains(string(output), requires a GPU reset) { return fmt.Errorf(MIG 模式已切换到启用需要 GPU reset 或重启节点 (GPU %d), m.gpuIndex) } return nil } // CreateGI 在指定 GPU 上创建 GPU Instance // profile 参数如 1g.10gbplacement 指定起始位置 func (m *MIGManager) CreateGI(ctx context.Context, profile string, placement int) (string, error) { ctx, cancel : context.WithTimeout(ctx, m.timeout) defer cancel() cmd : exec.CommandContext(ctx, nvidia-smi, mig, -i, fmt.Sprintf(%d, m.gpuIndex), -cgi, profile, -C, fmt.Sprintf(%d, placement), ) var stderr bytes.Buffer cmd.Stderr stderr output, err : cmd.Output() if err ! nil { return , fmt.Errorf(创建 GPU Instance 失败 (GPU %d, profile %s): %w, stderr: %s, m.gpuIndex, profile, err, stderr.String()) } // 解析输出获取 GPU Instance ID giID : strings.TrimSpace(string(output)) return giID, nil } // CreateCI 在指定的 GPU Instance 上创建 Compute Instance func (m *MIGManager) CreateCI(ctx context.Context, giID string, ciCount int) ([]string, error) { ctx, cancel : context.WithTimeout(ctx, m.timeout) defer cancel() cmd : exec.CommandContext(ctx, nvidia-smi, mig, -i, fmt.Sprintf(%d, m.gpuIndex), -gi, giID, -cci, fmt.Sprintf(%d, ciCount), ) var stderr bytes.Buffer cmd.Stderr stderr output, err : cmd.Output() if err ! nil { return nil, fmt.Errorf(创建 Compute Instance 失败 (GI %s): %w, stderr: %s, giID, err, stderr.String()) } ciIDs : strings.Fields(strings.TrimSpace(string(output))) return ciIDs, nil } // GetMIGProfiles 查询 GPU 支持的 MIG Profile 列表 func (m *MIGManager) GetMIGProfiles(ctx context.Context) ([]string, error) { ctx, cancel : context.WithTimeout(ctx, m.timeout) defer cancel() cmd : exec.CommandContext(ctx, nvidia-smi, mig, -i, fmt.Sprintf(%d, m.gpuIndex), -lgip, ) var stderr bytes.Buffer cmd.Stderr stderr output, err : cmd.Output() if err ! nil { return nil, fmt.Errorf(查询 MIG Profile 失败 (GPU %d): %w, stderr: %s, m.gpuIndex, err, stderr.String()) } profiles : strings.Fields(strings.TrimSpace(string(output))) return profiles, nil }Kubernetes 侧在安装 NVIDIA GPU Operator 之后GPU 节点会自动发现 MIG 切片设备。Pod 通过nvidia.com/mig-1g.10gb这种资源名请求对应的 MIG 实例。关键配置如下# mig-pod.yaml — MIG 推理服务 Pod 示例 apiVersion: v1 kind: Pod metadata: name: inference-llama2-7b spec: nodeSelector: nvidia.com/gpu.product: NVIDIA-A100-SXM4-80GB containers: - name: model-server image: vllm/vllm-openai:latest resources: limits: nvidia.com/mig-1g.10gb: 1 # 请求一个 1g.10gb 的 MIG 切片 env: - name: CUDA_VISIBLE_DEVICES value: 0 # 容器内只看到一个 GPU 设备需要注意MIG 模式下 GPU 不支持 CUDA IPC进程间通信。如果推理框架依赖 NCCL 的 P2P 通信做张量并行MIG 实例之间无法建立 P2P 连接。这是 MIG 的一个硬限制在选型时需要评估推理框架的并行策略。四、MIG 的边界与权衡不是所有场景都适合切片MIG 的硬件隔离是最大的卖点但也带来了不容忽视的限制。显存碎片化无法动态调整。一旦创建了特定的 GI Profile如3g.40gb该 GPU 上的显存布局就固定了。如果业务需求变更需要一个4g.40gb的 GI必须先销毁现有所有 GI 再重建期间该 GPU 上的服务全部中断。相比之下基于 CUDA MPS 的方案可以更灵活地动态调整进程间的显存和计算配额。Profile 组合的限制性。不是所有 Profile 的排列组合都被硬件支持。例如1g.5gb 1g.5gb 3g.40gb 2g.20gb这种组合可能因为内存通道冲突而无法创建。实际使用中必须在nvidia-smi mig -lgip的返回结果内选择合法组合。推理延迟的增长。每个 MIG 切片拥有的 SM 数量减少对于单个推理请求来说计算延迟会上升。以 Llama2-7B 为例在一张完整 A100 上 Prefill 延迟约 50ms在1g.10gb仅 14 个 SM上可能上升到 120ms。吞吐量角度看单位时间处理的请求总数可能增加但单请求延迟的退化必须满足 SLA 约束。MIG 适用场景多模型低延迟推理每个模型显存需求 GPU 容量多租户平台需要硬件级别故障隔离批量小模型推理服务显存不是瓶颈SM 利用率才是MIG 不适用场景大模型训练训练需要完整 GPU 带宽 NVLink单模型跨卡张量并行不支持 IPC显存需求 单 MIG 切片的场景需做模型量化或蒸馏五、总结MIG 是当前 GPU 共享方案中隔离性最强的选择硬件级内存分区和错误隔离使其成为多租户推理平台的首选。落地建议预先评估 Profile 组合使用nvidia-smi mig -lgip列出合法组合避免创建时发现不支持。监控 MIG 切片级别的利用率DCGM 支持按 MIG 实例采集 SM 占用率、显存带宽等指标比整卡粒度的监控更有意义。结合 HPA 做弹性伸缩当某个 MIG 切片的请求队列深度超过阈值时通过调整 GI Profile 或增加节点来实现扩容。注意 CUDA IPC 限制使用 vLLM 等框架的 Pipeline Parallel 替代 Tensor Parallel规避 MIG 的 P2P 通信限制。