资讯动态

大模型推理部署实战:从量化到上线,两张24G卡撑起高并发服务

发布时间:2026/10/20 4:33:18 来源:尧图企业网站定制
去年年底公司要做物流调度场景的智能化升级任务落到了我头上把大模型推理服务稳定、低成本地部署上线。团队只有三个人预算卡得很紧GPU 一共两张 24G 的卡。当时我们内部折腾了一套叫“海豚”的推理部署平台从模型选型、量化、推理框架参数调优到压测上线走了不少弯路。今天把整个过程中最实际的东西整理出来希望对准备碰大模型推理部署这个方向的小白程序员有点帮助。这篇内容不是我惯常写的算法论文式总结也不是某个框架的官方文档翻译而是把一个“物流场景下大模型推理服务”从零部署到上线的完整流程摊开讲。你能看到每个关键决策背后的原因比如为什么用 13B 模型而不是 70B为什么量化优先选 INT8为什么并发参数不能随便填。也会看到实际踩坑时的排查思路和最终解决办法。适合对模型训练略懂、但对部署和性能优化比较陌生的同学也适合正在为“怎么用便宜的卡跑起来”发愁的小团队。1. 先搞清楚部署大模型推理到底难在哪1.1 显存、延迟、成本三个老大难“部署一个大模型”听起来就是把模型文件 load 进来把服务起起来但真正做的时候小白往往会被三个问题迎面打懵。第一个是显存。一个 7B 参数的模型用 FP16 精度存储光权重就占 14GB 左右。这只是“把模型放进显存”的成本一旦开始跑推理KV Cache 也要占显存中间激活值也要占显存输入输出的临时张量都要占显存。一张 24G 的卡跑 7B 模型看起来绰绰有余实际并发一上来很快就会被 OOM 砸脸。70B 模型更不用说FP16 权重就要 140GB单卡根本放不下。第二个是延迟与吞吐的博弈。Query 的响应延迟要低就得减少批处理规模但 GPU 是并行计算设备一次喂进去的请求太少算力就空闲了吞吐上不去单次请求的成本就高。很多团队第一次压测时会发现并发从 1 加到 8吞吐确实涨了但 P99 延迟翻了一倍客户那边直接投诉。延迟和吞吐本质上是两个方向的指标想同时拿好就得靠推理框架层面的调度策略。第三个是成本。GPU 的采购和租用费是实打实的开销一张主流一点的显卡按包月租也得几千块。小团队的预算根本撑不起随意铺卡。于是“跑起来”很容易“跑得好”很难“跑得便宜”更是难上加难。我们当时评估过一个方案直接上 70B 模型两张卡做张量并行模型是能跑但租卡的费用直接让项目失去性价比。1.2 物流调度场景给的需求很不一般你可能觉得“大模型部署不就是 Chatbot 那套吗”但物流调度场景和常见的对话场景差别很大这直接影响技术选型。物流调度服务的请求集中在早晚高峰。白领们上班摸鱼聊天是随机的物流系统的下单、路径规划请求却会在早晨 8 点到 10 点、下午 4 点到 6 点集中爆发。这意味着服务必须扛住流量尖峰否则晚高峰路径规划超时司机和客户体验都会崩。同时预算非常敏感因为物流本身是微利行业单次调用如果能省下一分钱成本乘以每天几百万次调用就是很可观的数字。另一个特点是请求长度差异极大。有的请求是“把这两个订单合并到一个车次”一句话就完了有的请求要附带十几段历史轨迹描述上下文很长。长请求和短请求混在一起如果批处理策略做得不好短请求会被长请求“卡住”延迟直接失控。这些约束条件在当时直接影响了我对推理框架和部署方式的判断。1.3 整体思路软硬结合四板斧面对显存、延迟、成本三个老大难我们的整体思路可以概括为“软硬结合四板斧”。第一板斧是模型压缩用 INT8/INT4 量化把模型“瘦身”把显存占用降下来让同样一张卡能腾出更多空间给并发。第二板斧是推理引擎调度靠连续批处理和分页式显存管理把 GPU 的利用率顶上去。第三板斧是硬件选型不盲目追高端卡而是根据模型大小和流量峰值选性价比最高的方案。第四板斧是请求路由简单请求走快路径小模型或规则引擎复杂请求才走大模型让大模型只干“难活”。这四板斧不是平行关系而是有先后顺序的先压模型再调引擎再看硬件最后做应用层调度。因为我们很快发现如果模型没压下来后面所有优化都要在“显存不足”的前提下做施展不开。2. 降本增效的四个核心优化手段2.1 量化把 FP16 瘦身成 INT8/INT4显存和速度一起省量化是大模型推理部署里性价比最高的一步。原理一句话就能说明白模型权重原本用 16 位浮点数存储每个参数占 2 字节INT8 量化后每个参数只占 1 字节INT4 则只占 0.5 字节。7B 模型从 FP16 转成 INT8权重显存从 14GB 降到 7GB如果狠一点用 INT4直接降到 3.5GB。实际部署时我建议优先考虑 INT8 而不是直接上 INT4。WHY因为 INT4 虽然显存省得更多但对校准数据集很敏感稍有不慎模型输出质量就会明显下滑。我们在 7B 模型上做过对比INT8 量化后在内部评测集上的准确率下降不到 0.5%INT4 量化后一开始掉了 3% 以上后来换了几轮校准数据才勉强回到 1.5% 以内。如果你的业务对输出质量要求苛刻INT8 是稳妥的起步选择。注意量化不是“一键无损压缩”。很多小白以为量化等于“白嫖显存”实际上量化后必须用测试集重新评测效果。我们内部定了一条规矩量化后的模型离线评测指标低于原模型一定阈值就不能上线哪怕显存省得再多也一票否决。量化时还需要关注“量化粒度”和“校准数据集”。别拿网上随便找的文本当校准集最好从真实业务请求里采样。以物流调度场景为例我们直接抽了线上一个月的脱敏订单描述和路径规划 prompt 来校准效果明显比通用语料好。2.2 连续批处理把 GPU 的空转时间榨干大模型推理有个特点生成 token 是逐字逐个进行的。一个请求在生成第 12 个 token 的时候另一个请求可能还卡在第 3 个 token 上。传统的静态批处理是一次性把所有请求锁进来等最慢的请求生成完整批才一起释放。这会导致严重问题快请求等慢请求GPU 算力在做无谓等待。连续批处理continuous batching的思路是动态的每个请求的生成过程是独立的只要某个请求的某个 token 生成步骤完成了就把它“踢出”当前批次同时立刻把新请求加进来。这样 GPU 每一刻都在处理“此时此刻最需要计算”的 token不浪费一个时钟周期。我们在推理框架配置里把最大批次从 32 调到 64 后吞吐提升了近一倍而 P99 延迟只增加了不到 20%这个性价比非常可观。你可以把连续批处理类比成餐厅翻台传统批处理是“所有人必须一起吃完了才能换下一桌”连续批处理是“谁吃完谁走新客随到随入”翻台率自然高。配置时注意两个关键参数最大批处理 token 数和最大同时请求数。这两个值如果设太大GPU 的确在满负荷跑但单个请求的排队时间会变长首 token 延迟就爆了。设太小吞吐又上不去。我一般先用默认值压测然后逐步调大批次同时观察 P99 延迟找到一个“延迟还没明显恶化但吞吐明显上升”的拐点。2.3 KV Cache 与分页注意力显存不再浪费大模型在生成第 N 个 token 时需要重新计算前 N-1 个 token 的注意力结果。为了省掉这些重复计算推理框架会把之前算好的 Key 和 Value 缓存下来这就是 KV Cache。问题是KV Cache 的大小是动态变化的短请求占得少长请求占得多。如果一个批次里混进来一个特别长的请求KV Cache 可能会吃下大量显存挤占其他请求的空间。我们当时最头疼的就是这个。刚开始用朴素的内存分配方式预留给 KV Cache 的显存经常碎片化有一个请求结束释放了 300MB但另一个请求需要 500MB剩下的空洞凑不出连续空间于是只能重新申请旧显存又没被及时回收恶性循环。后来换成了带分页注意力机制的推理框架这个问题才算根治。分页注意力的思路很像操作系统的虚拟内存把 KV Cache 切成固定大小的“页”物理上不需要连续逻辑上通过页表串联起来。请求结束后的所有碎片页都能立即回收复用显存利用率可以从 50% 拉到 90% 以上。给我的直观感受是同样的显存下能同时处理的请求数量大概提升了七八成。2.4 蒸馏与模型路由不是所有请求都要上大模型模型压缩只能解决单个模型本身的成本而请求路由是从另一个维度省钱让不同难度的请求走不同规模的模型。物流调度里的许多请求是简单任务比如“判断这个订单地址是否在配送范围内”根本不需要 13B 模型去“思考”。我们的做法是训练了一个很小的分类模型做预判绝大多数简单的请求直接由轻量模型或规则引擎处理只有置信度低的难例才会转发到大模型。思路参考了模型蒸馏大模型先离线批量生成了一批带标注的答案我们用这些答案微调小模型让小模型的输出尽量贴近大模型。这样即时是小模型在简单任务上的准确率也能达到 95% 以上。实测下来整个系统的 GPU 成本下降了约一半而整体准确率几乎没变。实操心得模型路由千万不要一开始就搞得很复杂。最简单的方案就是“规则 关键词 长度判断”先把明显简单的请求过滤掉。跑两周看数据再决定要不要上分类模型。我们第一版路由用了不到 100 行规则就过滤掉了 30% 的流量。3. 全流程实操从镜像到压测上线的部署记录3.1 第一步选模型、准备镜像选模型是整个部署流程里最重要的第一步很多小白上来就问“我要不要上 70B”我的建议是先想清楚业务是否需要那么强的能力。我们的业务是订单解析、地址匹配、路径规划建议13B 级别的模型已经能满足需求没必要上 70B 给自己找罪受。确定模型后先把推理框架的基础镜像拉下来。这个环节很多人会踩坑版本不匹配、依赖冲突、CUDA 版本对不上。我们内部的做法是做了一个固定的基础镜像把 CUDA、编译依赖、推理框架都锁版本之后所有模型服务都用这个镜像派生的镜像对外提供服务。版本锁定省掉了“本地能跑容器里跑不了”的经典问题。3.2 第二步模型量化与格式转换在容器里执行量化脚本。以 INT8 为例伪代码如下# 假设模型从 HuggingFace 格式下载到本地 /models/llama-13b python quantize.py \ --model_path /models/llama-13b \ --output_path /models/llama-13b-int8 \ --calib_dataset /data/calib.jsonl \ --quant_method int8 \ --batch_size 8校准数据集就是之前说的真实业务采样。量化完成后一定要跑一遍自带的评估脚本对比量化前后指标。我们当时在地址解析任务上发现量化模型的某些特定地址格式识别变差了后来排查是校准集中这一类型覆盖太少补了样本重新量化才解决。还需要把模型转换成推理框架要求的格式。有些框架要求打成单个文件有些要求把 tokenizer 配置放在特定目录。这块没有统一的捷径就是按框架文档来。但有一条共通经验转换完成后务必用一条“短请求 一条长请求 一条空请求”分别跑一遍确认服务能正常启动和推理再继续下一步。3.3 第三步推理服务启动参数配置这是最核心的一步参数配置会影响服务的吞吐、延迟和稳定性。我整理了一份我们实际用过的配置以为 13B INT8 模型、单卡 24G 为例参数值说明max_model_len4096最长输入 输出 token 数太长会挤占 KV Cachegpu_memory_utilization0.85允许使用显存上限留出余量给临时张量max_num_seqs64同时处理的最大请求数max_num_batched_tokens8192单批最多塞入的 token 总量quantizationint8必须与量化后的模型一致tensor_parallel_size1单卡部署就填 1多卡再加大为什么要这么设置比如 gpu_memory_utilization 填 0.85是因为当前预留给总显存 85% 给推理框架统一管理剩下 15% 留给系统通信、临时算子等。如果你填 0.95虽然 KV Cache 空间更充足但遇到峰值显存抖动时很容易 OOM得不偿失。max_num_seqs 和 max_num_batched_tokens 两个参数其实是一对“双保险”。光限制请求数可能被少数超长请求占满 token 预算光限制 token 数短请求又可能把批次位置占满。两个配合起来才能让长短请求混合时依然稳定运行。3.4 第四步接口对接推理框架一般会暴露一个兼容 OpenAI 格式的 HTTP 接口。这就意味着我们的业务线不需要写专用 SDK直接用 HTTP 请求就能调用。curl -X POST http://127.0.0.1:8000/v1/chat/completions \ -H Content-Type: application/json \ -d { model: llama-13b-int8, messages: [ {role: user, content: 把这两个订单合并到一个车次地点都在城东} ], max_tokens: 512, temperature: 0.3 }返回结果里会包含生成的文本、token 数等字段。这里有一个需要注意的细节如果业务用的是流式响应一定要在代码层面处理“首包到达时间”这个指标。我们的物流调度服务一开始做成了同步等待完整响应后来发现用户侧感知延迟特别高改成流式后体验明显改善。3.5 第五步压测与容量规划服务还没正式上线前压测一定要做否则你不知道自己的服务在什么并发下会崩。压测工具用常见的并发测试工具就能完成。我建议压三个场景单请求延迟、固定并发下的吞吐、峰值并发下的稳定性。第一轮压测我们连 64 并发都扛不住P99 直接超时。后来发现是 max_num_seqs 设置太大64 个请求进来后单个请求在队列里排队太久。把 max_num_seqs 降到 32同时把 max_num_batched_tokens 从 8192 降到 4096P99 立刻恢复正常。压测的价值就在这里不是追求单值最大而是找到“延迟和吞吐都能接受”的甜点位。容量规划还要算一笔账假设单实例最大稳定并发是 20晚高峰流量需要 80 并发同时跑那就得至少扩到 4 个实例。这比“不管三七二十一先扩 10 台”要省钱得多。3.6 上线监控与告警上线只是开始监控才是保命符。我们当时在监控面板上盯四个核心指标第一个是显存利用率。如果长期超过 90%服务随时可能 OOM第二个是排队长度。一旦排队请求数持续增加说明后端处理能力跟不上需要扩容第三个是 GPU 利用率。如果 GPU 利用率很低但延迟很高说明瓶颈在队列调度或 CPU 预处理上第四个是 P99 延迟这是用户体验的直接反映超过阈值就要立刻告警。注意不要只看平均延迟。大模型推理服务的延迟分布长尾非常严重平均 200ms但 P99 可能是 2s。优化目标永远是 P99而不是平均值。4. 实战中的常见问题与排查技巧4.1 CUDA OOM显存爆了怎么办这是新手最常见的报错。我们的经验是先分清是“权重都放不下”还是“跑起来之后才爆”。如果是前者说明模型大小超过显存要么换更小的模型要么做更强的量化。如果是后者通常原因是 KV Cache 预留空间不够或短时并发过高。先降低 gpu_memory_utilization、把 max_num_seqs 调小试一轮。如果还爆就在代码里加入对输入长度的限制拒绝超长请求而不是硬扛。还有一个很容易被忽略的原因多实例共享 GPU 时其他实例把显存吃掉了。我们遇到过线上服务 A 只占 10GB但 GPU 显存被另一个团队的调试进程占满导致服务 A 推理时 OOM。排查时应先看nvidia-smi确认是不是“邻居”占了显存。4.2 首 token 延迟高首 token 延迟高一般不是 GPU 算力不够而是预处理和排队耗时太长。预处理包括 tokenize、padding、显存分配如果请求体很大这个环节很费时间。先查请求长度如果大量输入都在 2000 token 以上考虑在前置层加长度压缩比如提取关键信息后再送进模型。再看排队情况如果所有请求都在排队等上一批结束说明批次设置过大或实例数不足。最后检查模型推理框架是否开启了对输入输出的流式处理避免一次性加载全部上下文的开销。我们当时把排队方式从“先来先服务”改成“短请求优先”首 token 延迟直接下降了 40%。这个方法在业务允许的情况下很有效但要考虑公平性防止长请求被无限饿死——我们加了一个超时保护长请求等待超过 2 秒就插队处理。4.3 量化后模型变笨了模型量化后输出质量下降是最让人头疼的问题。根源几乎都在校准数据集上你选的校准集和真实业务数据分布差异太大量化尺度就不准。我们踩过一个大坑用模型自带的测试集做校准上线后发现它对物流地址的识别效果骤降。后来把校准集改成从线上脱敏数据中随机抽 5000 条质量立刻恢复。另外量化粒度也值得检查。按权重组per-channel量化往往比按整个张量per-tensor量化更精准缺点是推理速度稍慢但对质量敏感的场景值得。如果试了各种方法效果还不行还有一个备选方案混合精度。关键层保持 FP16非关键层用 INT8 量化。虽然实现复杂度高一点但能有效保住精度。4.4 高峰期偶发超时偶发超时是最难排查的一类问题因为它不是持续性的往往在流量尖峰出现。我们遇到过一次高并发下的偶发超时排查了很久最终定位到是“CPU 预处理跟不上 GPU 推理”。大模型推理并非全程都在 GPU 上跑。tokenize、请求组装、动态 batching 这些环节都在 CPU 上完成如果 CPU 核数不足GPU 就会空转等待。当时我们的容器只分配了 2 个 CPU 核高峰期 CPU 占用 100%GPU 利用率却只有 30%。把 CPU 核数加到 8 之后偶发超时基本消失。这种问题很容易被误判成“GPU 不够”然后盲目加 GPU 实例浪费预算。排查时先看 CPU 利用率和 GPU 利用率的匹配关系CPU 100% 而 GPU 空闲那瓶颈一定在 CPU。4.5 问题速查表现象可能原因排查方向启动即 CUDA OOM模型超过显存换模型或加强量化运行中 OOMKV Cache 空间不足降并发、调整显存利用率首 token 延迟高请求排队 / 预处理慢查队列长度、加短请求优先GPU 利用率低CPU 预处理瓶颈加 CPU 核数量化后效果差校准集分布不匹配换真实业务数据重新校准响应超时实例不足 / 负载过高扩容或限制最大输入长度最后还有一句想对小团队说的话不要一上来就追求“一步到位”。当时我们也是先从单实例跑通再慢慢压测、量化、加路由每一步都有数据支撑才继续往下走。这套流程走下来我们最终用两张 24G 的卡稳定支撑了每天几百万次调用成本比最初预估的下降了 60% 多。大模型推理部署没有那么神秘关键是先跑通再优化最后紧盯监控指标把所有决策建立在数据之上。希望这篇记录能让你少走几个我当时踩过的坑。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