算力到位了,服务还是卡,这是过去一年我在好几个推理项目里反复撞见的怪圈。GPU 明明没有跑满,显存也还有富余,可线上服务的延迟就是不稳定,吞吐上不去。大多数人习惯把 GPU 调度当成训练集群的专属课题,但推理场景下的资源调度完全是另一套逻辑——它要同时应付延迟敏感、显存碎片、并发抖动、多模型共存这些破事,一个处理不好,几十万买的卡跟摆设差不多。
这篇文章我就把几个推理项目里沉淀下来的 GPU 资源调度经验全部摊开讲,从显存管理、利用率排查、多模型共享到具体落地参数,属于抄了就能用的那种。无论你是刚把模型部署上线的新手,还是正在为多模型共卡发愁的运维老手,这篇文章应该都有你能带走的东西。
1. 推理场景和训练场景的 GPU 调度逻辑,完全是两码事
很多人上来就照着训练集群那套思路做推理资源调度,这是第一个大坑。训练场景下,我们追求的是算力打满、吞吐最大化,任务跑个几小时甚至几天,延迟波动几十毫秒根本无所谓。推理场景刚好相反,它追求的是稳定延迟和可控吞吐,单个请求可能只有几毫秒到几十毫秒的 GPU 计算时间,但对响应时间极度敏感。
1.1 训练调度看利用率,推理调度看的是延迟分布
训练任务里的 GPU 利用率,基准越低越值得优化,因为算力就是钱。但推理服务不一样,一个推理服务 GPU 利用率 30% 可能已经是健康状态,因为你要给流量洪峰留出缓冲,要给动态批处理腾出拼批窗口。如果推理服务长期跑在 90% 利用率,那延迟分位数大概率已经失控了。
我习惯用 TP99 和 TP999 这两个延迟指标来判断推理服务的健康度,而不是盯着利用率看。真正需要关注的是:在某个并发压力下,延迟分布是否稳定,有没有长尾。长尾请求通常不是 GPU 算力不够,而是资源调度出了问题——显存分配卡顿、上下文切换开销、批处理窗口太小、共卡任务互相干扰,这些都可能是元凶。
1.2 推理调度的核心矛盾:显存占用小,但访存带宽和延迟要求极高
模型推理和训练还有一个根本性差异:显存占用量级不同,但带宽需求一点不低。训练大模型动辄占满 80GB 显存,推理一个 7B 模型量化后可能只要 6GB 显存。显存看起来富余了,但推理过程中的访存模式是高度密集的,尤其自回归解码阶段,权重矩阵一遍遍从 HBM 里读,内存带宽直接决定 decode 的速度。这也是为什么 7B 模型在 A100 上推理,和 4090 上推理速度差距没那么悬殊——算力是一方面,带宽才是瓶颈。
这个底层差异导致推理资源调度不能只看显存余量,还要考虑带宽争抢。同一个 GPU 上塞多个推理任务,如果都是带宽密集型,互相干扰会比显存不足更早出现,表现为延迟分布劣化、逐 token 生成速度明显下降。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 显存分配与复用:推理调度最容易忽略的隐性成本
显存管理在推理场景里被低估得离谱。很多人以为显存够放模型就够了,实际上运行时显存开销包括模型权重、KV Cache、CUDA Context、CUDA 算子临时缓冲区、通信缓冲等一堆杂项。模型只占其中一部分,KV Cache 增长是动态的,CUDA Context 动不动就占几百 MB 到 1GB,这些都必须在调度时提前算进去。
2.1 CUDA Context 的吃显存机制,以及多进程隔离的代价
每个进程初始化 CUDA 环境,驱动都要给它分配一块统一内存空间来放 context,包括模块加载、kernel 编译缓存、设备参数等。这块空间在进程整个生命周期内不会释放。不同框架、不同 CUDA 版本的 context 开销不一样,PyTorch 相对节省,TensorRT 则比较克制,但一个上下文吃 300MB 到 800MB 只是起步价,多卡环境还要再乘卡数。
所以调度策略里,我坚决反对为每个请求拉起一个进程这种方式。进程级隔离安全是安全,但 context 反复初始化对服务延迟是灾难性的,而且 GPU 显存碎片化会因为频繁申请释放而恶
