3090 单卡跑 27B 大模型:升级推理引擎后改代码快近一倍,上下文从 15 万抠回 20 万

3090 单卡跑 27B 大模型:升级推理引擎后改代码快近一倍,上下文从 15 万抠回 20 万

本文数据来自同一台机器(双 RTX 3090)上的真实升级与调优实测;文中明确标注”官方”的数字来自引擎的发布说明,其余速度与上下文数字为本地实测。
同一个模型,同一张显卡,只是升级了推理引擎、又换了几项启动参数,让它把一整个代码文件改好再原样吐回来这类活儿,生成速度从每秒两百四十多个字,涨到了将近四百八十个,翻了一倍。代价是上下文一度从二十多万掉到十五万多,后来又被我们抠回了二十万出头。
翻倍的不是模型,是我们把它的运行方式拧对了。这篇文章讲的是,我们怎么在这台双 3090 的机器上,把 Qwen3.8-27B 跑到当前最新版的推理引擎上,以及在写代码这个最常用的场景里,抠出了哪些参数。
先说结论。负责编码的那张卡,改造之后写新代码快了大约两成,改文件、返回整段代码这类活儿快了将近一倍;上下文一开始从二十多万掉到了十五万多,我们又把它拉回到了二十万出头。整件事没有换模型,已经对接过它的程序,只要不碰那个已经被移除的查询接口,就一行配置都不用动。

先交代一下我们跑的是什么

我们在一台双 RTX 3090、64G 内存的机器上,本地跑 Qwen3.8-27B 这个大模型的量化版本,然后用它给几个应用和几个 AI 助手当后端。两张卡分工不同,一张跑通用版本,负责写作、研究、长文档这类任务;另一张跑一个偏向编程的微调版本,专门服务写代码的助手。
承载模型的引擎叫 NInfer,是一个从零写起的 C++/CUDA 推理引擎,目标就是把一张显卡上的一个模型跑到极致。它对 Qwen3.8 这一代模型做了深度定制,在我们此前的同机对比里,单张 3090 上大约能跑到通用引擎的两倍。它是开源项目,面向 3090 这条线由一个派生仓库在跟进。我们最近才把后端从另一个引擎迁到它上面,这次的升级,是我们碰到的第一版带有破坏性变更的版本。

新版本到底动了什么

引擎在十月十四日发布了 v0.16.0,从我们原先用的 v0.15.1 算起,中间大约合入了七十五个改动。官方说明里,最值得说的有几块。
一块是新的上下文缓存引擎。它把过去”每段会话各存各的”改成了统一管理,官方在一个四路并发、历史各约四万 token 的测试里,缓存命中率从三成出头升到了将近八成,第一个字的平均等待从将近九秒降到了不到三秒。它还允许把会话写到本地磁盘,重启之后能接着用,这是我们后来重点用上的一个能力。
另一块是复制型草稿,也就是 n-gram。它针对的是这样一种场景:模型正要写的内容,其实已经在它读过的材料里出现过了,比如你让它改写一个文件、返回一段工具的输出。这种情况下,模型可以一次性提议最多十五个”照抄”的字,然后去校验,抄错了只是慢一点,不会写错。官方在真实 agent 回放上的测试是整体快四成,那些需要把读过的文件原样写回去的轮次,快五成到七成半。
还有一些零散的改进:读长文本更快了,官方数据里六万四千 token 的输入读取提速约两成;带了结构化输出、工具调用的修复;还第一次让一个更大的混合专家模型,能在 24G 显存里跑起来。不过最后这条要打个折扣,它目前是 Windows 预览版、一次只服务一个请求、上下文只到 32K,而且需要另外准备一份模型产物,对我们这套 Linux 双卡暂时用不上。
但它也明说了,这是一次破坏性升级。大约十五个老的启动参数被直接删掉了,包括我们一直在用的一个控制长文本并发的开关;还有一个查询接口被移除,监控指标也整体改了名。它的原则是,如果你传了已经被删掉的参数,程序会当场报错退出,而不是默默按别的行为跑。

升级这件事本身

因为参数被删,升级就不是换个文件那么简单,必须先把启动脚本改干净。
我们原来为了传那个被删的参数,自己维护了一个包装脚本,每次升级都要重新生成。这一版那个参数整个没了,官方又自己暴露了一批新的开关,所以那个旧脚本直接弃用,改回官方脚本;只剩下一个官方没暴露的开关,我们用一个几行的通用小脚本在启动时补上,附录会讲,总的来说要维护的东西比过去少了。这次我们还顺手做了彻底的清理:删掉旧版本的二进制和旧缓存,重新拉了引擎代码,模型产物和容器镜像都核对过、继续复用。
这里有两个容易踩的坑,记一下。第一,模型文件和引擎版本必须配对,对不上轻则报错、重则直接启动失败,我们是逐一核对哈希确认没换才敢复用的。第二,这套引擎的 Linux 版本要的是较旧一代的 CUDA 运行时,最新一代的 CUDA 反而对不上,所以我们沿用了原来的运行镜像,没有盲目追新。
改完之后,两张卡重启,我们发了几个请求确认都正常。会话缓存那套也确实生效了:一段一万四千字的提示词,冷启动要读五秒多,运行中再问只要零点一秒;把容器重启之后,它从磁盘里把会话恢复回来不到一秒,再问同样的内容还是零点一秒出头。我们还埋了一个暗号做检索题,重启前后两次的答案逐字一致,说明这个缓存没有把输出搞坏。

