RTX 4090 本地运行 Qwen 27B:一次 llama.cpp 性能调优实测

模型在本地跑起来之后,我最想知道的是:这张 RTX 4090 还能不能更快?调整 batch、换 KV 缓存精度,究竟有没有实际收益?

在本地观察 llama-server 日志和显存,再用 llama-bench 做参数对照等对比后,最终选定的日常配置是 batch=1024、ubatch=512、Q8 KV、Flash Attention、16K 上下文、单并发。

在已测试条件下,输入处理约 3300 tokens/s,短生成约 47 tokens/s;实际一次 8208 tokens 的长回答平均 43.35 tokens/s。提高 ubatch 对输入处理有收益,换成 F16 KV 则没有明显提速。

这是我的个人机器上的参数筛选记录,不是不同显卡或不同模型的横向评测,也没有证明已经达到硬件极限。 本人也只是刚开始捣鼓这些,如果谁还有更好的优化或者测试方案,也可以告诉我。

1. 测试环境与模型身份

项目本次环境
测试日期2026-10-18
系统Windows 11
显卡NVIDIA GeForce RTX 4090,24GB
系统内存32GB
推理框架llama.cpp,CUDA 后端
benchmark 中显示的模型qwen35 27B Q4_K - Medium
参数量27.32B
benchmark 显示的模型大小15.32GiB
长上下文测试截图中的构建620d225c(11669)
使用场景个人聊天、小说与代码生成与长文本处理

我下载的模型称是 Qwen3.8-27B;但本次截图中的架构标识为 qwen35。这个可能是衍生模型可能沿用基础架构名称(具体不是很清楚)。

2. 指标简介

本次主要看两类速度:

  • pp(prompt processing):处理输入的速度。长提示词、小说前文和设定资料主要影响这一阶段。
  • tg(text generation):生成后续 token 的速度,更接近持续输出的体验。

pp2048 表示处理 2048 tokens 的输入测试,tg256 表示生成 256 tokens 的测试。本文命令使用 -p 2048 -n 256 时,pp 和 tg 是分别进行的测试,不能理解成“每次 tg 都先读入同一段 2048-token 输入”;如需联合测试,应参考官方文档中的 -pg。

-d 8192 用于先填充上下文,再测该深度下的性能。每组 -r 3 重复三次,表中 ± 是工具报告的标准差,不是置信区间。llama-bench 不包含分词与采样时间,因此它不能直接代表客户端完整请求耗时。

另外,token 不等于汉字。本文所有速度都保留 tokens/s 单位。

第一轮:实际聊天是否稳定

先观察已经启动的服务。持续输出日志中,前段累计生成速度约为 40~43 tokens/s,最近 3 秒速度约为 40~47 tokens/s。

第一轮:持续生成速度日志

一次完整长回答的最终日志为:

项目实测结果
输入 token 数381
输入处理耗时600.22ms
输入处理速度634.76 tokens/s
输出 token 数8208
输出耗时189339.86ms,约 189.34 秒
平均输出速度43.35 tokens/s
日志中的 total time189940.08ms,约 189.94 秒

第一轮:实际请求完整耗时及后续请求日志

输出后段的最近 3 秒速度约为 39.7 tokens/s。整体没有突然崩塌式掉速,不过它是一条真实请求,不能用于隔离某个参数的影响。

同一张图后面的请求显示约 2425 tokens/s 的输入处理进度,但它是另一条请求,存在不同输入长度和缓存状态,不能与前面的 634.76 tokens/s 直接计算提升倍数。

显卡状态如下:

项目截图值
GPU 利用率93%
专用 GPU 内存17.4 / 24GB
共享 GPU 内存0.2 / 15.9GB
GPU 温度69℃

第一轮:RTX 4090 负载、显存与温度

当时专用显存约有 6.6GB 余量,可以继续尝试参数对照。共享显存的 0.2GB 本身不能证明显存溢出;任务管理器显示的 93% 利用率也不能证明算力或显存带宽已经跑满。

这一轮没有保存完整启动参数,故只作为实际运行参考,不作为严格的优化前基线。

第二轮:先取得统一 benchmark 结果

