之前的测试发现 MoXing 和 Ollama 在 qwen3 系列模型上速度差不多,但在 omnicoder-9b 上差距很大。
稍微深入调查了一下,发现关键不仅仅在于上下文长度设置,而更应该说是在内存卸载上。
问题发现
Ollama 默认为 omnicoder-9b 使用 32768(32k)的上下文长度。查看日志:
KvSize:32768
GPULayers:32 (offloaded 32/33 layers to GPU)
model weights device=CUDA0 size="4.0 GiB"
model weights device=CPU size="1.3 GiB"
kv cache device=CUDA0 size="2.2 GiB"
total memory size="7.8 GiB"
可以看到:
- 模型权重 5.3GB,但只放了 4GB 到 GPU
- KV Cache 占了 2.2GB
- 总共用了 7.8GB,几乎耗尽了 8GB 显存
- 输出层被放到 CPU 上
这就是速度慢的原因:CPU 和 GPU 之间的数据传输成为了瓶颈。
测试方法
接下来咱们控制变量,测试了不同上下文长度下的推理速度:
测试模型:carstenuhlig/omnicoder-9b(5.3GB)
测试问题:Write a Python function to check if a string is a palindrome
上下文长度分别设置为 2048、4096、8192、16384、24576、32768
测试结果
MoXing 生成速度(tokens/秒)
| 上下文 | 生成速度 | Prompt 处理速度 |
|---|---|---|
| 2048 | 39.8 | 306.2 |
| 4096 | 40.0 | 285.0 |
| 8192 | 40.3 | 309.7 |
| 16384 | 40.4 | 307.5 |
| 24576 | 40.6 | 310.1 |
| 32768 | 40.0 | 307.7 |
Ollama 生成速度(tokens/秒)
| 上下文 | 生成速度 | Prompt 处理速度 |
|---|---|---|
| 默认(32k) | 15.6 | 615.4 |
| 2048 | 15.4 | 623.3 |
| 4096 | 15.6 | 629.6 |
| 8192 | 15.5 | 623.5 |
| 16384 | 15.6 | 622.6 |
| 24576 | 15.6 | 618.6 |
关键发现
发现一:上下文长度对生成速度影响很小
MoXing 在 2k-32k 上下文范围内,生成速度稳定在 40 t/s 左右。Ollama 也稳定在 15.5 t/s 左右。
这说明一旦模型加载完成,上下文长度对每 token 的生成时间影响很小。更大的上下文主要影响:
- 显存占用(KV Cache)
- 加载时间
- 首 token 延迟
发现二:Ollama 速度慢是因为 CPU 卸载
Ollama 默认的 32k 上下文需要 2.2GB KV Cache,加上模型权重 5.3GB,总共需要 7.5GB。
但可能是觉得 8GB 显存还要留一些给系统,所以 Ollama 把 1.3GB 模型权重放到了 CPU。
这大概就是 Ollama 只有 15.5 t/s 的原因——部分计算在 CPU 上进行。
发现三:MoXing 能充分利用 GPU
MoXing 在 32k 上下文时仍然保持 40 t/s,说明所有计算都在 GPU 上。这可能是因为:
- MoXing 用
-ngl 99强制所有层都在 GPU 上 - llama.cpp 的显存管理更高效
发现四:Ollama 的 Prompt 处理更快
Ollama 在 Prompt 处理上快了 2 倍(620 t/s vs 300 t/s)。这可能是因为 Ollama 的批处理优化更好。
速度差异对比
| 指标 | MoXing | Ollama | 差异 |
|---|---|---|---|
| 生成速度 | 40 t/s | 15.5 t/s | MoXing 快 2.6x |
| Prompt 处理 | 300 t/s | 620 t/s | Ollama 快 2x |
| 32k 上下文显存 | 全 GPU | 部分卸载到 CPU | MoXing 更高效 |
为什么 qwen3:8b 没有这个问题?
之前测试 qwen3:8b 时,MoXing 和 Ollama 速度差不多。原因是:
- qwen3:8b 只有 5.2GB,比 omnicoder-9b 的 5.3GB 略小
- Ollama 为 qwen3:8b 默认使用 4096 上下文(4k),不是 32k
- 4k 上下文只需要 ~300MB KV Cache,完全可以放进显存
查看 Ollama 日志:
qwen3:8b: KvSize:4096, GPULayers:37 (all on GPU)
omnicoder-9b: KvSize:32768, GPULayers:32 (1.3GB on CPU)
MoXing 新功能:自动上下文检测
MoXing 下一个版本就因此新增了自动上下文检测功能:
# 自动检测最优上下文(默认)
moxing serve model.gguf
# 手动指定上下文
moxing serve model.gguf -c 16384
自动检测逻辑:
- 检测可用显存
- 计算模型大小
- 留出 15% 显存余量
- 计算最大可用上下文
例如,8GB 显存运行 5GB 模型:
- 剩余显存:8 * 0.85 - 5 = 1.8GB
- 可用于 KV Cache:~1.8GB
- 每 1k 上下文约需 2MB
- 最大上下文:~900k(实际限制在 16k-32k)
实用建议
如果你有 8GB 显存:
- 7B-9B 模型:上下文可以设置到 16k-32k
- 13B+ 模型:需要部分 CPU 卸载,速度会下降
设置合理的上下文:
# 代码任务:4k 足够
moxing serve model.gguf -c 4096
# 长文档处理:16k-32k
moxing serve model.gguf -c 32768
# 让 MoXing 自动检测
moxing serve model.gguf
Ollama 用户:
Ollama 默认的 32k 上下文可能导致大模型速度下降。可以通过环境变量调整:
# 设置 4k 上下文
OLLAMA_CONTEXT_LENGTH=4096 ollama run model
# 全局设置
export OLLAMA_CONTEXT_LENGTH=16384
总结以下
这次测试揭示了上下文长度对推理速度的影响:
- 上下文本身不影响生成速度,但影响显存占用
- 显存不足会导致 CPU 卸载,速度下降 2-3 倍
- MoXing 的内存管理更高效,能充分利用 GPU
- Ollama 默认配置对大模型可能不是最优的
选择合适的上下文长度,可以在性能和功能之间取得平衡。
预览时标签不可点
Close
更多
Name cleared
微信扫一扫赞赏作者
Like the AuthorOther Amount
赞赏后展示我的头像
作品
暂无作品
Like the Author
Other Amount
¥
最低赞赏 ¥0
OK
Back
Other Amount
更多
赞赏金额
¥
最低赞赏 ¥0
1
2
3
4
5
6
7
8
9
0
.
大语言模型 · 目录
大语言模型
上一篇超强的本地大模型 OmniCoder-9B 简测:MoXing vs Ollama 对比下一篇MoXing升级:同时运行多个模型实例
Close
更多
搜索「」网络结果
Close
调整当前正文文字大小
更多
100%