首页 / 开源项目 / 正文
开源项目

开源推理加速实战指南:从延迟吞吐成本到框架选型与部署调优

chuanbook chuanbook
发布于 2026 年 10 月 18 日
阅读 约34分钟
浏览 1
评论 0

这两年我身边的团队几乎都在把大模型往线上推。有人做客服机器人,有人做代码助手,有人做内部知识库问答。模型效果聊起来都很热闹,真到部署上线,问题就变得很具体:一次请求要等多久,一台机器能扛多少并发,每个月账单会不会失控。我的感受是,推理这件事已经从“模型能不能跑”变成“推理能不能便宜又稳定地跑”。开源推理加速就是在这个缝隙里长出来的技术方向,也是我写这份内容最想聊清楚的部分。

我常跟做业务的朋友说,别只盯着模型参数和榜单分数。用户点下按钮的那一刻,感受到的是首字延迟和吐字速度。运维同学盯的是GPU利用率和请求排队。财务同学看的是单次调用成本。三个视角经常打架,也逼着我们去理解开源推理加速的边界。下面我分几个小主题,把背景和问题界定讲透。

1.1 大模型推理面临的延迟、吞吐与成本挑战

我先从最直观的延迟说起。我见过一个内部问答助手,离线测试时回答质量不错,上线后用户抱怨“打字慢”。问题不在模型不会答,在于首token延迟太高,长回答的生成速度也拖沓。用户等三秒就开始怀疑页面卡了,等十秒可能直接关掉。大模型推理的延迟拆开看有排队时间、预填充时间、解码时间、网络回传时间,每一段都能吃掉体验。开源推理加速工具做的事情,很多时候就是把这些时间一段段压下去。

吞吐是另一个视角。我做过一次小规模压测,同一张卡、同一个模型,换一种批处理策略,QPS能差出好几倍。业务高峰期的请求像潮水,来的时候不会排队等你准备好。吞吐上不去,团队只能加机器,加机器就推高成本。我见过有团队为了扛住白天流量,长期保留峰值容量,夜里机器闲着,账单照付。大模型推理的成本挑战,表面看是GPU贵,往深里看是资源利用率不够细。

成本这件事我特别想多说一句。很多人把成本理解成“每小时多少钱”,我更愿意算“每个有效回答多少钱”。这里有显存占用、并发效率、模型精度、失败重试、缓存命中率。开源推理加速的价值在于让团队能自己调这些变量,不用完全被闭源API的价格牵着走。我见过一家小团队用开源方案把单机吞吐拉上去,月成本降了一截,响应时间还更稳。延迟、吞吐、成本三个词经常一起出现,它们不是独立问题,是一组需要平衡的工程约束。

1.2 开源推理加速的范畴、价值与适用边界

我理解的开源推理加速,不是某一个单独工具,而是一组围绕推理部署的开放技术方案。模型量化、KV Cache管理、连续批处理、算子融合、投机解码、服务编排,这些都在范畴里。有人把它窄化成“换个推理框架”,我觉得太窄。开源推理加速更像一套可拆装的工具箱,团队能根据硬件、模型、流量形态挑零件。你可以在vLLM里用PagedAttention,也可以在llama.cpp里做端侧量化,还可以用TensorRT-LLM压榨特定硬件。边界不在工具名字,在团队要解决的问题。

它的价值我感受很深。闭源API省心,遇到特殊模型、私有数据、成本敏感场景,开源方案给了团队掌控感。我能看到推理链路里的每一层,能改batch策略,能换量化精度,能按业务SLA做调度。社区迭代速度也快,新模型出来,开源框架往往很快跟进。我踩过的坑是,开源不等于免费省心,版本兼容、显存溢出、精度回退都要自己扛。选开源推理加速之前,我会先问团队有没有基本的工程能力,有没有人能看日志、调参数、做压测。没有这些,开源工具也会变成新的技术债。

适用边界也需要说清楚。在线低延迟场景,开源方案可以做,前提是调好调度和批处理,别让排队把延迟吃掉。离线高吞吐场景,开源推理加速很划算,批处理和大并发能把单位成本压下来。端侧和边缘场景,量化和小模型配合轻量框架更合适。私有化部署、数据合规要求高的场景,开源方案有天然优势。我的判断是,开源推理加速适合愿意投入工程力量、对成本或数据有明确诉求的团队。只想开箱即用、不想碰底层参数,托管API可能更省事。这个边界想清楚,后面选框架和调优才不容易走偏。

1.3 从模型训练优化到推理部署优化的关注点转移

前几年大家聊大模型优化,话题容易落在训练侧:数据配比、分布式训练、混合精度、梯度检查点。训练当然重要,它决定模型能力上限。我观察到的情况是,模型训练完只是起点,推理部署才是天天要面对的现实。训练优化追求的是“多久训完、效果多好”,推理优化追求的是“每次回答多快、每块钱能服务多少请求”。两个阶段的指标不一样,工程手段也不一样。团队如果还把训练侧经验直接搬到推理侧,容易忽略KV Cache、批处理调度、显存碎片这些细节。

我自己的关注点也在转移。早些年我看模型先看参数量,现在看推理先看显存预算和延迟目标。一个7B模型在消费级显卡上跑,量化到4bit可能刚好;换到线上服务,batch大小、最大上下文长度、并发数会重新定义显存需求。训练时不太在意的解码阶段,在推理里变成主战场。投机解码、连续批处理、PagedAttention这些词,我一开始也觉得碎,真做过压测才明白它们直接决定服务能不能扛住。

