27届大模型面试准备(七十一):多租户 GPU 虚拟化与推理隔离工程——MIG、MPS 与噪声邻居治理

27届大模型面试准备(七十一):多租户 GPU 虚拟化与推理隔离工程------MIG、MPS 与噪声邻居治理

引言

上篇(六十九)讲 Prefill-Decode 分离,把单卡算力按阶段拆开调度;(七十)讲网关层如何把请求路由到不同实例。本篇把视角再抬一层:当一张 A100/H100 要同时服务多个业务方(多租户)时,怎么在显存、算力、延迟三个维度做隔离与复用,既把卡利用率榨干,又不让某个租户的突发流量把别人的 P99 拖垮。这是华为云、大模型推理平台岗的高频题,也是面试里最容易区分"只会调 API"和"真做过平台"的分水岭。

前文链接:A70 推理服务负载均衡与智能请求路由、A69 Prefill-Decode 分离式推理架构、A66 推理调度与弹性扩缩容工程。

复制代码
                ┌──────────────────────────────────────────┐
                │           推理网关 / 多租户调度器           │
                │  租户标识 → 路由 → 配额 → 优先级队列 → 限流 │
                └───────────────────┬──────────────────────┘
                                    │
      ┌─────────────────────────────┼─────────────────────────────┐
      │ 租户A(高优/SLA)             │ 租户B(中优)                  │ 租户C(best-effort)
      ▼                             ▼                             ▼
 ┌───────────┐              ┌───────────┐               ┌──────────────┐
 │ MIG slice │              │ MIG slice │               │ 共享 MPS 时间片│
 │ 1g.10gb   │              │ 3g.40gb   │               │ (无硬隔离)    │
 └───────────┘              └───────────┘               └──────────────┘
      │                             │                             │
      └─────────────────────────────┴─────────────────────────────┘
                                    ▼
                   ┌────────────────────────────────────┐
                   │     NVIDIA A100 80GB 单卡           │
                   │  SM 阵列 / HBM / NVLink 物理资源    │
                   └────────────────────────────────────┘

表:四种隔离手段对比

手段 隔离粒度 算力隔离 显存隔离 切换开销 典型适用场景
MIG 硬件物理切片 强(独占 SM 子集) 强(独占 HBM 分区) 中(需重建 slice) 稳定多租户、强 SLA 合同
MPS 进程级共享引擎 中(按 CUDA context 分时) 弱(共享显存池) 同信任域、提利用率
时间片调度 调度器级 弱(时分复用整卡) best-effort 错峰复用
容器+Cgroup 主机级 依赖驱动/MPS 依赖驱动 物理机多实例混部

一、为什么推理平台必须做多租户隔离

云上推理的两个矛盾:(1) 单卡跑一个小模型太浪费,7B/13B 模型 decode 阶段显存占用可能只有 8GB,剩下 70GB 空转;(2) 把多个模型塞一张卡,某个租户来一波长上下文突发,就会把共享的 HBM 带宽和 SM 占满,别人的 TTFT 从 200ms 飙到 3s。不做隔离,利用率和公平性只能二选一。

面试常问:"你们线上一张卡跑几个模型?怎么保证互不干扰?"标准答案不是"用 Docker",而是分层:硬件切片(MIG)→ 驱动级共享(MPS)→ 调度器配额(K8s/Volcano)→ 应用级限流(网关)。

二、硬件级 MIG:把一张卡切成多张"小卡"

MIG(Multi-Instance GPU)在 A100/H100 上把 SM 阵列、L2 Cache、HBM 带宽、显存做物理分区。一个 7g.40gb 的 slice 就是一张"逻辑 GPU",有独立的显存和算力,一个 slice 的故障不影响其他 slice。

复制代码
# 创建 1 个 1g.10gb + 1 个 3g.40gb 的组合(需先置 admin 模式)
sudo nvidia-smi -i 0 -mig 1
sudo nvidia-smi mig -i 0 -cgi 1g.10gb,3g.40gb -C
# 查看 slice
nvidia-smi mig -lgi
# 输出示例:
#   GI ID  CI ID  Profile
#   9      0     1g.10gb
#   10     1     3g.40gb
# 应用侧用 CUDA_VISIBLE_DEVICES 绑定到具体 GI
CUDA_VISIBLE_DEVICES=9 python -m vllm.entrypoints.openai.api_server --model qwen2.5-7b

MIG 的代价:slice 之间不能共享 KV Cache,跨 slice 不能做张量并行;且创建/销毁 slice 需要短暂中断整卡。所以它适合"长期稳定、SLA 不同"的租户组合,不适合频繁变配。

三、驱动级 MPS:同信任域提利用率

MPS(Multi-Process Service)让多个进程共用同一个 CUDA context,kernel 在 SM 上并发调度,显存仍共享。它没有硬隔离,但能把"两张卡各跑 30% 利用率"的两个小模型合并到一张卡跑 60%,省一张卡的钱。

复制代码
# 启动 MPS 服务端(按用户/按卡)
export CUDA_VISIBLE_DEVICES=0
nvidia-cuda-mps-control -d
# 之后该卡上的所有 CUDA 进程都走 MPS 共享引擎
# 限制单进程可用 SM 比例(需 MPS 配置 + 配合 cgroups)
echo "set_default_active_thread_percentage 50" | nvidia-cuda-mps-control

