Eval bug: Tensor parallelism crashes when combined with `-ncmoe` with Qwen 3.5 397B.

用户在 llama.cpp(b9672 版本)中,使用 `llama-completion` 或 `llama-cli` 工具,通过 `--sm tensor` 启用张量并行,指定 `--device ROCm1,ROCm3`(AMD GPU),配合 `-ncmoe 58` 参数加载 Qwen 3.

快速结论:该报错通常出现在使用 `–sm tensor` 张量并行(tensor parallelism)与 `-ncmoe` 参数同时开启时,尤其是针对 Qwen 3.5 397B 等 MoE 模型。优先检查 `-ncmoe` 值是否与实际 GPU 数量匹配,并排查 `ggml_backend_meta_get_split_state` 在非连续张量上的断言失败问题。

问题场景

用户在 llama.cpp(b9672 版本)中,使用 `llama-completion` 或 `llama-cli` 工具,通过 `–sm tensor` 启用张量并行,指定 `–device ROCm1,ROCm3`(AMD GPU),配合 `-ncmoe 58` 参数加载 Qwen 3.5 397B 模型的 Q3_K_M 量化版本时,程序立即崩溃。该问题在 2x AMD Radeon AI PRO R9700 GPU 上被复现,随后有用户报告在 CUDA 环境(2x Blackwell 5070 Ti)上加载 Qwen 3.5 122B 时也出现相同崩溃。

报错原文

GGML_ASSERT(ggml_is_contiguous(tensor)) failed

完整调用上下文在 ggml/src/ggml-backend-meta.cpp:1363

原因分析

根本原因在于张量并行初始化过程中,ggml_backend_meta_get_split_state 返回了一个非连续的张量(non-contiguous tensor),但后续的 GGML_ASSERT(ggml_is_contiguous(tensor)) 断言未考虑这种情况,导致程序中止。该问题在 MoE 模型使用 -ncmoe 参数时尤为突出:

  • 可能原因 1:-ncmoe 值(如 58)与物理 GPU 数量(2)不匹配,导致张量分割时 rank 数与设备数冲突,进而产生非连续张量。
  • 可能原因 2:在异构 GPU 或不同 ROCm 设备混合使用时,HIP 后端对 -ncmoe 的分片处理存在映射错误,ggml_tensor_parallel_init 尝试分割 MoE 层时未正确考虑 -ncmoe 计数。

环境排查

  • llama.cpp 版本:b9672(commit 74ade5274)
  • 系统:Linux x86_64,GNU 13.3.0 编译器
  • GPU 后端:HIP / CUDA / CPU(涉及 CUDA 和 ROCm 两种后端)
  • GPU 组合:2x AMD Radeon AI PRO R9700(测试环境)或 2x NVIDIA Blackwell 5070 Ti(其他用户)
  • 模型:Qwen 3.5 397B / 122B (GGUF),测试用量化 Q3_K_M
  • 启动参数:包含 --sm tensor-ncmoe <value>

解决步骤

  1. 确认 GPU 物理数量与 -ncmoe 的对应关系:

    -ncmoe 值设置为实际 GPU 总数。例如,若使用 2 张显卡,设置 -ncmoe 2。但需注意,-ncmoe 表示承载于 CPU 的专家层数量,降低该值可能导致 VRAM 溢出。

  2. (可优先尝试)修改源码中的断言逻辑:

    ggml/src/ggml-backend-meta.cpp 中(约 1247 行附近),将原有的:

    const size_t n_bufs = ggml_backend_meta_buffer_n_bufs(buffer);
    GGML_ASSERT(ggml_is_contiguous(tensor));
    const ggml_backend_meta_split_state split_state = ggml_backend_meta_get_split_state(tensor, /*assume_sync =*/ false);

    替换为:

    const size_t n_bufs = ggml_backend_meta_buffer_n_bufs(buffer);
    const ggml_backend_meta_split_state split_state = ggml_backend_meta_get_split_state(tensor, /*assume_sync =*/ false);
    GGML_ASSERT(ggml_is_contiguous(tensor) || split_state.axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED);

    此修改允许在张量处于 GGML_BACKEND_SPLIT_AXIS_MIRRORED 状态时跳过连续性检查。该修复由 Claude 生成,尚未作为正式 PR 提交,但已通过用户验证可阻止崩溃。

  3. 尝试不同的编译选项:

    如果使用 HIP 后端,可测试设置 -DGGML_HIP_ROCWMMA_FATTN=ON 是否影响崩溃表现(当前暂无明确证据证明有效,仅为社区建议)。

  4. 考虑升级或回退 llama.cpp 版本:

    当前问题在 b9672 版本上被报告,且标签为 bug-unconfirmed,社区尚未提供官方修复。可尝试更新至更新版本查看是否已包含相关调整。

验证方法

执行与崩溃时完全相同的命令,确认程序不再触发 GGML_ASSERT(ggml_is_contiguous(tensor)) failed 断言失败,并且模型能够正常完成前向推理生成输出。

参考来源

ggml-org/llama.cpp #24886

GamsGo AI

AI 工具推荐

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

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

了解 GamsGo AI

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

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 16116

发表回复

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