Qwen 在 RTX 3090 上的编码提速与长上下文实测
这几天,我继续在一张 24GB RTX 3090 上调 Qwen3.8-27B,把编码任务中的生成速度从原配置的约 33 token/s 提升到了约 60 token/s。
过程中还有两个发现值得记下来:一道反复失败的题,后来发现测试本身有缺陷;一个生成速度更高的配置,反而多花了三分钟才交付代码。
目前,我优先选 IQ3_S 量化权重、Q8 KV cache 和 MTP4。128K 总上下文用于常见修复任务;220K 已经跑过长输入,但完整编码验证还没完成。下面是这些选择的依据。
写作说明:本文基于已保存的本地实验记录,由 AI 辅助起草并经实验者审阅。以下结果及其限制均对应这些记录。
我实际测了什么
上一篇文章主要解决输出预算和思考设置的问题,最终达到 23/24 次交付通过。这里的 24,是八个任务各跑三次,不是 24 道不同题。后来用来筛查参数的八次测试,则是每个任务只跑一次。
这八个任务有六个 Python、两个 TypeScript,涉及缓存、数据库事务、分块数据流、路径处理、流水账、构建依赖、异步并发和分页。七个是自建修复任务,另一个是在固定版本的 boltons 库中植入故障。Agent 要读代码、修改文件、运行检查,再完成交接;只说一句“测试通过”不算成功。
我把代码通过独立检查记为“功能通过”。还要正常结束、完成自检并留下交接说明,才记为“交付通过”。这是一套小型编码修复测试,能帮助我选配置,不能代表大型真实仓库里的所有工作。
下文的 token/s 衡量生成阶段:总生成 token 除以总解码时间,包含思考和工具调用语法,不包含输入处理。完整任务还要读文件、运行测试、等待工具,所以生成速度和交付速度要分开看。
为什么我暂时保留 IQ3
原来的 Q4_K_M 权重文件约 15.66 GiB。后来选的 ISTA-DASLab GSQ-RCO IQ3_S,带 MTP 预测模块,约 11.29 GiB。更小的权重文件给缓存和运行时缓冲区留下了更多显存。
这里有两个容易混淆的压缩设置:IQ3 压缩模型权重,Q8 KV 以八比特格式压缩推理时保存的注意力缓存。它们可以同时使用。IQ3 的名字也不意味着每个权重都恰好是三比特;这份模型会对不同张量分配不同精度。
我还试了 Bartowski 的 IQ4_XS,并在本地加入 Q4_0 格式的 MTP 预测模块。下面这轮对照,每组都是八个任务各跑三次,使用 128K 总窗口、32K 单次输出上限和 xhigh 思考设置。
| 配置 | 生成速度 | 交付通过 |
|---|---|---|
| 原 Q4_K_M,MTP 关闭 | 33.29 token/s | 23/24 |
| GSQ-RCO IQ3_S,MTP3,Q8 KV | 59.87 token/s | 21/24 |
| Bartowski IQ4_XS,本地 MTP2,Q8 KV | 62.36 token/s | 22/24 |
IQ3 组合的生成速度比原 Q4 组合高约 80%,但这里同时换了权重和投机解码,不能把提升全部归因于 IQ3。Q4 和 IQ3 的控制结果也来自较早运行,而非同一时间随机交错采集。
表中保留的是旧版测试分数,其中有后面要讲的 Ledger 测试缺陷。这些历史结果还没有全部重新评分,不能拿它们宣布质量完全不下降,也不能据此确定最终质量排名。
IQ4 在另四个任务各跑三次的确认对照里,与 Q4 都达到 11/12 次功能及交付通过。不过,最后一轮 IQ4 与 IQ3 的新随机种子(seed)对照,又给了我一个保留 IQ3 的理由:IQ4 生成快了 7.8%,却只交付 6/8,IQ3 是 7/8;八次任务的总耗时还多了约 2.1%。IQ4 的 wallet 答案出现了实际的溢出处理问题。
这不足以断言 IQ4 总体更差,但也没有给我充分理由直接替换 IQ3。
其他尝试也有类似情况:减少 CPU 线程、改变 CUDA 等待方式、叠加 ngram 投机,都没有带来一致的速度收益;F16 缓存在部分短输入中更快,代价是更多显存。更小的 IQ3_XXS 也有短测收益,但部分编码跟进结果没有支持直接替换。短测适合筛选候选,最终还是要让 agent 做题。
MTP4 在这批编码任务中最快
MTP 的做法是先提出几个后续 token,再由主模型验证。接受的草稿越多,就越有机会减少主模型逐个生成的开销。
但草稿不是免费的。本地模型只有一个 MTP 预测模块,深度增加时会反复调用它;后面的草稿被拒绝,也会浪费这部分工作。MTP4 表示最多提出四个草稿 token,并不保证每轮接受四个。
我固定 IQ3_S、Q8 KV、128K 总窗口和 64K 单次输出上限,对 MTP2 到 MTP6 各跑八个编码任务,每题一个共同 seed,总共完成 40 次尝试。
| 最大草稿数 | 生成速度 |
|---|---|
| 2 | 57.98 token/s |
| 3 | 60.72 token/s |
| 4 | 61.31 token/s |
| 5 | 58.08 token/s |
| 6 | 56.37 token/s |
MTP4 比 MTP2 快约 5.7%,继续加深没有收益。短输入筛查曾偏向 MTP2,实际编码对照则偏向 MTP4。这也是我现在优先用 MTP4 的依据:它更贴近我要跑的工作。
这是八个熟悉任务、每题一次的结果,温度条件和运行顺序也不完全一致。它支持当前机器上的选择,还不足以给所有模型和 GPU 指定一个通用的最佳深度。
Ledger 的失败为什么让我重新检查测试
Ledger 是一个处理 CSV 流水账和金额的任务。它反复失败,很容易让人想到“是不是需要更大的上下文”。但诊断出来的是两种不同问题。
第一次,单次回复真的被输出上限截断了。我只把上限从 32K 提到 64K,保留 128K 总窗口和其他设置。新尝试的最长回复写到 40,612 token,最终通过功能和交付检查。实际最长序列只有约 73K,128K 窗口仍够用。代价是任务耗时从约 628 秒增加到 1,140 秒。
后来的 MTP 深度对照里,五份 Ledger 答案又都失败了,这次却没有耗尽输出或上下文。真正的问题是:测试用来模拟文件读取失败的替身,没有实现正常文件和标准输出的完整接口。有的合理代码还没碰到预期的读取异常,就撞上了模拟对象的缺陷。
修正模拟接口后,五份未修改的答案都从 12/13 变成 13/13 验收通过。故意不处理读取异常的代码仍然失败,说明错误处理的要求没有被放宽。
我随后建立新测试版本,重新评分 MTP4 那组八份已有答案。功能和交付结果由 7/8 变成 8/8,没有重新生成答案。这是修正误判后的结果,不是模型突然变强了;其他历史对照也不会自动获得新分数。
这件事改变了我解释失败的顺序:先看回复有没有截断,再看代码错在哪里,也要检查测试是否真的测到了它声称要测的行为。
220K 能放下长输入 但还没验证完长任务
上下文窗口由输入和输出共享,这里的 K 按 1,024 token 算。170K 输入加 50K 输出,需要 220K 总窗口;192K 输入加 64K 输出,需要 256K。提高最大输出上限,也不能忽略总窗口的容量。
IQ3_S+Q8 KV+MTP4 在 220K 总窗口下,已经处理过 179,532 token 输入和短输出,整张 GPU 的显存峰值约 22.80 GiB。256K+MTP4 则在启动时分配显存失败。关闭 MTP、减小 batch 后,256K 配置跑通了下面的迁移实验。
为了看长窗口有没有用,我做了一道跨服务 schema 迁移题:12 个服务的新规格散落在长材料里,还混有过期规格。三组都关闭 MTP,只改变输入提供方式。
| 输入方式 | 实际输入 token | 独立检查通过 |
|---|---|---|
| 256K 窗口,完整材料 | 179,532 | 198/198 |
| 128K 窗口,预先筛选相关文件 | 6,383 | 198/198 |
| 128K 窗口,简单截取首尾 | 54,755 | 138/198 |
完整材料保留了所需信息,简单截取首尾丢掉九个服务的规格。提前选好相关文件也能通过,而且输入处理加生成只用了约 712 秒,完整材料约 1,583 秒。
所以,大窗口对避免丢信息有帮助;能准确筛选材料时,小窗口也可以完成任务并节省时间。这里是 一道题、一个 seed、198 个检查,不是 198 道编码题,也没有验证 agent 能否自己检索到全部相关文件。
220K 的真实编码对照只完成了 2/8。cache 和 wallet 都通过,第三题运行时 CPU 温度采样达到 93.25°C,触发设为 92°C 的保护,其余六题没有有效评分。也还没有测完 170K 输入后连续生成完整 50K 输出的路径。
其中 wallet 特别说明问题:220K 下生成速度比 128K 高约 6.4%,但生成量从约 3.5 万增到 4.6 万 token,任务耗时从 654 秒增到 835 秒。快一点地生成更多内容,仍可能晚三分钟交付。这次观察不能证明大窗口让模型变啰嗦,但它提醒我,优化目标应包括完成时间和正确率。
DFlash2 在这张 3090 上暂时没有速度优势
DFlash也让主模型验证草稿,不过它用一个单独的小模型,并行提出一整块 token;本地 MTP 则逐步提出草稿。DFlash2进一步改进了草稿生成。这种机制值得测试,收益仍要看本地硬件和工作负载。
我在同一个 IQ3_S 目标模型、Q8 主缓存和 220K 总窗口下,分别运行 MTP4 与 DFlash2,启用后者时关闭 MTP。约 8K、32K、179K 的三种相同冷输入各测一次,生成长度分别是 512、512、128 token。
这轮 DFlash2 的生成速度低约 3% 到 6%,显存峰值约 23.33 GiB,比 MTP4 多约 540 MiB。最长输入那次完整请求却略快,约 303 秒对 307 秒,因为完整请求还包含输入处理。
因此,我目前会继续用 MTP4。这个短测没有覆盖长输出和完整编码任务,也没有回答 DFlash2 的编码质量如何;它只说明这组本地设置没有表现出生成速度优势。
我现在会怎么配
对于这批常见修复任务,我的首选是 GSQ-RCO IQ3_S+Q8 KV+MTP4,128K 总窗口,64K 单次回复输出上限。输入和输出仍共享窗口。temperature 保持 1.0,开启思考,reasoning effort 为 xhigh。
参考运行栈是 llama.cpp b11146、CUDA 12.8、OpenCode 2.0.20,单并发、Flash Attention、模型层全部放到 GPU。需要长输入时,再考虑 220K,并继续补完那组编码验证。
长期运行还要关注功耗和散热。早期两段接近完整的编码运行中,GPU 板卡平均功耗约 329W。这只是显卡读数,CPU、其他组件和电源损耗还没有包含在内;整机功耗需要通过插座侧测量。
这轮最实用的进展,是找到了一组约 60 token/s 的候选,并且更清楚哪些失败要改参数、哪些要改测试。下一步要回答的,是在修正测试后增加重复次数和任务覆盖,IQ3+MTP4 能否继续保住编码质量,以及 220K 能否稳定完成整组任务。
微信扫一扫分享
用微信扫描上方二维码,即可在手机端阅读或分享到朋友圈。