注意 MPS 下的故障传染:一个进程显存越界可能拖垮同 context 的其他进程。所以 MPS 只在"同团队、同信任等级"的内部租户间用,对外售卖必须用 MIG。

四、显存配额与上下文隔离

即使不用 MIG,也要防止某个租户申请超大 KV Cache 把整卡 OOM。做法是在调度器层给每个模型实例设显存预算,并在推理引擎里做硬性上限。

复制代码
# 伪代码:按租户维度限制 KV Cache 预算
class TenantGPUScheduler:
    def __init__(self, total_hbm_gb=80):
        self.budget = {}          # tenant -> 显存配额(GB)
        self.used = {}            # tenant -> 已用(GB)

    def admit(self, tenant, need_gb):
        if self.used.get(tenant, 0) + need_gb > self.budget.get(tenant, 0):
            return False, "tenant_gpu_quota_exceeded"
        if sum(self.used.values()) + need_gb > self.total_hbm_gb * 0.92:
            return False, "node_hbm_pressure"
        self.used[tenant] = self.used.get(tenant, 0) + need_gb
        return True, "ok"

    def release(self, tenant, free_gb):
        self.used[tenant] = max(0, self.used.get(tenant, 0) - free_gb)

五、噪声邻居(Noisy Neighbor)治理

"噪声邻居"指同卡其他租户的突发把你的延迟拖垮。治理三板斧:

  1. 优先级抢占:高优租户到来时,低优租户的长 decode 被挂起或限速。

  2. 带宽隔离:MIG 天然隔离 HBM 带宽;非 MIG 场景用 MPS thread percentage + 限流近似。

  3. 延迟 SLO 监控:每个租户独立打 P99,越界自动触发扩容或迁移。

    优先级队列 + 加权公平调度(WRR)

    import heapq

    class PriorityAdmitter:
    def init(self):
    self.queues = {0: [], 1: [], 2: []} # 0高 1中 2低

    复制代码
     def schedule(self):
         # 高优先发,中优按权重,低优有空才发
         for level in (0, 1, 2):
             if self.queues[level]:
                 return self.queues[level].pop(0)
         return None

六、调度器层:K8s Device Plugin 与公平性

在 K8s 上,MIG 通过 nvidia.com/mig-1g.10gb 这类扩展资源暴露,Volcano / 自研调度器按租户 namespace 做配额(ResourceQuota)和优先级(PriorityClass)。避免"一个租户 Pod 占满节点 MIG slice 导致别人 Pending"。

面试速答

问:MIG 和 MPS 有什么区别,什么时候用哪个?

答:MIG 是硬件物理切片,算力和显存都硬隔离,故障不传染,适合对外多租户强 SLA;MPS 是驱动级共享引擎,提利用率但不隔离,故障可能传染,适合内部同信任域复用。对外卖算力用 MIG,内部提效用 MPS。

问:一张卡跑多个模型,怎么防止 OOM 互相影响?

答:三层------硬件用 MIG 物理隔离显存;驱动/调度层给每实例设显存预算和 KV Cache 上限;节点层保留 8% HBM 余量防整卡 OOM。

问:噪声邻居怎么治?

答:优先级抢占 + 带宽/算力配额 + 每租户独立 P99 SLO 监控,越界自动限速、扩容或迁移。

高频追问清单

  1. MIG slice 之间能共享 KV Cache 吗?跨 slice 张量并行有什么限制?
  2. MPS 故障传染的根因是什么,生产上怎么规避?
  3. best-effort 租户和 SLA 租户混部,调度器怎么做加权公平?
  4. 显存预算按 tenant 还是按 model instance 计量更合理?长上下文突发怎么处理?
  5. K8s 上 MIG 资源如何暴露和做 namespace 配额?
  6. 节点 HBM 压力时,应该拒绝新请求还是抢占低优请求?怎么选?
  7. 租户级限流(QPS/并发)和 GPU 配额怎么联动?
  8. 单卡多模型场景下,NVLink 带宽争用怎么观测和隔离?
相关推荐
虎虎(_ _)。゜zzZ10 小时前
Qdrant向量数据库工程实战
数据库·人工智能·大模型·向量数据库·rag·qdrant
deepseek2311 小时前
GPT-6 Astra 发布拆解:Computer Use 产品化时刻、CoT 监控失守与 AGI 契约的终结
大模型·openai·ai agent
程序猿编码13 小时前
基于GGML的C++17轻量化语音推理引擎:说话人识别与语音分析技术全解析
开发语言·c++·pytorch·深度学习·神经网络·大模型
夏文强14 小时前
DeepSeek Harness 底层探秘:Cordis 元框架与「一切皆插件」的实现
人工智能·开源·大模型·agent·deepseek
夏文强15 小时前
DeepSeek Harness 可追溯性实战:会话日志的 resume、fork 与 replay
人工智能·开源·大模型·agent·deepseek
songsong.18 小时前
一个简单通用的ChatLLM类设计与使用
大模型·openai·大语言模型
像风一样自由20201 天前
20.Milvus常见问题检索不到维度错误和数据一致性
人工智能·大模型·milvus
这张生成的图像能检测吗1 天前
(论文速读)Scaling Rectified Flow Transformers:Rectified Flow + MM-DiT 的高分辨率文生图路线
大模型·文生图·多模态·扩散模型·图像生成
是Yu欸2 天前
实测openPangu-2.0-Pro:昇腾原生, 505B大模型的开源答卷
人工智能·开源·大模型·昇腾·pangu