LLM 推理异构硬件调度工程 2026:从拓扑路由到在线凸优化的统一框架
把异构硬件调度建模成局部实时决策加全局慢速反馈的在线凸优化问题,用拓扑感知路由器、KV 跨设备分配、动态批处理 split、全局纠偏四件套把调度延迟压进 50ms 预算,让 2026 年的推理平台在 H100、L40S 与国产 NPU 混部场景下拿到稳定 SLA。
约 20 分钟阅读5,955 字1 次阅读博主

把异构硬件调度建模成局部实时决策加全局慢速反馈的在线凸优化问题,用拓扑感知路由器、KV 跨设备分配、动态批处理 split、全局纠偏四件套把调度延迟压进 50ms 预算,让 2026 年的推理平台在 H100、L40S 与国产 NPU 混部场景下拿到稳定 SLA。

2026 年的 LLM 推理服务平台已经很少有"全栈同构"的部署形态。即使是最保守的私有化部署,集群里也至少混着两种 GPU 型号(H100 + L40S,或者 A100 + H200),更不用说正在被纳入生产路径的国产卡(昇腾 910B、寒武纪 MLU、燧原 S60)。这种异构性不是某家公司的临时妥协,而是 LLM 推理在 2024-2026 年间的必然演化:训练侧的算力扩张到单卡 80GB 显存、300GB/s NVLink 带宽后,推理侧为了追求每美元 token 数最大化,必须把不同代际、不同厂商、不同精度的硬件混部在同一调度平面里,让"昂贵的高吞吐卡跑长 prompt 的 prefill + 高吞吐 decode"、让"便宜的旧卡跑短 prompt 的纯 decode 或者低优先级流量"成为默认形态。
但异构硬件调度不是简单地把请求 round-robin 到不同卡。一个完整可用的异构调度系统,需要解决至少五个相互耦合的子问题:(1)请求路由器如何在毫秒级延迟预算下判断"这条 prompt 该去哪张卡";(2)显存预算如何在跨设备 KV cache 之间分配,避免一边 OOM 一边空载;(3)动态批处理如何在不同卡上独立决策,避免等最慢的一张;(4)故障域如何隔离,避免单卡抖动污染整条推理链路;(5)调度策略本身如何在生产运行时自学习,因为用户的 prompt 分布、模型版本、硬件良率都在持续漂移。
这篇文章把这五个子问题统一到一个"异构调度作为在线凸优化"的工程框架里讨论。我们不追求数学上的严格最优,而是关注每条决策链在 50ms 调度预算下必须满足的工程边界——边界才是真正的"正确性",理论最优解如果不能在两跳 RTT 内算出,就是空解。
我们把异构推理调度问题建模成一个四元组 (H, M, Q, π),其中:
H 是硬件集合,每张卡 h ∈ H 由六个属性描述:(a) 显存容量 V_h,单位 GB;(b) 峰值 FP16/BF16 TFLOPS T_h;(c) NVLink/PCIe 互联带宽 B_h,单位 GB/s;(d) 故障率 λ_h,单位 次/小时(包含瞬时抖动与永久失效);(e) 当前显存占用 v_h,单位 GB,0 ≤ v_h ≤ V_h;(f) 当前活跃请求队列深度 q_h。这是调度器实时能看见的"硬件画像",每 100ms 刷新一次。
M 是模型版本集合,每个模型 m ∈ M 由四个属性描述:(a) 参数量 P_m(决定 KV cache 单 token 占用的字节数,与是否 GQA 强相关);(b) 上下文窗口 C_m;(c) 当前实例的部署位置集合 D_m ⊆ H,即"这个模型正在哪些卡上跑";(d) 当前版本的 rollout 时间戳,用于在灰度发布期间分流。
Q 是请求流,每条请求 r ∈ Q 由五元组 (prompt_length, generation_length, model_id, priority, deadline) 描述。priority 与 deadline 都是业务侧契约,不在调度器内部重新计算;调度器只能"尊重"它们,不能"优化"它们。
π 是调度策略,它是个函数 π: (H, M, Q) → A,其中 A 是动作空间,包含:(a) 选择目标卡 h ∈ H;(b) 选择排队策略(先进先出、优先级队列、加权公平);(c) 选择是否触发跨卡迁移;(d) 选择是否降级(换到更小的模型或者量化版本)。调度器的目标函数是个加权组合,权重由业务侧 SLA 契约给出。
我们强调这个四元组是为了把"调度问题"和"调度系统"分开。问题层面,这四个集合的笛卡尔积定义了状态空间;系统层面,我们要在每个状态上用远小于状态空间规模的时间预算算出动作。这是任何生产调度系统都逃不开的两层抽象,工程上的复杂度基本都来自后者——状态空间可以无限大,但每个请求的调度延迟不能超过 50ms。
请求路由是调度链路的第一跳,也是延迟预算最紧的一跳。从接到请求到决定目标卡,路由器的可用时间通常是 1-3ms,因为剩下的几十毫秒要留给排队等待、跨卡传输、首 token TTFT。一条典型的拓扑感知路由器由四个组件构成:
第一是预过滤层,按 (D_m, priority) 快速筛选出"这张卡不能跑这个模型"或者"这条请求不能路由到这个优先级的队列"。这一步基本是 O(1) 查表,绝大多数请求在这里就被分到 2-3 个候选卡集合里。
第二是拓扑打分函数,对每个候选卡计算一个拓扑亲和度分数。该分数的核心是"数据传输距离"——prompt token 的 KV cache 计算量大致与 prompt 长度乘以模型层数成正比,而 KV cache 的存储量则与 prompt 长度加 generation 长度乘以 KV head 数成正比。如果模型已经部署在卡 h 上但 prompt 非常长,那么 prefill 阶段的计算量会显著高于 decode 阶段,这种请求就更适合放到 NVLink 互联带宽高、TFLOPS 强的卡上(如 H100/H200),而不是互联带宽弱的 L40S 上。
第三是显存可用性快速估算,这一步不追求精确,只追求上界。我们用一个保守公式估算请求 r 在卡 h 上的显存峰值占用:v_peak(r, h) = model_weights_static + kv_cache_per_token × (prompt + generation) + activation_buffer。如果 v_h + v_peak(r, h) > 0.92 × V_h,则该卡被剔除——留 8% 余量给碎片和突发增长。
第四是抖动感知,根据卡 h 在过去 5 分钟的 TTFT p99 历史,做一个 Z-score 归一化,把持续抖动的卡降级到"低优先级流量"或"重试回退队列"。这一层是异构调度独有的,因为同构集群里"卡坏了直接踢出"就行,异构集群里"踢出一张卡可能让整层调度退化"。
四个组件的输出加权求和得到最终分数。权重不是固定的——它来自线上 A/B 实验的反馈闭环,每小时根据真实延迟分布更新一次。这就把"静态调度规则"变成了"自学习调度策略",代价是路由器的实现复杂度上升一个数量级。
KV cache 是 LLM 推理里最贵的运行时资源。在 70B 模型、8K 上下文、BF16 精度下,每个并发请求的 KV cache 大约 4-6GB;在 405B 模型、128K 上下文下,这个数字能飙升到 30-50GB。显存预算管理在异构集群里特别棘手,因为不同卡的显存容量差异巨大(H100 80GB vs L40S 48GB vs 国产卡 64GB)。
我们采用三层显存预算架构。第一层是静态预留,模型权重和激活 buffer 是不可压缩的,按卡容量扣掉这一部分,剩下的就是 KV cache 可用额度 V_kv(h)。第二层是公平共享,把 V_kv(h) 按"当前活跃请求数"或者"按 SLA 等级"分配给每个请求。公平共享有两种实现:硬隔离(每条请求独占一份 KV 预算,超出立刻换卡或者排队)和软隔离(共享池,OOM 时 LRU 淘汰)。生产里几乎都是软隔离——硬隔离的显存利用率太低。
第三层是跨设备 spillover,当卡 h 的 KV 池饱和但其他卡还有空间时,新请求可以"溢出"到其他卡。这个机制看起来简单,但实现里有三个隐藏陷阱:第一是 spillover 的请求不能享受"同卡 prefix 复用",因为 KV cache 不在本卡,等于每次都全量重算 prefix;第二是 spillover 的请求 TTFT 会被跨卡数据传输拖累,尤其当互联带宽只有 PCIe Gen5 x16(约 64GB/s)时;第三是 spillover 必须配合超时机制,长 prompt 的请求 spillover 出去后 decode 阶段再迁回原卡会引入额外的 KV 复制开销。
我们的工程经验是:spillover 阈值应该按卡剩余显存比例动态调整,而不是固定一个数字。比如当 V_kv(h) > 30% 时允许 50% 的新请求 spillover 试探,V_kv(h) < 10% 时只允许 priority=high 的请求 spillover。这样既不浪费显存,又不会因为 spillover 导致卡 A 满卡 B 闲置的极端倾斜。
动态批处理(continuous batching)是 vLLM、SGLang、TensorRT-LLM 在 2024-2025 年间引入的核心优化。它的核心思想是:传统静态批处理必须等一批请求全部 decode 完才能开始下一批,而动态批处理允许新请求在旧请求 decode 完成的那个 slot 上立即插入——这就把 GPU 利用率从 30-40% 提升到 70-85%。但动态批处理在异构集群里遇到了新的复杂性:每张卡的批处理窗口应该独立决策还是协同决策?
我们的答案是独立决策为主、协同纠偏为辅。每张卡 h 上的 batching 调度器独立运行 continuous batching 循环,决策点有三个:(1)当 batch 中某条请求 decode 完成,是否立即拉取新请求填充该 slot;(2)当 batch 中所有请求长度差异超过阈值,是否触发 split——把短请求和长请求分开,避免长请求拖累短请求的 TTFT;(3)当 batch 累积到某个 size 阈值,是否触发 preemption——把 batch 中最低优先级的请求抢占,让更高优先级请求进来。
这三个决策都是每张卡独立做的,但它们共同受全局调度器的"纠偏信号"影响。纠偏信号是个标量,包含三项:(a)卡间负载均衡度(标准差/均值);(b)总排队请求数;(c)SLA 违约率。当纠偏信号越过阈值时,全局调度器会向特定卡注入"加快"或"减速"指令——比如让某张卡降低 batching 阈值以提高 TTFT,或者让另一张卡提高 batching 阈值以提高吞吐。
这套"独立决策 + 全局纠偏"的架构在 2026 年的实践中表现稳健。它的核心优势是避免单点故障:全局调度器挂掉不影响单卡独立 batching,单卡 batching 卡顿也不会让全局调度器背锅。生产里我们要求全局纠偏信号每 500ms 更新一次,单卡 batching 循环每 100ms 跑一次,两层时间尺度相差 5 倍,正好覆盖"局部抖动 vs 全局漂移"两种时间尺度的故障。
把前三个主体放在一起看,它们都遵循同一个模式:局部实时决策 + 全局慢速反馈。这条模式本质上就是在线凸优化(Online Convex Optimization, OCO)的工程实例。在 OCO 框架里,每一步决策是个"在线猜测",每一步反馈是个"凸函数的次梯度",长期累积 regret 有理论下界(如 Hedge、FTL、ONS 等算法的 regret 界),但实际系统里我们不追求理论最优,只追求"工程稳定性"。
工程稳定性有三个硬约束:第一是决策延迟上限,每次调度决策必须在 50ms 内完成,超过这个上限的优化都是空优化——因为请求早被超时的用户放弃了。第二是反馈环路鲁棒性,业务侧反馈信号(延迟、错误率、SLA 违约)必须是单调的、连续的,不能因为某次 A/B 实验异常就触发策略跳变。第三是冷启动可降级,新策略上线时必须有一条 fallback 路径——比如"前 24 小时用 round-robin 收集基线数据,第 25 小时开始用自学习策略,72 小时后如果自学习策略的 SLA 违约率超过 round-robin 就回滚"。
从 OCO 视角看异构调度的最大好处是避免重复踩坑。所有调度策略的"局部抖动 vs 全局漂移"问题,本质上都是"短视决策 vs 长视最优"的权衡;所有"某卡特别忙某卡特别闲"的问题,本质上都是"局部 loss 函数的梯度方向不一致";所有"上线后效果变差"的问题,本质上都是"反馈环路延迟太长,导致策略追不上漂移"。把这三个共性提取出来后,每个新策略上线前都能用同一个 checklist 检验:决策延迟、反馈鲁棒性、冷启动可降级——三条都过了才能进灰度。
这套统一视角还帮我们识别出了一个隐含的"调度器天花板":无论策略多聪明,调度器的总决策次数受限于单卡最大 RPS 与全局请求数的乘积。当这个乘积超过某个阈值(经验值约 10^7 decisions/秒),任何在线算法都会撞上物理瓶颈——不是因为算力不够,而是因为反馈环路自身的延迟已经超过请求本身的延迟。突破这个天花板只能靠两个方向:(a)让反馈环路变快(比如从 500ms 缩短到 50ms);(b)让单卡决策承载更多请求(比如从单请求粒度调度变成"超请求"粒度调度)。两个方向都在 2026 年的生产系统里有初步落地,但都还没有跨过盈亏平衡点。
基于前六节的统一视角,我们提炼出五条可直接落地的工程推论:
推论 1:路由器的拓扑打分权重必须按硬件代际差异化。 H100/H200 的 NVLink 互联带宽是 L40S 的 4-6 倍,权重不能简单线性套用。我们推荐把权重拆成"计算密度"和"互联带宽"两项独立调优,每周根据 TTFT p99 回归一次。
推论 2:KV cache spillover 阈值应该用相对剩余比例而非绝对 GB 数。 异构卡容量差异巨大(48GB vs 80GB),绝对阈值会让 48GB 卡经常空载 80GB 卡经常满载。相对比例(10%/30%/50% 三档)配合 priority 标签是个更稳健的工程选择。
推论 3:动态批处理的 split 决策必须按 prompt 长度分桶而非按 decode 长度分桶。 prompt 长度决定 prefill 计算量,decode 长度决定 KV cache 增长斜率,两者对 batching 窗口的影响是独立的。我们推荐三桶制:短 prompt (< 2K)、中 prompt (2K-32K)、长 prompt (> 32K),每桶独立的 batching 阈值和 preemption 策略。
推论 4:全局纠偏信号的更新频率必须小于单卡决策频率的 5 倍。 经验值是单卡 100ms / 全局 500ms;如果全局更新太快,会跟单卡决策循环耦合震荡;太慢则纠偏效果不显著。
推论 5:所有调度策略上线必须配冷启动基线。 第一天跑 round-robin,第二天开始灰度 10% 自学习策略,第三天 50%,第四天 100%,第五天回滚阈值设为"自学习 SLA 违约率 > round-robin × 1.05"。这条推论看似保守,但在生产里救过我们无数次——自学习策略在训练数据上有 3-5% 的优势,在线上分布漂移时反而可能跑输 round-robin,因为 round-robin 的无偏性恰好对未知分布更鲁棒。
我们的统一视角建立在三个工程假设上,每个假设都有其失效边界。
第一个假设是"调度决策延迟可以压到 50ms 以内"。这个假设在 NVLink 互联的同机房集群里成立,但在跨机房调度(如主集群 + 边缘节点)里就不成立——跨机房 RTT 本身就超过 10ms,再加上策略计算和跨机房数据传输,决策延迟经常突破 100ms。跨机房调度在 2026 年仍是个开放问题。
第二个假设是"反馈信号是单调连续的"。这个假设在大多数业务里成立,但在冷启动场景(如新模型上线首日)和突发热点(如某条 prompt 被全网刷屏)里就失效。我们目前用"异常检测 + 临时切回 round-robin"应对,但更系统的方案还没出现。
第三个假设是"异构卡的 TFLOPS 与显存可以独立建模"。这个假设对 GPU 卡大致成立,但对国产 NPU 卡就不成立——昇腾 910B 的算子和显存带宽之间存在强耦合(某些算子的瓶颈是带宽、另一些是算力),单卡建模的误差会被异构混部放大。国产卡在推理侧的真正成熟,可能还要等 2-3 年的编译器优化才能赶上 GPU 卡的成熟度。
另外还有几个未解之题值得未来关注:(a)多模态模型的异构调度(vision encoder、audio decoder、LLM 三段的资源占用曲线完全不同);(b)联邦学习场景下的边缘异构推理;(c)基于强化学习的端到端调度策略 vs 当前基于规则的策略;(d)调度器自身的 A/B 测试方法论(调度器本身就是基础设施的一部分,传统 A/B 框架对它不直接适用)。这些方向目前都没有公认的最佳实践,工程上的进展更多来自各家公司的内部探索。
最后给负责生产推理平台的 SRE 团队一份可执行的工程清单:
按这份清单把监控、告警、审计、回滚四条线都建起来,异构推理调度的工程稳定性就能从"靠运气"变成"靠机制"。剩下的优化空间才是模型层、策略层、算法层的事,那一层才是研究者们真正发力的战场。
一句话摘要:把异构硬件调度建模成"局部实时决策 + 全局慢速反馈"的在线凸优化问题,用拓扑感知路由器、显存预算分配、动态批处理 split、全局纠偏四件套把调度延迟压进 50ms 预算,让 2026 年的推理平台能在 H100/L40S/国产 NPU 混部场景下拿到稳定 SLA。
Conversation
0 条