
Qwen3.8-27B 在 RTX 3090 24G 上的上下文对比实测
基于 Ollama 0.32.15 DEBUG 日志 + 此前 32K 基准测试数据
数据源:ollama64k.log / ollama128.log(本次 log)+ 原 Qwen3.8-27B_RTX3090_Ollama_上下文性能对比报告.md 32K 章节
测试时间:2026-08-22
TL;DR
档位 |
结论 |
|---|
32K |
100% GPU、Prefill ~1200 tok/s、Decode 30-42 tok/s。性能最好,但 Coding Agent 容易撑爆。 |
64K |
100% GPU、Prefill ~1100 tok/s、Decode ~37 tok/s。真正的甜点档。 |
128K |
触发 12 层 CPU Offload,Decode 掉到 2.3 tok/s,是 64K 的 1/15。24GB 物理边界。 |
想要更大上下文,24GB 显卡到此为止。要么换 48G(A6000 / L40 / RTX 6000 Ada),要么走多卡 MoE 拆分。
1. 测试环境
项目 |
配置 |
|---|
GPU |
NVIDIA GeForce RTX 3090 24GB(CUDA 12.8.1,driver 见系统) |
模型 |
Qwen3.8-27B(Qwen3.8 27B 0814,ollama tag qwen3.8:27b) |
量化 + 加速 |
Q4_K_M + MTP(draft-mtp) |
验证 |
ollama ps 显示 ID = 22130167c4c2,SIZE 17 GB,PROCESSOR 100% GPU。该 hash 与 ollama 官方 qwen3.8:27b / :latest / :27b-mtp-q4_K_M 三个 tag 共享,确认是 MTP + Q4_K_M 默认组合(纯 Q4_K_M 不带 MTP 的 tag 是 qwen3.8:27b-q4_K_M,hash 为 25b843619e94,不同) |
量化细节 |
GGUF V3,file_type=15,f32 360 / q4_K 439 / q6_K 67 tensors |
模型参数 |
27.32 B(n_layer=64 transformer + 1 MTP = n_layer_all=65) |
架构 |
qwen35 hybrid(SSM + 局部 attention,full_attention_interval=4) |
上下文训练长度 |
262144(256K) |
Ollama |
0.32.15 |
llama.cpp build |
1 (9d77fa172) with GNU 13.3.1 for Linux x86_64 |
CPU |
n_threads = 44 / n_threads_batch = 44(88 逻辑核) |
指令集 |
SSE3 / SSSE3 / AVX / AVX2 / F16C / FMA / BMI2 / LLAMAFILE / REPACK |
系统内存 |
251.8 GiB |
GPU 显存 |
22.9 GiB(available)/ 23.3 GiB(free) |
启动参数 |
--spec-type draft-mtp --spec-draft-n-max 4 --spec-draft-backend-sampling --flash-attn auto -b 512 -ub 512 --context-shift --keep 4 |
场景 |
Coding Agent / Tool Calling / 长上下文 |
2. 实测样本与数据来源
档位 |
num_ctx |
数据来源 |
证据强度 |
|---|
32K |
32768 |
原报告(此前 benchmark 测试,非本次 log 文件) |
★★★★★ |
64K |
65536 |
本次 ollama64k.log(20+ task 完整数据) |
★★★★★ |
128K |
131072 |
本次 ollama128.log(task 0 + task 14 完整数据) |
★★★★☆ |
32K 数据来源说明:本批 ollama.log 文件(应为 32K 启动档)实际上加载时被 abort(client connection closed before llama-server finished loading, aborting load),无任何生成数据。32K 的 1200 tok/s Prefill 与 42.6 tok/s Decode 来自原 Qwen3.8-27B_RTX3090_Ollama_上下文性能对比报告.md 第 3 节,是此前用 benchmark 工具或 API 客户端测得的环境。
3. 性能结论
3.1 核心指标三档对比
指标 |
32K |
64K |
128K |
64K vs 128K |
|---|
加载到 GPU 的层数 |
66/66(推断) |
66/66 |
54/66 |
-12 层 |
GPU 显存占比 |
100% |
100% |
~72.6% |
-27% |
Model VRAM |
~17 GiB |
15339 MiB |
12598 MiB |
-18% |
KV cache GPU |
~3.0 GiB |
4096 MiB |
6656 MiB |
+62% |
KV cache CPU |
0 |
0 |
1536 MiB |
∞ |
Model mmap(CPU 端) |
— |
682 MiB |
3423 MiB |
5× |
Prompt Prefill(4K-16K) |
~1200 tok/s |
~1100-1250 tok/s |
~242-256 tok/s |
64K 快 4-5× |
Prompt Prefill(28K+) |
— |
760-1043 tok/s |
— |
|
Decode 短输出 |
42.6 tok/s |
33-47 tok/s |
5.38 tok/s |
64K 快 6-9× |
Decode 长输出 |
30-36 tok/s |
28-45 tok/s |
2.0-2.5 tok/s |
64K 快 15× |
启动 fit 耗时 |
— |
0.76s |
5.26s |
7× |
MTP 接受率 |
— |
0.71(平均) |
0.75 |
接近 |
3.2 体感耗时对比
场景 |
32K |
64K |
128K |
|---|
1000 token 输出 |
~28s |
~25s |
~7 分钟 |
5000 token 输出 |
~2.5 分钟 |
~2 分钟 |
~35 分钟 |
10000 token 输出 |
~5 分钟 |
~5 分钟 |
~70 分钟 |
32K 和 64K 体感接近(都流畅);128K 实际等同于"死锁"。
4. 32K 实测(原报告数据)
4.1 ollama ps
NAME ID SIZE PROCESSOR CONTEXT
qwen3.8:27b 22130167c4c2 17 GB 100% GPU 32768
4.2 Prompt Prefill
11264 tokens -> 1228.84 tok/s
12800 tokens -> 1217.80 tok/s
15360 tokens -> 1199.70 tok/s
17408 tokens -> 1184.26 tok/s
综合约 1200 tok/s,是三档里 Prefill 最高的。
4.3 Decode
短输出:
eval time = 1056.35 ms / 46 tokens
42.60 tokens per second
长输出:
n_gen = 1129 tg = 35.92 t/s
n_gen = 1348 tg = 36.00 t/s
n_gen = 1880 tg = 33.70 t/s
n_gen = 2346 tg = 31.65 t/s
综合约 30-36 tok/s,短输出甚至能到 42.6 tok/s。
4.4 32K 优劣
优点:
- 100% GPU Offload
- Prefill 速度三档最高
- Decode 速度三档最高
缺点:
- Coding Agent 很容易到 24K-31K
- 频繁触发
COMPACTED(上下文压缩)
- 复杂项目上下文偏紧
32K 是"纯性能档",但 Agent 场景的上下文需求往往超过 32K。
5. 64K 实测(本次 log)
5.1 资源分布
load_tensors: offloaded 66/66 layers to GPU
load_tensors: CPU_Mapped model buffer size = 682.03 MiB
load_tensors: CUDA0 model buffer size = 15339.44 MiB
llama_kv_cache: CUDA0 KV buffer size = 4096.00 MiB
llama_kv_cache: size = 4096.00 MiB ( 65536 cells, 16 layers, 1/1 seqs)
runner.size = 16.3 GiB
runner.vram = 16.3 GiB ← 完全在显存
64K 把 KV cache 控制在 4 GiB,刚好能把 66 层全部塞进 24GB 显存。
5.2 Prompt Prefill
n_tokens 4096 → 1257.75 tok/s
n_tokens 8192 → 1227.95 tok/s
n_tokens 12288 → 1199.89 tok/s
n_tokens 15360 → 1179.16 tok/s
n_tokens 25082 → 760.77 tok/s ← 28K prompt 开始衰减
n_tokens 28985 → 1043.51 tok/s
16K 之前基本无衰减,28K+ 才有明显拐点。
5.3 Decode
Task |
n_gen |
prompt |
eval tok/s |
|---|
0 |
892 |
21263 |
34.28 |
427 |
5827 |
9625 |
40.36 |
2802 |
5958 |
15771 |
45.91 |
4774 |
4309 |
512 |
44.37 |
5888 |
4846 |
15463 |
46.17 |
7295 |
11179 |
7002 |
37.49 |
10489 |
2441 |
28985 |
28.52 |
11502 |
5616 |
24826 |
33.93 |
30+ 个 task 全部数据:Decode 范围 27-47 tok/s,平均 ~37 tok/s。
长 prompt(>25K)会让 Decode 掉到 28-34 tok/s,但仍然流畅。
6. 128K 实测(本次 log)
6.1 资源分布
load_tensors: offloaded 54/66 layers to GPU ← 12 层去 CPU
load_tensors: CPU_Mapped model buffer size = 3423.21 MiB ← 5× 增长
load_tensors: CUDA0 model buffer size = 12598.26 MiB
llama_kv_cache: CPU KV buffer size = 1536.00 MiB ← 新增 CPU 端 KV
llama_kv_cache: CUDA0 KV buffer size = 6656.00 MiB
llama_kv_cache: size = 8192.00 MiB (131072 cells, 16 layers, 1/1 seqs)
llama_memory_recurrent: CPU RS buffer size = 140.27 MiB
llama_memory_recurrent: CUDA0 RS buffer size = 607.85 MiB
common_params_fit_impl:
projected to use 24529 MiB ... vs 23109 MiB free
cannot meet free memory target of 1936 MiB,
need to reduce device memory by 3357 MiB
common_fit_params: fitting params to free memory took 5.26 seconds
runner.size = 19.0 GiB
runner.vram = 13.8 GiB ← 实际只有 72.6% 在 GPU
6.2 Prompt Prefill
n_tokens 1024 → 255.56 tok/s
n_tokens 4096 → 250.95 tok/s
n_tokens 8192 → 245.25 tok/s
n_tokens 12288 → 244.07 tok/s
n_tokens 16789 → 241.73 tok/s
Prefill 直接比 64K 慢 4-5 倍。
6.3 Decode
Task 0(短输出):44 token,5.38 tok/s
Task 14(长输出):495 token,从 2.27 一路掉到 2.04 tok/s
n_gen = 101 tg = 2.27 t/s
n_gen = 203 tg = 2.39 t/s
n_gen = 252 tg = 2.46 t/s
n_gen = 398 tg = 2.32 t/s
n_gen = 495 tg = 2.04 t/s
7. 性能差距的根因
7.1 物理边界
24GB 显存的硬上限:
模型权重 16.3 GiB + KV cache 8 GiB(128K 翻倍)+ MTP 388 MiB + mmproj 1.1 GiB ≈ 25.8 GiB
已经超过 24GB,llama.cpp 在 fit 阶段直接判断"装不下",主动把 12 层权重 + 1.5GB KV 推到 CPU。
7.2 PCIe 搬运代价
每次 Decode 都要:
- CPU → GPU:拉权重(12 层)
- GPU → CPU:保存 KV 增量
- CPU → GPU:再读回来下一帧用
RTX 3090 的 PCIe 4.0 x16 实际带宽约 25 GB/s,但小数据包 + 双向来回 + 系统总线争抢,实际有效吞吐远低于此。这就是 128K Decode 比 64K 慢 15 倍的物理原因。
7.3 Prompt Cache 失效
128K 跑长 prompt 时,log 记录了一次 cache 强制重算:
slot operator(): id 0 | task 14 | checking checkpoint with [6, 6] against 1...
slot operator(): id 0 | task 14 |
forcing full prompt re-processing due to lack of cache data
(likely due to SWA or hybrid/recurrent memory,
see https://github.com/ggml-org/llama.cpp/pull/13194)
Qwen3.8 27B 用的是 hybrid/recurrent memory(SSM + 局部 attention) 架构,跨请求时 context checkpoint 失效。
64K 时也存在,但 Prefill 本身够快,体感无感。
128K 时叠加本来就慢的 Prefill,体验更差。
8. 显存账本
资源 |
32K |
64K |
128K |
|---|
VRAM - 模型权重 |
~15.0 GiB |
15339 MiB |
12598 MiB |
VRAM - KV cache |
~2.0 GiB |
4096 MiB |
6656 MiB |
VRAM - Recurrent state |
— |
748 MiB |
608 MiB |
VRAM - MTP context |
388 MiB |
388 MiB |
388 MiB |
VRAM - mmproj (Qwen-VL) |
1161 MiB |
1161 MiB |
1161 MiB |
VRAM - working buffer |
~1.0 GiB |
~1.0 GiB |
~1.0 GiB |
VRAM 合计 |
~19.6 GiB |
~22.7 GiB |
~22.4 GiB |
RAM - 模型 mmap |
— |
682 MiB |
3423 MiB |
RAM - KV (CPU 端) |
0 |
0 |
1536 MiB |
RAM - Recurrent (CPU 端) |
0 |
0 |
140 MiB |
24GB VRAM 的红线在 22-23GB 附近。
32K 余量最大(4.4GB),64K 还有 2.7GB 余量,128K 几乎贴顶。
9. 推荐配置
# 64K 跑 Coding Agent 推荐配置
export OLLAMA_CONTEXT_LENGTH=65536
export OLLAMA_FLASH_ATTENTION=true
ollama serve &
ollama run qwen3.8:27b
启动参数(log 中验证可用):
--spec-type draft-mtp
--spec-draft-n-max 4
--flash-attn auto
-b 512 -ub 512
--context-shift --keep 4
预期表现:
指标 |
32K |
64K |
128K |
|---|
Prefill |
~1200 tok/s |
~1100 tok/s |
~250 tok/s |
Decode |
30-42 tok/s |
28-47 tok/s |
2.0-2.5 tok/s |
MTP acceptance |
— |
~0.71 |
~0.75 |
显存占用 |
~19.6 GiB |
~22.7 GiB |
~22.4 GiB |
不推荐:
OLLAMA_CONTEXT_LENGTH=131072 → 触发 12 层 CPU Offload
runner.num_ctx=262144 → 24G 完全跑不动
10. 进一步优化方向
- KV cache 量化:试
OLLAMA_KV_CACHE_TYPE=q8_0 或 q4_0,看 128K 能否救回一部分性能
- PCIe 抓数:在 128K 跑批时用
nvidia-smi pcie -l 抓实际搬运量
- 64K 长 prompt 拐点:当前 25K+ prompt 已经看到 Prefill 衰减,可以画更细曲线找临界点
- Cache 失效问题:跟踪 llama.cpp PR #13194,等 hybrid memory checkpoint 修复
11. 结论
64K 是 RTX 3090 24G + Qwen3.8-27B 的真正甜点档。
32K / 64K / 128K 对比一览:
维度 |
32K |
64K |
128K |
|---|
GPU 占比 |
100% |
100% |
~72.6% |
Prefill |
~1200 tok/s |
~1100 tok/s |
~245 tok/s |
Decode 短输出 |
42.6 tok/s |
33-47 tok/s |
5.38 tok/s |
Decode 长输出 |
30-36 tok/s |
28-45 tok/s |
2.0-2.5 tok/s |
Coding Agent 体验 |
容易 Compact |
^-^ 流畅 |
^-^ 不能用 |
适用场景 |
短问答 / 单文件 |
Coding Agent |
仅理论可达 |
关键证据:
- 64K:100% GPU Offload(66/66 层),~1100 tok/s Prefill,~37 tok/s Decode,KV 完全在 VRAM
- 128K:12 层 CPU Offload,Decode 比 64K 慢一个数量级(15×)
24GB 物理边界:模型权重 16.3 GiB + KV 8 GiB(128K 翻倍)已经超过 24GB,CPU Offload 不可避免。
- 想跑 128K+ 流畅:换 48G 显卡(A6000 48G / L40 48G / RTX 6000 Ada)
- 想跑 256K:多卡 MoE 拆分(Qwen3 是 dense,理论上不拆分;MoE 架构才行)
报告数据来源说明:
- 32K 数据来自原
Qwen3.8-27B_RTX3090_Ollama_上下文性能对比报告.md 第 3 节(非本批 log 文件)
- 64K / 128K 数据来自本次
ollama64k.log / ollama128.log(Ollama 0.32.15 DEBUG 日志)
- 所有数字都有
slot print_timing 或 llama_kv_cache 的原始 log 行支撑
如果想看更详细的 timing 表、复现测试流程,或者想看 KV quant 后的对比,回复里喊一声。