这个转移对团队协作也有影响。算法同学关心效果,工程同学关心吞吐,运维同学关心稳定性。开源推理加速把这三者拉到同一张桌子上。我常建议团队在项目早期就做推理基准测试,别等模型上线才发现显存不够、延迟超标。训练优化和推理部署优化不是谁替代谁,是接力赛。训练把模型交出来,推理部署把它变成可用的服务。开源推理加速正好站在后半程,帮团队把模型能力转成业务体验和成本优势。这就是我开篇先界定背景和问题的原因,后面的技术机制、框架对比和实战教程,都从这里展开。

我平时跟人聊推理加速,最怕聊成名词接龙。量化、PagedAttention、投机解码、算子融合,这些词单独拎出来都挺唬人,放进真实服务里到底管什么用,才是我关心的。这一章我想拆的就是这层底座。模型在显卡上跑起来,快的和慢的中间隔着四层东西:模型本身怎么存、推理引擎怎么管请求、底层算子怎么算、解码调度怎么排。我按这四层往下走,每一层都说说它解决什么问题,什么时候好用,什么时候容易踩坑。

我自己的理解是,这四层不是独立起作用的。你把模型压到4bit,引擎层没管好KV Cache,显存照样爆。算子融合做得再漂亮,调度策略拉胯,用户等首字还是等到骂人。做推理加速有点像调一辆车的动力系统,发动机、变速箱、底盘、电控都得配合。我见过团队只盯着量化一个点,上线效果不达预期,回头查发现是批处理配置没跟上。所以这章我尽量把每一层的边界和联动讲清楚。

2.1 模型层加速:量化、稀疏化与蒸馏的适用场景

我最早接触模型层加速就是量化。说白了就是把模型权重从FP16压到INT8、INT4,甚至更低。显存占用直接砍半甚至砍到三分之一,同一张卡能塞更大的模型。我做过一个7B模型的INT4量化,原来FP16跑起来显存紧绷,量化之后留出了不少空间给KV Cache,并发数也上去了。量化分训练后量化和量化感知训练两类,前者省事,后者精度更稳。我一般会先跑训练后量化看效果,精度掉得厉害再考虑QAT那套。

量化的坑我也踩过不少。不是所有层对精度都敏感,有些模型的注意力层压太狠,回答就开始胡言乱语。我现在的习惯是做完量化先跑一组业务评测,别只看perplexity。还有硬件支持问题,INT4在有些卡上加速明显,在老卡上可能还不如FP16。量化不是万能药,它换的是显存和带宽,代价是精度余量。业务能容忍多少精度回退,这个账得提前算。

稀疏化和蒸馏我放在一起说,因为它们在我手里的使用频率比量化低,但场景很特定。稀疏化是把权重里不重要的连接剪掉,理论加速空间大,实际落地要看硬件和框架支持,我见过不少团队剪完发现推理引擎吃不到这个红利。蒸馏更像训练侧的事,拿大模型教小模型,适合端侧或者成本极敏感的场景。我的经验是,量化是首选,稀疏化观望硬件生态,蒸馏适合有训练资源和时间窗口的团队。三个工具不是替代关系,是不同预算下的不同解法。

2.2 引擎层加速:连续批处理、PagedAttention与KV Cache管理

引擎层是我觉得最容易被低估的一层。很多人以为推理快慢主要看模型和显卡,其实请求怎么排队、显存怎么分配,影响一点不比硬件小。连续批处理就是典型例子。传统批处理要等一批请求凑齐了一起跑,短请求被长请求拖着,GPU利用率上不去。连续批处理让新请求随时插进来,完成的请求随时退出,GPU尽量不空转。我第一次在vLLM里看到这个机制跑起来,QPS提升很明显,尤其是请求长度参差不齐的线上场景。

PagedAttention这个名字听着玄,我理解它就是给KV Cache做了分页管理。大模型推理时每个请求都要存Key和Value,上下文越长占得越多。传统做法是给每个请求预分配一块连续显存,长度按最大可能来,浪费严重。PagedAttention把KV Cache切成固定大小的块,按需分配,像操作系统管内存那样管显存。我在长上下文场景里感受特别深,显存碎片少了,能同时服务的请求数上去了,吞吐自然跟着涨。

KV Cache管理本身也是个细活。缓存留多久、什么策略淘汰、前缀能不能复用,这些参数在真实服务里直接影响成本和延迟。我见过客服场景里大量重复的系统提示词,开启前缀缓存之后首token延迟降了不少。也见过缓存策略没调好,显存被撑爆触发OOM。引擎层这些东西不像模型量化那么直观,调好了是润物细无声,调不好就是线上事故。我现在的习惯是部署前先把请求长度分布摸清楚,再决定批处理和缓存参数。

2.3 计算层加速:算子融合、编译优化与硬件后端适配

计算层离业务最远,离硬件最近。算子融合我拿一个简单例子说。模型里常见的LayerNorm加激活、矩阵乘加偏置,这些操作分开跑要多次读写显存,融合成一个算子就能少跑几趟。显存带宽在大模型推理里经常是瓶颈,少读写一次就是实打实的加速。我见过优化前后的profile对比,融合之后kernel数量少了一截,端到端延迟也跟着降。这种事单看代码看不出来,得靠profiling工具把热点找出来。