真正的收益,在写代码上

升级到新版之后,我们发现默认档位其实有两种玩法。一种是我们一直在用的 mtp,胜在能同时服务两个请求,上下文能顶满;另一种是 dflash2,单次请求更快,而且只有它才能开启刚才说的复制型草稿。
我们把编码那张卡切到 dflash2,做了同一套基准测试,三组负载各自反映一种真实工作:写一段新代码、把一个文件改好后原样返回、以及解释一段概念。下面的数字里,dflash2 那一列已经是后文调过上下文之后的最终形态,结果是这样的。

负载 mtp(两个并发) dflash2 加复制草稿(单个并发)
写新代码 155.7 字/秒 187.3 字/秒
改文件并原样返回 247.1 字/秒 479.2 字/秒
解释概念 103.4 字/秒 129.0 字/秒

第二行是最有说服力的。让模型修改一个文件、再把整段代码原样写回来,正是复制型草稿的主场,速度接近翻倍。写新代码和解释概念则是顺带受益,也多了两成上下。这份提速里,一部分其实来自并发从两个降到一个,我们没把它单独拆开;但即便抛开这点,复制型草稿的贡献也是主要的。

质量上我们不敢只看速度,照例做了长文检索的抽查,埋进去的暗号两种配置都能准确答出。

上下文掉了一大截,我们把它抠了回来

天下没有白拿的好处。切成 dflash2 之后,上下文从二十多万直接掉到了十五万六千,而且并发从两个变成了一个。原因不复杂:dflash2 要多加载一套草稿权重,占的显存更多,能留给上下文的就少了;而编码这张卡的模型本身又比通用版重,雪上加霜。

对一个要读长文件的编码助手来说,十五万六千不算小,但比起原来的二十六万还是缩水明显,我们不接受,于是开始找办法把上下文要回来。最后叠了两个杠杆,效果出乎意料。

先是读文档的分块大小。引擎默认用一块四千多 token 的块来做预填充,这样读取更快,代价是一大块显存工作区。把它调小一档,上下文立刻多出约一万五千。

接着是一个更关键的发现。我们拆开模型文件看它的内部构成,发现编码这张卡的模型,它负责把词映射成向量的那部分权重,存的是精八位,而通用版存的是精四位。同一个引擎提供了把这块压到精四位的转码开关,官方说它几乎不损失质量。这一压,权重从十八点三 G 降到了十七点七 G,省下的显存直接换成了上下文,一下子就多出了约三万七千。

配置 权重 上下文
dflash2 默认 18.3 G 155,648
加上小分块 18.3 G 171,008
加上权重转码 17.7 G 207,872

两步下来,上下文从十五万六千拉回到二十万七千,把丢掉的那部分找回了一半。代价只有一个,就是那个转码和分块调整,都属于启动参数,改起来没有成本。

还有一步我们没能做。理论上输出头那块权重也能压,能再省一点显存,但引擎明确禁止在 dflash2 下做这件事,它读那份权重的方式不一样。所以二十万七千,基本就是这套组合在这一张卡上的上限。想要完整的二十六万,就还得回到 mtp,牺牲速度。

我们最终采用的方案

折腾完,两张卡的定位更清楚了。

通用那张卡维持原样,mtp、两个并发、上下文二十六万,负责需要长上下文和通用能力的一切。编码那张卡换成 dflash2 加复制草稿,配上小分块和权重转码,上下文二十万七千,单并发,专门吃写代码这碗饭。

两张卡都顺带开了一个新功能:当模型的思考陷进重复的段落里打转时,让它把这段思考收住、直接作答,官方实测吞吐损失不到百分之一。

要说这套方案适合谁,我觉得是这样。如果你的用法是单人为主、偶尔一两个助手,而且编码是高频场景,那这套调优的收益非常直接,改文件这类活儿差不多快一倍。如果你经常需要同时跑好几个长任务,或者动辄要喂进去二十多万字的材料,那 mtp 的并发和满上下文仍然更稳,编码的提速就只能放弃。两者各有所长,没有一边全赢。

附:可复现的参数与测试说明

编码卡这一套,核心就是把几句话告诉启动脚本。用引擎自带的启动器,关键的环境变量大致是:指定 spec 为 dflash2、草稿数七、预填充分块设成两千零四十八、并打开权重转码。因为启动器没有直接暴露那个权重转码开关,我们用了一个极小的通用包装脚本,在启动时把这一项追加进去,除此之外没有改动引擎的任何文件。

需要说明的是,这套参数是围绕我们这张具体的模型产物和这张卡抠出来的,换一个模型产物,权重的大小和存储格式会变,能拉到的上下文也就不一样。上下文达到多少,是由引擎在启动时按显存自动决定的,我们请求的是二十六万,实际能装多少它自己算,多出来的显存才分给上下文。

除文中标注”官方”的数字外,所有速度与上下文数字都是本地实测,测试在同一台机器、同一张卡、同一套提示词下完成。质量方面做了长文检索抽查,重启前后、改造前后答案一致。这套引擎更新很快,参数也时有增删,跨版本升级前,务必先看它的破坏性变更清单再动手。


皖ICP备2025105865号-2|皖公网安备34010402704739号