快速结论:此报错发生在使用 --n-cpu-moe CPU 卸载配合 --no-mmap --mlock(或等价的 --load-mode mlock)时,因 --load-mode 重构 #20834 导致 mlock 强制隐含 mmap,引发双缓冲 OOM 或 --load-mode none 下无锁定导致 swap 性能骤降。优先排查 llama.cpp 版本是否包含 #20834 提交。
适用环境:Linux 系统;NVIDIA GeForce RTX 5070 Ti(16GB VRAM),CUDA 后端;llama.cpp commit ed7adbfef(master 分支,2026-07-24 后);模型为大型 MoE GGUF(如 120B F16)。
最快修复方案:暂无官方确认的一步修复方案。Issue 报告者已验证的临时方案:将 llama.cpp 版本回退到 --load-mode 重构前的最新提交 1f66c3ce1(该提交为支持 Laguna S 2.1 模型同时保留旧 --no-mmap --mlock 行为的最后一个版本)。若无法回退,可尝试手动修改 llama-model-loader.cpp,将 load_mode==MLOCK 分支中的 use_mmap=true 改为 false,并仅对 CPU 卸载的张量区域调用 llama_mlock(需 C++ 修改能力,未官方验证)。
注意事项:回退版本将缺失 #20834 之后的其他 bug 修复和新功能;手动修改源码可能导致兼容性风险,需自行承担后果。Issue 开启后上游尚未回复是否采纳修复,持续关注后续提交。
问题场景
用户使用 llama-server 加载大型 MoE 模型(如 gpt-oss-120b F16 GGUF),指定 --n-cpu-moe 31 将大部分专家张量卸载到 CPU,并试图通过 --no-mmap --mlock(或重构后的 --load-mode mlock)防止 CPU 驻留张量被换出。在重构前的版本中此组合正常工作,重构后出现 OOM 或 swap 导致的极低 token 生成速度。
报错原文
# --load-mode mlock 导致 OOM 时的内核日志
Out of memory: Killed process (llama-server) ... file-rss:~57GB, ...
# --load-mode none 下的 swap 满
$ free -h
Swap: 8.0Gi 8.0Gi 0B
# 核心报错描述(取自 Issue 标题)
--load-mode refactor (#20834) removed the only safe combo for --n-cpu-moe CPU-offload: "no mmap, but pin the CPU-resident tensors"
原因分析
PR #20834 将旧的 --no-mmap 和 --mlock 等选项合并为 --load-mode 枚举,其中的 mlock 模式在 llama-model-loader.cpp 中硬编码了 use_mmap = true,导致无法实现“不 mmap 但 mlock”的组合。这产生了两个失败场景:
- OOM(
--load-mode mlock):由于 mmap 已启用同时 CPU 卸载的张量还需额外分配缓冲区存储,实际驻留内存 ≈ 模型文件全尺寸 + CPU 卸载部分尺寸,超出可用内存,被内核 OOM-killer 终止。 - swap 性能崩溃(
--load-mode none):不 mmap 也不锁定,CPU 驻留的 MoE 张量在系统内存压力下被换出,导致推理时频繁缺页,吞吐量从 25-27 t/s 暴跌至约 7.55 t/s。
Issue 报告者及另一位用户 (vakst) 在 PR #20834 评论区独立复现了相同现象。上游截止 Issue 关闭时未确认或修复该问题。