编译优化这几年在推理侧越来越主流。传统推理是算子一个个调,编译优化是把整个计算图拿过来,做图层面的融合、内存规划、指令调度。TensorRT-LLM、ONNX Runtime、OpenVINO这些走的就是这个路子。我自己的体会是,编译优化在特定硬件上收益很大,代价是模型转换和适配要花时间。新模型出来,编译链路不一定马上跟上,团队得留出适配窗口。它不是开箱即用的东西,更像一条需要维护的产线。

硬件后端适配这块我特别想提一句。同一个模型、同一套代码,跑在NVIDIA卡、AMD卡、国产加速卡上,性能表现能差出好几倍。开源推理框架的硬件支持成熟度参差不齐,有的对CUDA生态吃得透,有的在特定国产芯片上做了深度优化。我选框架时会先看目标硬件的支持列表,别等部署了才发现某个算子在目标卡上没实现,回退到CPU跑,延迟直接没法看。计算层的优化不是抽象的,它最终要落到你手里那张卡上。

2.4 解码与调度:投机解码、并行策略与服务编排

解码阶段是生成式推理的特殊战场。大模型是一个token一个token往外吐的,解码速度直接决定用户感受到的吐字快慢。投机解码的思路我喜欢用一个比喻:先让一个小模型快速猜几个token,再用大模型一次性验证。猜对了就省了多次大模型前向,猜错了回退重来。我在对话场景里试过,草稿模型选得合适的时候,解码速度提升挺可观。草稿模型选不好,验证开销吃掉收益,甚至更慢。这个技术对场景有要求,不是所有任务都适合。

并行策略解决的是单卡装不下或者单卡不够快的问题。张量并行把一层拆到多张卡上算,流水线并行把不同层分到不同卡上。我做过双卡张量并行的部署,模型能跑起来了,卡间通信开销也上来了。并行度不是越高越好,通信成本和收益要算账。多卡部署还得考虑负载均衡,别让一张卡忙死、另一张卡闲着。我见过团队为了跑大模型硬上多卡,结果小请求根本喂不饱,资源浪费严重。

服务编排在调度这一层是收口的位置。请求进来怎么路由、多模型怎么共存、GPU怎么分时复用、限流和降级怎么做,这些事推理框架本身不一定全管,得靠编排层补上。我在生产环境里见过单机多模型部署,通过编排把不同业务分配到不同实例,显存隔离,互不干扰。也见过流量突增时没有限流,整个服务被拖垮。解码和调度这一层,技术含量不低,工程经验占比很大。它决定了前面三层优化能不能在真实流量下稳定发挥出来。

回过头看这四层,我的感受是开源推理加速没有银弹。模型层省显存,引擎层提吞吐,计算层压延迟,调度层保稳定。每一层都有它的收益和代价,组合起来才是一套能上线的方案。我后面讲框架对比和实战部署,都会回到这四层来找依据。哪一层薄了,线上迟早会以某种方式提醒你。

上一章拆完四层底座,这一章我想聊框架。圈子里隔三差五就出一份框架性能排行榜,图上柱子高低差得挺吓人。我早年也照着榜单选过框架,选完上线发现不是那么回事。榜单是别人家的模型、别人家的硬件、别人家的请求分布。你手里的活儿跟它对不上,跑分再高也白搭。我现在的态度是,框架对比先看它长在什么土壤里,再看它在你的场景里能不能活。

这一章我按自己用过的顺序来说。有的框架我用了两年,有的只跑过demo就放下了。我会把每个框架的脾气、适合谁、哪里容易硌手都讲一讲,最后给一张我自己在用的选型表,再说几个我踩过的误区。

3.1 对比维度与评测方法:吞吐、延迟、显存、易用性与生态

我评框架一般看五个口子。吞吐看每秒能出多少token、能扛多少并发;延迟分首token时间和每token时间,在线业务盯首字,离线批量盯总时长;显存看峰值占用和长上下文下的表现;易用性看装起来顺不顺、文档看不看得懂;生态看模型跟进速度、硬件支持列表、社区活跃度。这五个口子不是并列关系,业务场景不同,权重完全不一样。做客服的会把首token延迟排第一,做离线摘要的把吞吐排第一,做端侧的先把显存和硬件兼容性摆前头。

评测方法上我有一个笨办法,但管用。先把自己线上真实的请求长度分布抽出来,按P50、P90、P99分三档造压测集。再用并发阶梯往上打,从1并发打到硬件吃满,记录每一档的吞吐和延迟。冷启动和热稳定状态分开测,很多框架冷启动慢得离谱,模型加载加warmup能花好几分钟。我见过一个框架跑分漂亮,实际压测时P99延迟抖得跟心电图似的,这种数据官方榜单上看不到。

还有一个细节我想提,评测的时候别只测一个模型。7B和70B的表现能差出框架的适用边界来。小模型上vLLM和SGLang可能咬得很紧,上了大模型多卡场景,通信开销和并行策略的差异就冒出来了。我一般至少跑一个7B稠密模型加一个MoE模型,MoE的专家路由对框架调度是个考验。测完再把数据拉平看,哪个框架在哪个档位掉链子一目了然。

3.2 通用服务型框架:vLLM、SGLang、TGI、LMDeploy

