Hybrid SSM/attention models (qwen35moe) leak a fixed ~126 MiB RSS per request

此问题并非真正的内存泄漏,而是 llama.cpp 的 prompt cache(提示缓存)机制在混合 SSM/注意力模型(如 qwen35moe 架构)上为每条缓存条目分配了约 126 MiB 的固定大小内存,导致 RSS 随请求次数线性增长,直到达到默认的 8192 MiB 上限。优先排查方向是

快速结论:此问题并非真正的内存泄漏,而是 llama.cpp 的 prompt cache(提示缓存)机制在混合 SSM/注意力模型(如 qwen35moe 架构)上为每条缓存条目分配了约 126 MiB 的固定大小内存,导致 RSS 随请求次数线性增长,直到达到默认的 8192 MiB 上限。优先排查方向是检查 --cache-ram 设置和缓存条目大小。

适用环境:llama.cpp(版本 b9722 159d093a4 和 b10673 f5e85d43a),Linux 操作系统,AMD RX 7900 XTX(gfx1100)显卡,ROCm 7.2.0 或 Vulkan 后端,GNU 13.3.0 编译器。

最快修复方案:暂无确认的“一步修复”方案;但已验证有效的解决方案是设置 --cache-ram 0 禁用提示缓存,或将 --cache-ram 设置为一个更小的值(如 512),以限制缓存占用并观察 RSS 增长停止。

注意事项:禁用提示缓存会降低重复请求的处理速度;同时需注意默认的 8192 MiB 缓存上限对混合 SSM 模型来说可能占用大量主机内存(每条目约 126 MiB),在内存较小的主机上可能触发 VRAM 到 GTT 的换出。

问题场景

用户在 llama.cpp 的 llama-server 中加载混合 SSM/注意力 MoE 模型(general.architecture=qwen35moe),通过 API 连续发送多次请求时,观察到进程 RSS(Resident Set Size)每次请求固定增加约 126 MiB,且从未释放,直到进程重启。该行为在 ROCm/HIP 和 Vulkan 后端上均能复现,并排除了构建版本、MTP 推测解码、上下文长度、视觉支持、KV 缓存量化、Flash Attention 等因素的影响。

报错原文

Hybrid SSM/attention models (qwen35moe) leak a fixed ~126 MiB RSS per request
RSS=1340 → RSS=2851 → RSS=4363 → RSS=5875 → RSS=6379 MiB (delta=+126 each)

原因分析

经 Issue 讨论链确认,这并非真正的内存泄漏,而是提示缓存(prompt cache)机制导致的行为。对于混合 SSM/注意力模型,每一条缓存条目包含一个完整的循环状态(recurrent state),其大小固定且与序列长度无关,约为 126 MiB。在默认 --cache-ram 8192 设置下,缓存会持续增长直到填满该上限,因此单次请求的 RSS 增长看起来像“永不释放的泄漏”。可能原因还包括:默认的缓存上限(8192 MiB)对普通注意力模型是合适的(每条目仅几 MiB),但对混合 SSM 模型来说每条目约 126 MiB,相同的默认值可能导致大量主机内存被缓存占用,在 32 GB 主机上可能引发与 amdgpu VRAM→GTT 换出冲突。

环境排查

  • 确认 llama.cpp 版本是否为 b9722(159d093a4)或 b10673(f5e85d43a),或更早/更晚版本。
  • 检查编译后端:-DGGML_HIP=ON -DAMDGPU_TARGETS=gfx1100(ROCm)或 -DGGML_VULKAN=ON(Vulkan),验证是否确实使用了对应后端(例如通过 ldd 检查链接的库)。
  • 确认模型是否包含 ssm.* 键,如 ssm.conv_kernelssm.state_sizessm.inner_sizefull_attention_interval 等(混合 SSM 模型的标志)。
  • 记录启动参数,特别是 --cache-ram--parallel 的值。
  • 检查系统内存总量,判断 8192 MiB 默认缓存上限是否可能引发与其他进程或 GPU 驱动的内存竞争。

解决步骤

  1. 在启动 llama-server 时添加 --cache-ram 0 参数以完全禁用提示缓存,然后重复之前的请求测试,观察 RSS 是否保持稳定。
  2. 如果希望保留一定缓存能力,可尝试设置较小的值,如 --cache-ram 512,观察 RSS 增长到约 512 MiB 后是否停止(参考 Issue 中验证:设置 512 后,RSS 增长约 +507 MiB 后保持平坦)。
  3. 如果问题依然存在,可尝试设置 MALLOC_ARENA_MAX=2 环境变量(注意:此项单独设置不能解决问题,需与 --cache-ram 配合使用)。
  4. 若这些参数无法解决,建议在 llama.cpp 仓库中提交 issue,附上你的模型信息、启动参数、RSS 观测数据和后端类型,供开发者进一步排查是否存在与缓存条目大小相关的优化空间。

验证方法

应用上述参数后,连续发送至少 12 次请求,每次请求后从 /proc/<pid>/status 采样 VmRSS:如果 RSS 在达到 --cache-ram 指定的上限后保持平坦(如 --cache-ram 0 时每次请求 +0 MiB),则说明问题已解决。同时建议使用 --no-mmap 保持与 Issue 一致的测试环境。

参考来源

ggml-org/llama.cpp #27894

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 21310

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注