测试前停止 llama-server,避免两份模型同时竞争显存和计算资源。以下 PowerShell 命令在 llama.cpp 目录执行,模型路径替换为实际文件:

Powershell
$modelFile = "F:\AI\models\你的模型.gguf"

.\llama-bench.exe `
    -m $modelFile `
    -ngl 99 `
    -fa on `
    -ctk q8_0 `
    -ctv q8_0 `
    -b 2048 `
    -ub 512 `
    -p 2048 `
    -n 256 `
    -r 3

本轮固定 CUDA、请求 GPU 卸载层数 99、Flash Attention 与 Q8 KV,取得一个统一测试起点。

batchubatch输入处理 pp2048生成 tg256
20485123336.12 ± 76.5947.82 ± 0.19

单位均为 tokens/s。

第二轮:2048/512 单组 benchmark

这组结果不能与第一轮的长回答直接相减,看起来提速了约 10%。两者的上下文、生成长度和测试开销都不同。

第三轮:batch 与 ubatch,哪一个更有用

两个参数容易混淆:batch-size 是逻辑批量上限,ubatch-size 是实际计算的微批量。增大它们主要是探索输入处理效率,同时也可能增加运行时内存需求。

本轮保持其他显式参数不变,只比较:

Powershell
.\llama-bench.exe `
    -m $modelFile `
    -ngl 99 `
    -fa on `
    -ctk q8_0 `
    -ctv q8_0 `
    -b 1024,2048 `
    -ub 256,512 `
    -p 2048 `
    -n 256 `
    -r 3
batchubatchpp2048,tokens/stg256,tokens/s
10242563063.43 ± 3.2046.18 ± 0.80
10245123298.15 ± 22.1747.32 ± 0.19
20482563019.81 ± 39.8947.70 ± 0.18
20485123297.65 ± 40.5247.59 ± 0.31

第三轮:batch 与 ubatch 四种组合

ubatch 从 256 增到 512:输入处理约快 7.7%

固定 batch=1024:

Text
(3298.15 / 3063.43 - 1) × 100% ≈ 7.66%

这是本轮最明确的收益。固定 batch=2048 时,同样能看到 ubatch=512 的输入处理更快,方向一致。

batch 从 1024 增到 2048:没有观察到输入处理收益

固定 ubatch=512,输入处理为 3298.15 与 3297.65 tokens/s,几乎相同。因此日常选择较小的 batch=1024 即可。

生成速度约在 46~48 tokens/s,不能把这几行的全部差异都归因于参数。测试没有随机化执行顺序,也没有逐轮记录 GPU 时钟与功耗。尤其 tg 的结果不能作为“大 batch 必然加速单人逐字输出”的证据。

本轮选择:batch=1024、ubatch=512。这是已测组合中的实用取舍,不是穷举后的全局最优值。

6. 第四轮:已有 8K 上下文时会不会掉速

小说场景会不断积累历史,空上下文跑得快还不够。因此增加深度对照:

Powershell
.\llama-bench.exe `
    -m $modelFile `
    -ngl 99 `
    -fa on `
    -ctk q8_0 `
    -ctv q8_0 `
    -b 1024 `
    -ub 512 `
    -d 0,8192 `
    -p 2048 `
    -n 256 `
    -r 3
测试空上下文已有 8192 tokens变化
pp20483358.66 ± 53.223083.06 ± 29.53下降约 8.2%
tg25647.22 ± 0.3646.72 ± 0.03下降约 1.1%

单位为 tokens/s。

第四轮:Q8 KV 的 0/8K 深度对照

本次 8K 深度下,输入处理有一定下降,生成速度则保持得较稳定。这支持当前配置用于该长度附近的实际任务。

F16 KV 能不能进一步提速

Q8 KV 的主要价值是节省缓存占用;它不是保证提速的开关。既然显存还有余量,我就把 K/V 都换成 F16,对照一次。

Powershell
.\llama-bench.exe `
    -m $modelFile `
    -ngl 99 `
    -fa on `
    -ctk f16 `
    -ctv f16 `
    -b 1024,2048 `
    -ub 256,512 `
    -p 2048 `
    -n 256 `
    -r 3
batchubatchF16 pp2048F16 tg256
10242563025.68 ± 59.7647.81 ± 0.24
10245123345.68 ± 8.2547.57 ± 0.49
20482563037.01 ± 27.6448.08 ± 0.09
20485123376.37 ± 37.0647.64 ± 0.81

单位为 tokens/s。

第五轮:F16 KV 四种组合

以最终选择的 1024/512 配置比较,并采用第四轮的 Q8 空上下文结果:

指标Q8 KVF16 KVF16 相对变化
pp20483358.663345.68约 -0.4%
tg25647.2247.57约 +0.7%

两个值来自不同轮次,只能作近似对照。若采用第三轮的 Q8 结果,则差异约为 +1.4% 与 +0.5%;无论选哪次已记录数据,都没有看到值得为速度切换 F16 的明显收益。

本轮没有记录 F16 显存峰值,也没有加入 -d 8192,因此没有完成 F16 的 8K 对照。测试只测速度,没有测困惑度、小说质量或长文准确率;不能据此声称 Q8 与 F16 输出质量完全相同。

最终保留 Q8 KV,原因是本次没有测出 F16 的实用速度优势,同时希望保留缓存空间余量。

8. 最终启动参数

现有脚本保留实际模型路径和程序路径,将参数数组设置为:

Powershell
$serverArgs = @(
    "--model", $modelFile,
    "--alias", "qwen-local",
    "--host", "127.0.0.1",
    "--port", "8080",
    "--n-gpu-layers", "99",
    "--flash-attn", "on",
    "--ctx-size", "16384",
    "--parallel", "1",
    "--batch-size", "1024",
    "--ubatch-size", "512",
    "--cache-type-k", "q8_0",
    "--cache-type-v", "q8_0",
    "--jinja"
)
参数最终选择的理由
GPU layers=99请求尽量将模型层放入 GPU;实际卸载结果仍以启动日志为准
Flash Attention=on本次统一使用;没有做 on/off 对照,不能量化其独立收益
ctx-size=16384日常服务的上下文预算,输入、历史与输出共用;本次没有验证填满 16K 的表现
parallel=1面向个人单请求使用;没有测试多并发吞吐
batch=1024增至 2048 没有观察到明显输入处理收益
ubatch=512相对 256,对输入处理有较一致收益
K/V=q8_0F16 短上下文测试没有明显速度优势
jinja使用模型聊天模板,属于服务功能配置,不是本轮测速得出的加速项

这些是服务参数;benchmark 的测试上下文由其测试项目和深度决定,不能把 --ctx-size 16384 视为每轮 benchmark 都验证过的条件。

9. 这次测试最终说明了什么

第一,实际有收益的是把 ubatch 从 256 提高到 512。 在 batch=1024 的对照中,输入处理提升约 7.7%;batch 进一步增大则没有显著帮助。

第二,Q8 换 F16 没有带来明显提速。 保留 Q8 是这台机器、这份模型、已测条件下的实用选择,而不是所有模型的通用定律。

第三,8K 深度的生成性能比较稳定。 Q8 KV 下 tg256 从 47.22 降至 46.72 tokens/s,约下降 1.1%。

第四,实际长回答与短 benchmark 应分开理解。 约 43 tokens/s 的真实长输出与约 47 tokens/s 的短测试都是真实记录,但不能直接用它们计算参数优化收益。

当前可以停止围绕 batch 和 KV 精度反复微调,把这套配置作为可用基线。后续如果体验仍不理想,应先确认瓶颈是首字等待、持续输出、输出过长还是内容质量,再决定下一步实验。

本次没有比较其他模型量化、推测解码、不同后端、自行编译选项或 CPU 线程,也没有保存完整模型身份与全部启动日志。因此,准确的结论是“找到了已测试组合中的合理配置”,而不是“4090 的理论最优解”。

官方参考资料

本文中的数字来自本次截图;工具含义和参数用法参考以下官方资料。命令参数应同时核对本地程序的 --help,因为主分支文档会更新。

  1. llama-bench 官方文档:测试类型、重复次数、上下文深度与输出格式

  2. llama-server 官方文档:服务参数、上下文、批量与缓存

  3. llama.cpp 官方构建说明:CUDA 等后端

  4. llama.cpp 官方发行版

感谢读到这里

日志还会继续,欢迎常来。

返回首页