vLLM是我上线第一个服务时用的框架,那会儿版本号还是0.4开头。PagedAttention和连续批处理是它的招牌,这两样东西在上一章讲过原理,落到实际使用里,最直观的感受是并发数能拉起来。它的OpenAI兼容接口做得很到位,前端几乎不用改代码就能接上。装的时候踩过CUDA版本对不上的坑,折腾了小半天,装顺了之后跑起来还算省心。社区迭代快,新模型一般几天内就能跟上,这个对追新模型的团队挺友好。

SGLang我是拿来做多轮对话场景的,它的RadixAttention在长system prompt重复率高的业务里优势明显。我们那个客服场景每条请求带两千多字的系统提示词,开启前缀缓存之后首token延迟降了一截。它还有个约束解码的功能,做结构化输出时挺顺手,不用在外面再套一层解析。SGLang的学习曲线比vLLM稍陡一点,文档写得不算特别细,有些参数得翻源码或者社区issue才搞明白。

TGI是Hugging Face家的,Rust写的,docker镜像拉下来就能跑,部署体验在几个框架里算最顺的。我拿它做过快速验证和内部demo,起来就能用。它的问题是模型适配速度有时候不如vLLM快,一些新架构的模型要等community那边合并支持。生产环境里我用得少一点,主要是定制化空间不如前两个大。

LMDeploy是上海AI Lab那边的,我在国产加速卡上试过,硬件适配做得比预期好。TurboMind引擎加W4A16量化,在特定卡上跑出来的吞吐能看。它跟InternLM系列模型配合得紧,中文社区活跃,遇到问题去群里问响应挺快。多卡部署的配置比vLLM稍微繁琐一点,得看清楚它的并行配置文档。这几个框架我现在的用法是,通用在线服务vLLM打底,长提示词场景加SGLang,国产硬件上先试LMDeploy,TGI留给快速验证。

3.3 端侧与轻量部署:llama.cpp、MLC LLM、ExLlamaV2

llama.cpp是我在MacBook上跑模型的第一选择。GGUF格式现在生态很成熟,Hugging Face上大把现成的量化模型直接下,Q4_K_M这种量化档位在7B模型上能跑出可用的速度。我出差路上拿它跑过会议纪要整理,十几token每秒,够用。它的强项是硬件覆盖面广,CPU、Metal、CUDA、Vulkan都能吃,量化类型给得细,从Q2到Q8都有,还有各种K量化变体。缺点也明显,它的服务化能力弱,并发支持有限,拿它扛线上流量不现实。

MLC LLM走的是另一条路,基于TVM编译,把模型编译到目标后端。它最惊艳的演示是浏览器里跑模型,WebGPU一开,手机上也能跑。我在一个内部展示项目里用过,效果挺抓眼球。实际落地的话,编译流程比llama.cpp麻烦,环境配置和模型转换要花时间,出问题排查起来也偏底层。它适合有跨端部署需求的团队,尤其是那种一套模型要跑到iOS、Android、Web多端的场景。

ExLlamaV2在GPU上跑量化模型效率不错,EXL2格式支持每权重2到8bit的混合精度,单张24G卡跑70B的Q3量化能跑起来。我在一个离线批处理任务里用过它,速度比预期好。它的生态比前两个小,模型转换工具链不算完善,社区规模也有限。我把它定位成一个特定场景的补充工具,不是主力框架。端侧这三个框架有个共同点,它们解决的是一台机器或者一台设备上跑起来的问题,不是服务化的问题。拿它们去做在线服务,得在外面自己搭一层调度和限流。

3.4 编译优化与厂商生态:TensorRT-LLM、ONNX Runtime、OpenVINO等

TensorRT-LLM是NVIDIA的亲儿子,性能天花板确实高。我在一个固定模型的长期服务里用过,同样的硬件和模型,延迟比通用框架低一截。代价是编译转换链路长,build engine花几十分钟是常事,模型版本一换就得重来。它对CUDA和驱动版本的耦合也紧,升级环境前得先看兼容矩阵。我现在的判断是,模型固定、硬件固定、对延迟极度敏感的场景值得上它,模型天天换的团队用它会被维护成本拖住。

ONNX Runtime走的是通用路线,跨硬件跨平台,GenAI这套扩展出来之后在LLM推理上进步不小。Windows上配合DirectML能跑,跨平台统一部署是它的卖点。它的性能在NVIDIA卡上比不过专门优化的框架,换来的是可移植性。我见过一些企业环境里用ONNX Runtime做统一推理层,不同硬件后端跑同一套模型格式,运维上省心。

OpenVINO在Intel生态里有主场优势,至强CPU和集显上跑LLM,配合INT8量化,吞吐能接受。我在一个纯CPU的部署场景里用过,成本比上GPU低不少,延迟嘛,跟GPU没法比,适合对延迟不敏感的离线任务。这类编译优化框架有个共性,它们跟硬件厂商绑得深,性能红利来自对特定硬件的深度适配,代价是灵活性和模型跟进速度。选它们之前先问自己一句,模型和硬件半年内会不会变。

3.5 框架选型矩阵与常见误区

我自己的选型表按场景分。在线低延迟高并发服务,vLLM打底,长提示词和结构化输出场景加SGLang。离线批量处理,TGI或者LMDeploy都行,看硬件。端侧和轻量部署,llama.cpp优先,跨多端需求看MLC LLM。NVIDIA卡上模型固定、延迟卡得死的场景,评估TensorRT-LLM。跨硬件统一部署需求,ONNX Runtime和OpenVINO按硬件阵营选。这张表不是死的,我每隔几个月会根据自己的压测数据调一调。

