Research: ROCm/gfx1100: Qwen3.8-27B Q4_K_XL batch-1 tensor-split decode reaches only 1.31x one card, with per-card DRAM utilisation falling

该现象出现在 ROCm/gfx1100 双卡(RX 7900 XTX)以 tensor-split 方式运行 Qwen3.8-27B Q4_K_XL、batch-1 decode 的场景:双卡吞吐仅约单卡的 1.31x,单卡 per-card DRAM 利用率从 66% 降到 43%。优先确认单卡本

快速结论:该现象出现在 ROCm/gfx1100 双卡(RX 7900 XTX)以 tensor-split 方式运行 Qwen3.8-27B Q4_K_XL、batch-1 decode 的场景:双卡吞吐仅约单卡的 1.31x,单卡 per-card DRAM 利用率从 66% 降到 43%。优先确认单卡本身是否已达到目标带宽利用率,再判断 tensor-split 是否引入了额外的 per-card 带宽损失。

适用环境:llama.cpp(ROCm/HIP 后端,build f9f09f02c,stock,RCCL ON);AMD Radeon RX 7900 XTX ×2(gfx1100,Wave Size 32,VMM 不可用,单卡 VRAM 24560 MiB);模型 Qwen3.8-27B Q4_K_XL(16.34 GiB / 27.32B 参数);benchmark 参数 -p 2048 -n 512 -d 0 -b 4096 -ub 512 -fa 1 --load-mode none -r 5。Issue 未给出 Python、PyTorch、CUDA 版本,不在此补写。

最快修复方案:暂无确认的一步修复方案。Issue 以 research 标签关闭且无说明,讨论中也没有给出已被验证可消除该缩放的改动。

注意事项:单卡 65.9% UMC 与双卡 43.0% UMC 均为实测值,但“补齐 tensor-split 惩罚可提升约 +53%”以及“100% UMC 可达 109.4 t/s”只是基于实测带宽的推算,并未在双卡上以单卡效率实际跑通。Issue 中两台机器的测量(RX 7900 XTX 与 Radeon Pro W7900)不能直接合并比较,复测时应固定同一 build、同一 amd-smi 性能策略和同一 benchmark 参数。

问题场景

用户在 ROCm/gfx1100 上使用 llama.cpp 的 llama-bench 运行 Qwen3.8-27B Q4_K_XL,开启 flash attention、-b 4096 -ub 512、--load-mode none、-r 5,先测单卡(-sm none),再测两张 RX 7900 XTX 的 tensor-split decode。结果:单卡达到 UMC 的 65.9%(约 632.5/960 GB/s),双卡合计仅 825.7 GB/s,即合并峰值的 43.0%,batch-1 吞吐 47.06 t/s,仅为单卡约 1.31x(相对两张卡中较慢的一张为 1.32x)。同一现象在 7B Q8_0 上也存在:拆分后 per-card 带宽保留约 63.9%–65.3%,差别主要在拆分前的基线不同。

报错原文

Research: ROCm/gfx1100: Qwen3.8-27B Q4_K_XL batch-1 tensor-split decode reaches only 1.31x one card, with per-card DRAM utilisation falling from 66% to 43%

原因分析

该 Issue 是性能研究,不是常规崩溃,没有明确的报错栈。讨论把差距拆成两个比值:A 是单卡本身的低效率(65.9% UMC),B 是 tensor-split 惩罚(per-card UMC 从 65.9% 降到 43.0%)。按实测带宽推算,B 的因子约为 1.532x,A 约为 1.518x,合起来约 2.326x。

在多种配置下,拆分都会让 per-card 带宽保留约 63.9%–65.3% 的相同比例,但拆分前的基线不同(632.5 GB/s 与 776.4 GB/s),所以拆分后的比例会在 43.0%–54.8% 之间变化,惩罚本身没有变。这说明惩罚是对 batch-1 kernel 已经达到的效果做乘法,并非固定的结构性上限。

可能原因:小 M 的 decode GEMM 本身占用率低、wave 利用率差;AMD 的 LDS-Pipelined Split-K 方案只面向 MI355X/gfx950,属于单卡优化(针对 gap A),并不是 tensor-split 惩罚的已确认修复。Issue 未确定 gap B 的机制,讨论中也没有结论说明关闭是“接受测量结果”还是“不认可机制”。

环境排查

  • 确认 GPU 为 gfx1100(RX 7900 XTX 或 W7900),并记录 Wave Size、VMM 是否可用、单卡 VRAM。
  • 确认 llama.cpp 的 build 哈希与编译选项:GGML_HIP=ON、AMDGPU_TARGETS=gfx1100、GGML_CUDA_FORCE_MMQ、GGML_CUDA_FORCE_CUBLAS、GGML_HIP_GRAPHS、GGML_HIP_RCCL、GGML_HIP_NO_VMM。
  • 确认 ROCm/HIP 驱动版本以及 amd-smi set --perf-level 的当前策略(AUTO 或 profile_standard),因为功耗上限与频率会影响 UMC 读数。
  • 确认模型文件与量化类型(Q4_K_XL,16.34 GiB / 27.32B 参数),以及是否走了 mmap/load-mode 差异。
  • 确认 benchmark 参数一致:-p 2048 -n 512 -d 0 -b 4096 -ub 512 -fa 1 -r 5,tensor-split 对照时 -sm none 与双卡拆分各跑一次。
  • 确认测带宽时使用的工具是否与 llama-bench 输出的 t/s 换算方式一致;两份不同机器的数据不要混用。

解决步骤

  1. 固定同一 build 和同一 amd-smi 性能策略,先跑单卡 -sm none 基线,记录 pp2048 与 tg512 的 t/s 及对应的 UMC 利用率。
  2. 再跑双卡 tensor-split 的同一组参数,记录合计 t/s,并换算 per-card 带宽与合并峰值的比值。
  3. 分别计算两个比值:单卡 UMC 利用率(gap A)、拆分后 per-card UMC 保留比例(gap B),不要只以 1.31x 这一个数字下结论。
  4. 可优先尝试:在同一台机器上换一个 batch-1 小 M 的 decode 形状复测,观察拆分后的 per-card 带宽保留比例是否仍为约 64%,以判断惩罚是否与具体 kernel 无关。
  5. 可优先尝试:对比 GGML_HIP_GRAPHS=ON/OFF、GGML_HIP_RCCL=ON/OFF、FORCE_MMQ/FORCE_CUBLAS 自动分发等编译或运行时差异造成的 UMC 变化,但这些组合在 Issue 中没有给出验证结果,需要自行复测。
  6. 不要在拆分状态下直接套用“补齐 gap B 可得 +53%”的推算结论,只有实际跑出双卡 per-card 效率接近单卡时才能确认该收益。

验证方法

在同一台机器、同一 build、同一性能策略下,重复运行单卡与双卡 benchmark。若双卡 per-card UMC 达到接近单卡 65.9% 的水平,并且 batch-1 t/s 接近按实测带宽推算的值(约 72 t/s,即相对 47.06 t/s 提升约 53%),说明 gap B 被消除;若 per-card 保留比例仍稳定在约 64%,则说明拆分惩罚依然存在,需要继续定位 batch-1 kernel。同时核对返回的 ggml_cuda_init 设备信息,确认两张卡都被正确识别且分到了负载。

参考来源

ggml-org/llama.cpp #28863

GamsGo AI

AI 工具推荐

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

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

了解 GamsGo AI

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

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 33831

发表回复

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