误区这块我踩过几个,印象深。一个是拿官方benchmark当自己的性能预期,官方跑的是标准数据集、理想并发,跟你线上的流量形态差得远。一个是不看硬件支持列表就选框架,部署那天才发现某个算子在目标卡上没实现,回退CPU跑,延迟没法看。还有一个是低估运维成本,框架版本升级、模型格式转换、依赖冲突这些事,上线之后每个月都得花时间。

最坑的一个误区是把端侧框架硬扛在线服务。我见过团队拿llama.cpp搭了个API就对外服务,并发一上来就崩。端侧框架的设计目标是单机单用户跑起来,不是扛流量。还有一个反向误区,一上来就上TensorRT-LLM,模型还没定型,编译链路天天重来,团队时间全耗在适配上了。框架选型这事,我现在的原则是先跑通再优化,先用通用框架把服务跑起来,摸清瓶颈再决定要不要上专用框架。

框架选完,活儿才刚开始。上一章末尾我说过一句话,先跑通再优化。这一章我就把跑通到跑稳这段路拆开讲。我带过几个新人做部署,他们卡住的地方往往不是框架本身,是前面那些琐碎的准备工作。硬件账没算清,模型格式没对上,环境依赖打架,压测数据看不懂,每一步都能耗掉一两天。这一章我把这几步按我自己干活的顺序排一遍,中间夹着踩过的坑和几个小脚本思路。

4.1 部署前准备:硬件评估、模型选择与环境依赖

硬件评估这事我习惯拿张纸先算。模型权重的显存账很简单,参数量乘精度字节数,7B的FP16模型大约14个G,70B的FP16得140个G。这只是权重,真正吃掉显存的是KV Cache,并发数一上来它能翻好几倍。我一般按目标并发数乘上上下文长度,再乘每token每层的KV字节数,估一个峰值。估完留20%的余量给激活值和框架自身开销。算下来一张24G卡跑7B的FP16模型,并发开到8到16也就到头了,再往上就得靠量化或者加卡。

模型选择上我有一个偏好,优先挑社区支持成熟的架构。Llama系、Qwen系、Mistral系这些,主流框架跟进快,出问题搜索引擎上能找到答案。冷门架构的模型,哪怕效果再好,部署时算子不支持、量化工具链缺失,能把你卡到怀疑人生。我见过一个团队选了个新出的MoE模型,vLLM那边还没合并支持,自己改源码改了两周。模型没定型之前,选个主流架构能省下大量时间。

环境依赖是新人最容易栽跟头的地方。CUDA版本、驱动版本、PyTorch版本、框架版本,这四个东西有一条对不上就报错,报的错还常常牛头不对马嘴。我现在的做法是用Docker,框架官方镜像拉下来直接用,环境一次配好镜像存起来,换机器直接跑。裸机装的话,我一般先跑一个nvidia-smi看驱动,再跑nvcc -V看CUDA,然后去框架的requirements里核对它要求的版本范围。这个核对花十分钟,能省掉后面两小时的报错排查。

4.2 模型转换与量化:格式适配、精度校验与显存预算

格式适配这一步看你选的框架。vLLM吃HuggingFace原生格式,下载下来基本能直接用,大模型分片的话注意把config和tokenizer都下全。llama.cpp要GGUF格式,HuggingFace上直接搜模型名加GGUF后缀,现成的量化版本一大把,省得自己转。LMDeploy有自己的转换工具,AWQ量化模型得走它的流程。TensorRT-LLM的转换链路最长,先转checkpoint再build engine,中间任何一个参数配错都得重来。

量化这事我有个原则,先校验再上线。W4A16、GPTQ、AWQ、FP8,每种量化方式在不同模型上的掉点幅度不一样。我一般准备一个小评测集,一两百条覆盖业务典型问题,量化前后各跑一遍,对比输出质量和困惑度。掉点可接受才往生产推。有一次我用INT4量化一个7B模型做摘要任务,评测集上看不出差别,上线之后用户反馈长文档摘要开始丢细节,回头一查,量化把长尾token的概率分布压平了。量化省显存是真的,伤精度也是真的,校验这步不能省。

显存预算我会在转换完之后再核一遍。W4A16量化7B模型,权重大概压到4个G出头,KV Cache没变,并发能力能翻两三倍。这个账要提前算进容量规划里。我习惯在部署脚本里加一行日志,把模型加载后的显存占用打出来,跟预算对一下。对不上就说明哪里估错了,早发现比压测时才发现好。

4.3 服务化部署:API封装、容器化与多模型管理

API封装我首选OpenAI兼容接口。vLLM、SGLang、LMDeploy都内置了这套接口,起服务的时候加个参数就开了,前端SDK几乎不用改。自研接口的话至少要实现chat completions和completions两个端点,流式输出用SSE,超时和重试机制得想清楚。我在一个项目里自己封了一层网关,做鉴权、限流、请求日志,模型服务本身保持干净,网关和模型解耦之后扩容和维护都灵活。

容器化这块我踩过一个坑,镜像里把模型权重也打进去了,镜像体积干到三十多个G,每次更新都得重新推。后来改成权重挂载宿主机目录,镜像只装框架和依赖,体积压到几个G,更新模型只是换挂载路径。Dockerfile里我一般固定基础镜像的digest,避免某天上游更新把依赖版本带跑偏。启动脚本里加健康检查端点,容器编排那边探活能探到,服务假死的时候能自动重启。

多模型管理有两种路子。一个服务实例加载多个模型,请求里带模型名路由,适合模型都不大、请求量分散的场景。另一种是每个模型一个实例,前面挂个路由层,适合大模型和流量集中的场景。我倾向后一种,隔离性好,一个模型出问题不影响其他。代价是显存要分着用,得算清楚每张卡上放几个实例。管理上我一般配一个简单的模型注册表,记录每个模型的路径、量化方式、显存占用、端口号,部署脚本按注册表拉起实例。

4.4 性能压测与监控:指标采集、瓶颈定位与容量规划

压测工具我用得最多的是框架自带的benchmark脚本,vLLM的benchmark_serving、SGLang的benchmark,参数能把输入长度、输出长度、并发数、请求数都配出来。跑的时候我按阶梯来,并发从1、4、8、16一路往上加,每一档记录吞吐和延迟。首token延迟和每token延迟分开看,这两个指标对应的瓶颈不一样。首token慢通常是prefill阶段的问题,每token慢往往是decode阶段或者调度的问题。

瓶颈定位有个笨办法但好用,边压测边看nvidia-smi。GPU利用率上不去,八成是CPU预处理或者网络IO卡住了。显存满了但利用率不高,可能是KV Cache分配策略有问题。GPU利用率打满但吞吐上不去,得看是不是批处理没开起来。我遇到过一次吞吐死活上不去,查了半天发现是tokenizer在CPU上串行处理成了瓶颈,换了个并行tokenizer实现,吞吐直接翻倍。这种问题光看框架日志看不出来,得把系统层面的指标一起看。

监控指标我一般盯这几个,请求QPS、P50/P90/P99延迟、首token延迟、GPU利用率、显存占用、队列长度。队列长度这个指标特别有用,它能提前告诉你容量要到顶了。容量规划我按峰值QPS乘上一个安全系数来算副本数,再留一档给突增流量。压测数据出来之后画个并发和吞吐的曲线,找拐点,拐点之前是线性增长区,拐点之后加并发吞吐不涨延迟暴涨,那个拐点对应的并发数就是单实例的合理容量上限。

4.5 典型场景部署路径:单机服务、多卡并行与边缘端

单机服务是最常见的场景,一张卡跑7B或者14B模型,中小流量的在线业务够用。部署路径很直接,装框架、下模型、起服务、压测、上监控,半天能跑通。我一般用vLLM打底,命令行参数把max-model-len、gpu-memory-utilization、max-num-seqs这几个调好。gpu-memory-utilization默认0.9,显存紧的时候可以往上调一点,注意别把系统撑爆。max-num-seqs控制并发批大小,调大了吞吐涨但延迟会变差,得压测找平衡点。

多卡并行是70B以上模型的必经之路。张量并行TP是最常用的方式,vLLM起服务的时候tensor-parallel-size设成卡数就行,卡间通信走NVLink的话效率高,走PCIe的话通信开销得算进延迟里。我部署过一个70B的模型,4张A100走NVLink,TP=4,首token延迟比单卡跑7B还低,吞吐也够看。多卡部署的坑主要在环境一致性上,每张卡的驱动版本、CUDA版本得一模一样,有一张卡版本不对整个服务起不来。部署前跑一遍nvidia-smi -L确认卡都在,再跑个简单的all-reduce测试确认通信正常。

边缘端部署跟前面两个场景差别挺大。硬件资源有限,模型得量化到4bit甚至更低,llama.cpp是首选。我在一台Jetson Orin上部署过7B的Q4量化模型,十来token每秒,做本地问答够用。Mac上跑llama.cpp更简单,brew装完下个GGUF模型就能跑。边缘端部署要特别注意内存和散热的约束,长时间跑推理设备会烫,降频之后速度掉得厉害。我做边缘部署的时候会加一个简单的温度监控,温度过高时降低并发或者暂停请求,保护设备。

部署这事说到底是个细致活。每一步都有坑,坑的大小跟你对环境的熟悉程度成反比。我现在的习惯是每部署一个新场景,把步骤写成脚本,下次遇到类似场景改改参数就能用。脚本里把每一步的检查点加上,哪一步没过直接报错退出,省得跑到一半才发现问题。这套东西攒下来,现在部署一个新模型,从环境准备到压测通过,半天到一天能搞定。

部署跑通是一回事,长期跑得稳、跑得省、跑得跟得上变化是另一回事。我带过几个团队从零搭推理服务,发现一个共性:上线第一个月大家都很兴奋,指标也漂亮,三个月后回头看,配置没人敢动,版本没人敢升,性能悄悄滑坡,成本悄悄上涨。这一章我想聊的就是怎么把推理加速从一次性的部署项目,变成一套能自己转起来的运营体系。选型、调优、成本、生态、团队,五件事环环相扣,漏掉哪一环后面都得还债。

5.1 场景化选型:在线低延迟、离线高吞吐与端侧推理

选型第一刀永远切在场景上。我见过太多团队拿着一份框架对比表格就开始投票,vLLM分数高选vLLM,SGLang新出了个特性又想换,换完发现业务场景根本不吃那一套。在线服务和离线任务对推理引擎的要求几乎是相反的。在线服务盯着首token延迟和P99,用户敲完问题等三秒就开始不耐烦,这时候吞吐高不高没那么重要,尾巴不能长。离线批处理盯着单位时间处理量,延迟是十分钟还是十五分钟没人关心,GPU利用率拉满才是正经事。

我自己的经验是,在线低延迟场景优先看框架的调度精细度和KV Cache管理能力。vLLM的PagedAttention在长上下文、高并发下表现稳,SGLang的RadixAttention对多轮对话、共享前缀的场景有优势,两者选谁看你的请求模式。我们有个客服机器人项目,多轮对话占比高,用户经常在同一个会话里追问,切到SGLang之后首token延迟降了将近四成。反过来一个文档翻译的离线任务,用TGI的批处理模式,把max_batch_size调到硬件上限,吞吐比默认配置高了快两倍,延迟从三秒变成八秒,业务方根本感知不到。

端侧推理的选型逻辑又不一样。端侧没有机房环境,内存、功耗、散热全是硬约束,框架的体积和依赖复杂度比性能指标还重要。llama.cpp在端侧几乎是默认答案,单二进制文件,量化格式成熟,Mac、Jetson、树莓派都能跑。MLC LLM的编译路线在移动端有优势,但工具链学习曲线陡,团队没有编译背景的话维护成本不低。我一般建议端侧项目先用llama.cpp跑通场景验证,确认模型效果和延迟可接受之后,再评估要不要换更激进的方案。端侧换框架的代价比服务端大得多,机型适配、功耗调优、固件兼容都是坑。

还有一个容易被忽略的维度是团队技术栈。框架再好,团队里没人能改它的源码,出了问题只能等社区修,这个风险得算进选型里。我们选vLLM有一个原因就是社区活跃,issue响应快,遇到算子不支持的情况社区一般两三周能合入。选框架跟选队友差不多,能力重要,靠得住更重要。

5.2 调优闭环:基准测试、参数调参与回归验证

调优这事最怕做成一次性运动。上线前猛调一轮,参数写死在启动脚本里,后面再也没人碰过。模型换了、流量变了、框架升级了,参数还是那套老参数,性能慢慢就掉下去了。我现在推的做法是把调优变成一个固定节奏的闭环,基准测试、参数调参、回归验证三步循环,每轮框架升级或者模型换版就转一圈。

基准测试的关键是测试集要贴近真实流量。拿公开数据集跑出来的数字好看,上线之后对不上,这种事太常见了。我一般从线上日志里采样几百条真实请求,输入长度分布、输出长度分布、并发模式都按实际比例来,做成一个固定的压测集。每次调参或者升级,拿这个集跑一遍,对比首token延迟、每token延迟、吞吐和显存占用四个数。数字对不上就查原因,是框架行为变了还是参数没跟上。

参数调参我吃过一个亏。早期调vLLM的时候,看到max-num-seqs调大吞吐涨,就一路往上加,加到256的时候吞吐确实好看,上线之后P99延迟直接飙到十几秒。回头分析发现并发批太大,单个请求在队列里等的时间太长。后来我给自己定了个规矩,调参必须看P99,不能只看平均值。gpu-memory-utilization也是,默认0.9往上调能多挤一点显存出来,调到0.95以上就得小心,框架自身的显存开销和碎片化可能把系统撑爆,我们有一次调到0.97,服务跑了三天之后OOM,查了半天是显存碎片积累导致的。

回归验证这一步很多人省掉了,觉得浪费时间。我的做法是每次调参之后,不光跑性能指标,还跑一小批业务效果校验。量化参数、批处理策略、调度参数这些改动,理论上不影响输出质量,实际上有些参数会间接影响采样行为。我们有个摘要服务,调了一个调度参数之后BLEU分数掉了两个点,原因是批处理改变了请求的拼接方式,影响了tokenize的边界处理。这种问题性能测试根本发现不了,必须业务侧一起回归。调优闭环里性能和质量两条线得同时看,缺一条都容易翻车。

5.3 成本、稳定性与安全合规的平衡

推理服务的成本账,我习惯拆成三块来看:GPU成本、人力成本和故障成本。GPU成本最直观,一张A100每小时多少钱,跑多少并发,摊到每个请求上多少成本。这里有个反直觉的地方,GPU利用率高不等于成本低。利用率拉满的时候延迟往往变差,用户体验下降带来的隐性成本可能比省下的GPU钱多得多。我一般会算一个平衡点,在延迟可接受的范围内把利用率做到最高,而不是追求利用率绝对值。我们有个项目把利用率从85%压到70%,GPU数量多用了两台,但P99延迟从四秒降到两秒,用户投诉率降了七成,算总账反而是省钱的。

稳定性这块,开源推理服务有几个常见的脆弱点。一个是版本升级的兼容性,框架社区迭代快,小版本之间API变更是常事,升级之前不看changelog直接升,配置项改名、参数默认值变化都能让服务起不来。我现在固定一个做法,升级先在预发环境跑一周,压测加业务回归都过了再上生产。另一个是模型服务的健康检查,光探端口通不通不够,得探推理接口能不能正常返回。有些框架进程活着但推理线程卡死,端口探测是通的,请求全超时。我在网关层加了一个轻量的健康检查请求,定期打一个短输入进去,返回超时就把实例摘掉。

安全合规是开源方案里容易被低估的一块。模型权重、推理日志、请求内容,这三样东西在合规审查里都得有交代。权重文件的访问控制,日志里的敏感信息脱敏,请求内容的留存策略,这些在闭源商业方案里厂商帮你兜底,开源自建就得自己设计。我们现在的做法是推理服务前面挂一层网关,鉴权和审计都在网关做,模型服务本身不直接对外。日志里请求内容默认不落盘,只留token数量和延迟指标,需要排查问题时临时开debug日志,排查完关掉。这一套东西部署的时候多花两天,后面省掉的是合规审查时的来回扯皮。

还有一个平衡点是量化策略和业务容忍度。INT4量化省显存是实打实的,7B模型从14G压到4G,同样的卡能多跑两三倍的并发。量化对输出质量的影响因任务而异,分类、抽取这类任务容忍度高,生成、推理这类任务容忍度低。我的建议是按业务场景分档,不同场景走不同量化等级,不要一刀切。省钱和省心之间得有个明确的决策依据,不能拍脑袋。

5.4 生态趋势:标准化接口、软硬协同与社区演进

开源推理生态这两年的变化速度很快,快到做长期规划的时候得留出足够的弹性。我观察下来有三个趋势值得关注。一个是接口标准化,OpenAI兼容接口几乎成了推理框架的标配,vLLM、SGLang、LMDeploy、TGI都支持,这对上层应用是好事,框架可以换,应用层不用大改。我们现在的做法是所有模型服务统一暴露OpenAI兼容接口,上层网关只认这一套协议,后面换框架或者加框架,网关侧改个路由配置就行。标准化接口带来的解耦价值,比单个框架的性能优势更值得重视。

软硬协同是另一个明显趋势。以前推理加速主要在软件层做文章,现在硬件厂商也在往框架里扎。NVIDIA的TensorRT-LLM跟自家GPU深度绑定,AMD的ROCm生态在补推理支持,国产芯片厂商也在适配主流框架。这个趋势对选型的影响是,硬件和框架的匹配度变得更重要了。选框架的时候不能只看框架本身,得看它在你的目标硬件上有没有官方支持、社区适配做得好不好。我们有一个项目跑在国产卡上,vLLM官方支持有限,社区有个分支在维护,用起来就得接受版本滞后和算子缺失的风险。硬件生态的成熟度直接决定了框架选型的自由度。

社区演进的速度也得纳入规划。vLLM从0.2到0.5版本,PagedAttention的实现改了好几轮,性能提升明显,但配置参数和默认行为也变了不少。SGLang的RadixAttention缓存策略更新也快。跟着社区升级能吃到性能红利,不跟着升又怕错过重要的bug修复和安全补丁。我现在的策略是固定一个升级节奏,比如每季度评估一次框架版本,看changelog里有没有影响我们的变更,有就排期升级,没有就跳过。不追最新,也不掉队太远。升级之前预发环境跑一周这个规矩不能破,生产环境直接升级出过事,一次框架小版本升级把默认的max-model-len改了,长请求全被截断,用户反馈上来才发现。

5.5 从部署到运营:团队能力与最佳实践沉淀

最后聊点软性的东西。推理加速这件事,技术方案只占一半,另一半是团队能不能把方案持续运营好。我见过技术选型很漂亮但运营跟不上的团队,服务跑三个月配置就没人说得清了,压测脚本找不到了,调参记录散落在各个人的聊天记录里。也见过技术方案一般但运营扎实的团队,每次变更都有记录,每个参数都有注释,出问题半小时能定位到原因。

能力沉淀我建议从三件事做起。第一件是把部署和调优过程脚本化,从环境准备、模型转换、服务启动到压测验证,每一步写成可重复执行的脚本,脚本里带检查点和日志。这件事我前面章节提过,这里再强调一次,因为它的长期价值远超一次性部署的便利。我们现在的部署脚本跑一遍会自动生成一份部署报告,记录硬件配置、模型版本、量化方式、关键参数、压测结果,归档到一个固定目录。三个月后回头看,当时怎么配的一目了然。

第二件是建一个参数配置的知识库。每个服务的关键参数配了什么值、为什么配这个值、调整过哪些值、每次调整的效果如何,这些信息得有个地方存。工具不限,Notion、Wiki、甚至一个markdown仓库都行,关键是得有人维护、有格式规范、新人能查到。我们团队有个规矩,任何参数变更必须同步更新配置文档,PR里不带文档更新不合并。这条规矩执行了半年,配置相关的线上问题少了七成。

第三件是值班和故障复盘机制。推理服务的故障模式相对固定,OOM、超时、队列积压、版本兼容、硬件故障,翻来覆去就这几类。每次故障之后把时间线、根因、处理动作、改进项写清楚,攒上几次之后你会发现大部分故障是可以提前预防的。我们有一次线上OOM,复盘发现是显存碎片积累导致的,改进项里加了一条定期重启策略和显存碎片监控,后面同类问题再没出过。运营这件事没有终点,但每转一圈,系统就稳一分。

选型看场景,调优靠闭环,成本算总账,生态跟节奏,运营靠沉淀。这五件事串起来,开源推理加速才算是从项目变成了能力。我自己的体会是,前三个月搭架子最累,架子搭好了后面就是日常维护和按节奏演进,投入产出比会越来越好看。

赞0
踩0
☆收藏0
版权声明
文章版权声明:除非注明,否则均为ZBLOG原创文章,转载或复制请以超链接形式并注明出处。
分享到
chuanbook

链接已复制到剪贴板