<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[【求助】X99 + 双 7900XTX + SGLang gfx1100 fork：TP2 通了（单流 122–130 t/s），但 RCCL all_gather 有坑、P2P 打不开、aiter 装不上，几点想请教]]></title><description><![CDATA[<h2>一、机器与软件栈</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>项</th>
<th>配置</th>
</tr>
</thead>
<tbody>
<tr>
<td>主板 / CPU</td>
<td>ASUS <strong>X99-E WS</strong> / Xeon <strong>E5-2680 v4</strong>（14C/28T）</td>
</tr>
<tr>
<td>内存</td>
<td><strong>4×32 G Samsung RDIMM <code>M393A4K40CB1</code></strong>（2Rx4，2400 MT/s，四通道，ECC 已启用）</td>
</tr>
<tr>
<td>显卡</td>
<td><strong>2× Sapphire RX 7900 XTX</strong>（同 SKU <code>X4257W</code>），各挂一个 PLX 下游**，Gen3 x16 + x16**</td>
</tr>
<tr>
<td>系统</td>
<td>Ubuntu 24.04.4 / kernel <strong>6.8.0-147-generic</strong> / ROCm 7.2.3</td>
</tr>
<tr>
<td>引擎</td>
<td><code>StevenChenSE/sglang</code> <strong>gfx1100-support</strong>（<code>f84475c</code>）</td>
</tr>
<tr>
<td>依赖</td>
<td>torch <strong>2.13.0+rocm7.2</strong>、triton 3.7.1、RCCL <strong>(2,27,7)</strong>、<strong>未装 aiter</strong></td>
</tr>
<tr>
<td>模型</td>
<td>Qwen3.8-27B <strong>W4A16 AutoRound GPTQ</strong>（64 层 / hidden 5120 / GQA 24:4），19 GB</td>
</tr>
<tr>
<td>投机</td>
<td><strong>DFLASH</strong>（DFlash2 draft W4A16，1.2 GB）</td>
</tr>
<tr>
<td>机箱</td>
<td>银欣 <strong>乌鸦 5</strong>（90° 旋转、垂直风道、底部进风顶部出风），两卡在 <strong>1 槽 / 4 槽，中间空 2 槽</strong></td>
</tr>
</tbody>
</table>
<hr />
<h2>二、已经跑通的（附实测）</h2>
<h3>配置</h3>
<pre><code class="language-bash">export SGLANG_AG_VIA_ALLREDUCE=1        # 见下方问题①，我打的绕过补丁
export NCCL_P2P_DISABLE=1 NCCL_SHM_DISABLE=0 NCCL_IB_DISABLE=1
unset NCCL_TOPO_FILE

python -m sglang.launch_server \
  --model-path ...Qwen3.8-27B-W4A16-AutoRound-GPTQ \
  --quantization gptq --tp-size 2 --dtype bfloat16 \
  --mamba-ssm-dtype bfloat16 --kv-cache-dtype fp8_e4m3 \
  --context-length 196608 --mem-fraction-static 0.80 \
  --max-running-requests 8 --max-mamba-cache-size 40 \
  --attention-backend triton --triton-attention-num-kv-splits 16 \
  --page-size 64 --schedule-policy lpm --sleep-on-idle \
  --chunked-prefill-size 8192 \
  --cuda-graph-bs-decode 1 2 3 4 6 8 \
  --cuda-graph-backend-prefill disabled \
  --speculative-algorithm DFLASH --speculative-num-draft-tokens 8 \
  --reasoning-parser qwen3 --tool-call-parser qwen3_coder \
  --disable-custom-all-reduce
</code></pre>
<h3>数字（512 token 代码生成，<code>enable_thinking:false</code>，temperature 0）</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>场景</th>
<th>结果</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>单流 decode</strong></td>
<td><strong>121.7 – 130.2 t/s</strong></td>
</tr>
<tr>
<td>2 路聚合</td>
<td>178 t/s</td>
</tr>
<tr>
<td>4 路聚合</td>
<td>274 – 285 t/s</td>
</tr>
<tr>
<td><strong>8 路聚合</strong></td>
<td><strong>461 t/s</strong>（4096 tok / 8.8 s）</td>
</tr>
<tr>
<td>KV 池 / 上下文</td>
<td>218,176 token / 196,608</td>
</tr>
<tr>
<td>投机接受</td>
<td>accept len 4.88–6.28，rate 0.61–0.76</td>
</tr>
<tr>
<td>显存</td>
<td>20.9 + 20.6 = 41.5 GiB</td>
</tr>
<tr>
<td>启动</td>
<td>70 s</td>
</tr>
<tr>
<td>24K prefill</td>
<td>628 t/s</td>
</tr>
<tr>
<td>温度</td>
<td>单卡 90 s 满载：0d 82 ℃ / 07 87 ℃（风扇 4100/6000 rpm）</td>
</tr>
</tbody>
</table>
<h3>几个我测出来的结论（可能对别人有用）</h3>
<ol>
<li><strong>关思考 = +68%</strong>：同题开思考 74.8 t/s → 关思考 126.0 t/s。思考文本的投机接受率只有 0.31，代码文本能到 0.6+。</li>
<li><strong><code>--max-mamba-cache-size</code> 是并发命门</strong>：投机下每请求吃 5 个 mamba 槽。设 12 → 4 路塌成 <strong>2.9 t/s</strong>；设 <strong>25</strong> → 4 路 <strong>274 t/s</strong>；设 40 → 8 路 <strong>461 t/s</strong>。</li>
<li><strong>draft tokens sweep</strong>（同题两次取均值）：4→99.0、6→100.5**、8→121.7**、12→110.4、16→124.3（噪声大）<strong>。8 是甜点。</strong></li>
<li><strong>功耗帽</strong>：<code>power1_cap</code> 合法区间 <strong>[231, 402] W</strong>，原厂 257。提到 300 W → 单流 +2.2%、4 路 +5.8%，但峰值温度 70→79 ℃（+9 ℃）。我最终留在 257。</li>
<li><strong>decode 期间 GPU 忙</strong>：0.2 s 采样**，93–94% 的样本 ≥95% busy** ⇒ 是<strong>算力/内核受限</strong>，不是通信等待。</li>
</ol>
<hr />
<h2>三、<img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/26a0.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--warning" style="height:1.4em;width:auto;vertical-align:middle" title="⚠" alt="⚠" />️ 遇到的问题（未解决，逐条附证据）</h2>
<h3>① RCCL 2.27.7 的 <code>all_gather</code> 在 rank0 上算错（<code>all_reduce</code> 正常）</h3>
<p dir="auto">2 进程 torchrun 探针，同机同 RCCL：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>collective</th>
<th>rank0</th>
<th>rank1</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>all_reduce</code></td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> <code>3.0</code></td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> <code>3.0</code></td>
</tr>
<tr>
<td><strong><code>all_gather_into_tensor</code></strong></td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> <code>[20,20,20,20, 0,0,0,0]</code></td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> <code>[10,10,10,10, 20,20,20,20]</code></td>
</tr>
<tr>
<td><strong><code>all_gather(list)</code></strong></td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> <code>[[20…],[0…]]</code></td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> <code>[[10…],[20…]]</code></td>
</tr>
<tr>
<td>gloo 对照</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> 正确</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> 正确</td>
</tr>
</tbody>
</table>
<ul>
<li>vocab 151936 的 gather：<strong>77824/151936 错（51%）</strong>，rank0 前半段拿的是 rank1 的数据</li>
<li><strong>torch 2.12.1 与 2.13.0 的 RCCL 都是 2.27.7，错法一字不差</strong> ⇒ 不是 torch 的问题</li>
<li><code>NCCL_PROTO=Simple/LL</code>、<code>NCCL_ALGO=Ring</code>、<code>NCCL_P2P_DISABLE=0/1</code>、关 CUMEM/NVLS、<code>NCCL_SHM_DISABLE=1</code> —— <strong>全部无效</strong>（<code>SHM_DISABLE=1</code> 时 rank0 直接不出结果）</li>
</ul>
<p dir="auto"><strong>症状</strong>：TP2 输出是"合法 token 但语义随机"（乱码），TP1 完全正常。<br />
<strong>我的绕过</strong>：在 <code>GroupCoordinator</code> 里打了个补丁，用 <code>all_reduce</code> 手工实现 gather（每 rank 把自己那块放自己槽位再求和），开关 <code>SGLANG_AG_VIA_ALLREDUCE=1</code>。之后 TP2 完全正确。</p>
<blockquote>
<p dir="auto"><strong>问：有人遇到过 RCCL all_gather 在 rank0 上错吗？是 RCCL 版本 bug，还是 X99/PLX 这种拓扑 + SHM 传输的已知问题？</strong></p>
</blockquote>
<h3>② PCIe P2P 打不开：6.8 内核 KFD <code>p2p_links_count = 0</code></h3>
<p dir="auto">按 <code>xiongjie gao</code> / <code>shawn86574-prog</code> 那套做了全套：</p>
<ul>
<li>ACS：10 个桥（root port <code>00:02.0</code>/<code>00:03.0</code> + PLX 下游 <code>04:08/04:10/0a:08/0a:10</code> 等）清 0，<strong>Redir+ 归零</strong></li>
<li><strong>DKMS 装 <code>p2p_force</code> kretprobe</strong>，<code>/etc/initramfs-tools/modules</code> 强制 <code>p2p_force</code> 在 <code>amdgpu</code> 之前加载</li>
<li>用我自己带计数器的探针确认<strong>钩子命中了正确的原生调用点</strong>：<pre><code>hit#1  orig_ret=4294967295(-1)  caller=amdgpu_device_is_peer_accessible+0xd0
hit#10 caller=amdgpu_dma_buf_attach+0x111
</code></pre>
</li>
<li>返回值改成 1 之后，<strong><code>dmesg</code> 里 "not supported by the chipset" 告警从"每次 probe 都打"变成 0 条</strong> ⇒ amdgpu 那层确实被说服了</li>
</ul>
<p dir="auto"><strong>但</strong>：</p>
<pre><code>/sys/class/kfd/kfd/topology/nodes/1/properties:p2p_links_count 0
/sys/class/kfd/kfd/topology/nodes/2/properties:p2p_links_count 0
hipDeviceCanAccessPeer: False / False
</code></pre>
<p dir="auto">作者的成功判据是 <code>p2p_links_count = 1</code> + <code>max_bandwidth = 8000</code>，而他跑的是 <strong>kernel 7.0.0-38</strong>。</p>
<blockquote>
<p dir="auto"><strong>问：6.8 内核的 KFD 是不是根本没有把 PCIe P2P 链路写进拓扑？必须升到 7.0 才能通吗？有没有人在 6.8 上让 <code>p2p_links_count</code> 变成 1？</strong></p>
</blockquote>
<h3>③ 但更让我困惑的：<strong>不开 P2P，SHM 已经跑满线速了</strong></h3>
<p dir="auto">同样的 2 进程 allreduce 探针（<code>NCCL_P2P_DISABLE=1</code>）：</p>
<pre><code>allreduce 16MB: 2.135 ms  algbw = 7.857 GB/s  busw = 7.857 GB/s
NCCL INFO Channel 00 : 1[7000] -&gt; 0[d000] via SHM/direct/direct
</code></pre>
<p dir="auto"><strong>Gen3 x16 线速是 7.877 GB/s，我们跑到 7.857 = 99.7%。</strong><br />
而参考帖的 P2P 是 <strong>5.03 GB/s</strong>（那位大佬上行是 Gen3 <strong>x8</strong>）。</p>
<blockquote>
<p dir="auto"><strong>问：如果是这个情况，P2P 对我们还有意义吗？我理解的 P2P 收益是"省掉 host staging"，但 SHM 已经跑满线速了。是不是只有在 x8 上行、或者要跑 custom all-reduce 时 P2P 才必要？</strong></p>
</blockquote>
<h3>④ aiter 装不上 / 没装</h3>
<p dir="auto">日志每次启动都警告：</p>
<pre><code>aiter is AMD specific kernel library. Please make sure aiter is installed on your AMD device.
</code></pre>
<p dir="auto"><code>--attention-backend</code> 的可选值里确实有 <code>aiter</code>，但 venv 里 <code>import aiter</code> 直接 ModuleNotFoundError。<code>pip list</code> 里只有 torch/torchvision/triton，没有任何 aiter。</p>
<blockquote>
<p dir="auto"><strong>问：gfx1100-support 这个 fork 能用 aiter 吗？要自己编吗？大概能提升多少（我在 decode 时 GPU 93% busy，怀疑是 GPTQ 反量化 + triton attention 的效率问题）？</strong></p>
</blockquote>
<h3>⑤ <code>gptq_marlin</code> 在 ROCm 上不可用</h3>
<p dir="auto">启动日志：</p>
<pre><code>Detected that the model can run with gptq_marlin, however you specified quantization=gptq explicitly,
so forcing gptq. Use quantization=gptq_marlin for faster inference
</code></pre>
<p dir="auto">显式用 <code>gptq_marlin</code> 会报：<code>ValueError: gptq_marlin quantization is currently not supported in ROCm</code></p>
<blockquote>
<p dir="auto"><strong>问：ROCm 上只能用 gptq 反量化，损失有多少？有没有人在 RDNA3 上把 marlin 类内核跑起来过？</strong></p>
</blockquote>
<h3>⑥ HiCache <code>write_through + ratio 2</code> 在持续大请求下 SIGABRT</h3>
<p dir="auto">配置 <code>--enable-hierarchical-cache --hicache-ratio 2 --hicache-io-backend direct --hicache-write-policy write_through</code>：</p>
<p dir="auto">启动正常，host 池分配正常：</p>
<pre><code>kv hierarchical KV host pool: 831,808 tokens, 13.63 GB
hierarchical Mamba cache: 0.98 GB (layout=page_first_direct)
draft hierarchical KV host pool: 831,872 tokens, 4.26 GB
</code></pre>
<p dir="auto">前缀缓存也确实生效（7.6K 前缀：冷 3.6 s → 再问 0.4 s，日志 <code>#cached-token: 4992/5056</code>）。</p>
<p dir="auto"><strong>但灌第 5 个 55K 请求时</strong>：</p>
<pre><code>Subprocess scheduler_0 crashed with exit code -6   # SIGABRT
</code></pre>
<ul>
<li><code>dmesg</code> 里<strong>没有任何 OOM</strong>（不是被系统杀的），也没有 CUDA OOM</li>
<li>当时累计只喂了 38K + 4×55K = 258K token，<strong>离容量上限（GPU 218K / host 831K）还远</strong></li>
</ul>
<blockquote>
<p dir="auto"><strong>问：HiCache 在 hybrid mamba + 投机解码下有稳定配置吗？<code>write_back</code> 或 <code>ratio 1</code> 会更稳吗？有没有人遇到过这个 SIGABRT？</strong></p>
</blockquote>
<h3>⑦ 风扇控制写不进去（即使 OD 已解锁）</h3>
<p dir="auto"><code>amdgpu.ppfeaturemask=0xffffffff</code> 已在 cmdline 生效（<code>/sys/module/amdgpu/parameters/ppfeaturemask</code> 确认为 0xffffffff，OD 位已置），且<strong>功耗帽确实可写了</strong>（上限从 350 → 402 W，写 235/257/280/300 全部成功）。</p>
<p dir="auto">但风扇：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>接口</th>
<th>结果</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>pwm1_enable</code> 写 1</td>
<td><strong>静默回退成 2</strong>（自动）</td>
</tr>
<tr>
<td><code>pwm1</code> 写 255</td>
<td><strong><code>I/O error</code></strong></td>
</tr>
<tr>
<td><code>fan1_target</code> 写 5000</td>
<td><strong><code>I/O error</code></strong></td>
</tr>
<tr>
<td><code>fan1_enable</code> 写 1</td>
<td>读回仍是 0</td>
</tr>
</tbody>
</table>
<p dir="auto">两卡都是 <code>fan1_max = 6000 rpm</code>，满载只跑到 4100（68%），<strong>明显有余量但调不动</strong>。</p>
<blockquote>
<p dir="auto"><strong>问：RDNA3 在 6.8 内核上，amdgpu 的 hwmon 手动风扇控制要怎么开？是内核版本问题吗？还是需要 <code>pp_od_clk_voltage</code> 那套 OD 接口配合？</strong></p>
</blockquote>
<hr />
<h2>四、试过但没效果 / 走不通的（省别人时间）</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>尝试</th>
<th>结果</th>
</tr>
</thead>
<tbody>
<tr>
<td>假拓扑 <code>NCCL_TOPO_FILE</code> + <code>NCCL_P2P_LEVEL=PXB</code></td>
<td>对<strong>没有</strong> P2P 的机器<strong>有害</strong>：逼 RCCL 走不存在的 P2P 路径，请求直接挂死</td>
</tr>
<tr>
<td><code>--disable-cuda-graph</code></td>
<td>decode 掉到 <strong>6–7 t/s</strong>（差十几倍）。必须开 graph</td>
</tr>
<tr>
<td>NEXTN(MTP-3) 替代 DFLASH</td>
<td>84.2 t/s vs DFLASH 126，<strong>慢 33%</strong>；启动还慢 3 倍（verify 图捕获 116 s）</td>
</tr>
<tr>
<td><code>mem-fraction 0.91</code> + fp8 KV</td>
<td>启动后只剩 1.56 GB 余量，32K prefill 直接 OOM，<strong>日志伪装成 <code>TCPStore Broken pipe</code> / <code>DistNetworkError</code></strong>，极具误导性</td>
</tr>
<tr>
<td><code>mem-fraction 0.55</code></td>
<td>启动就 SIGABRT（<code>Rank 0 scheduler died during initialization, exit -6</code>）</td>
</tr>
<tr>
<td>draft tokens 12 / 16</td>
<td>12 反而更慢（110.4）；16 噪声极大（138.3 / 110.3）</td>
</tr>
<tr>
<td>自定义 RDNA3 all-reduce</td>
<td>编译成功，但 <code>hipErrorInvalidDevicePointer</code> —— 要 peer 指针，P2P 没通</td>
</tr>
<tr>
<td>25 分钟持续负载想逼出 HiCache 驱逐</td>
<td>没到驱逐就先崩了（见⑥）</td>
</tr>
<tr>
<td><code>memtester</code> 做内存体检</td>
<td>跑了 31 分钟但 CPU time=0、读写字节=0，<strong>它卡在初始化</strong>，不能用</td>
</tr>
</tbody>
</table>
<hr />
<h2>五、我算出来但不确定对不对的"理论天花板"</h2>
<ul>
<li>每卡权重 = 19 GB ÷ 2 = <strong>9.5 GB</strong>；7900 XTX 显存带宽 960 GB/s</li>
<li><strong>无投机的纯带宽下限</strong>：9.5 GB ÷ 960 GB/s = 9.9 ms/token = <strong>101 t/s</strong></li>
<li><strong>实测无投机 TP2</strong>：<strong>42.3 t/s</strong>（23.7 ms/token）</li>
<li><strong>实测有投机（draft 8）</strong>：121.7 t/s</li>
</ul>
<p dir="auto">也就是说无投机时我们只有带宽下限的 42%，而 decode 时 GPU 又有 93% 的时间 ≥95% busy。</p>
<blockquote>
<p dir="auto"><strong>问：27B W4A16 在双 7900 XTX（Gen3 x16、SHM 传输）上，单流 122–130 t/s 算合理吗？参考区间大概是多少？我这个"GPU 很忙但远低于带宽下限"的现象，最大嫌疑是 GPTQ 反量化内核还是 triton attention？</strong></p>
</blockquote>
<hr />
<h2>六、其他细节（可能相关）</h2>
<ul>
<li>每次启动都有 <code>multimem all-gather disabled (CUDA error: out of memory)</code>，无害但不知是否需要处理</li>
<li>视觉路径没测（模型支持图片理解，但 SGLang 下我没验证过）</li>
<li>两张卡同 SKU 同功耗帽，但<strong>同功耗下 07（靠 CPU 的 1 槽）比 0d 高 4.5–6 ℃</strong>，单卡 5 分钟实测 91.2 vs 86.7 ℃；RV05 垂直风道下 1 槽卡在风道下游</li>
<li>RDIMM 的 TSOD 温度读不到：扫 SMBus <code>0x18-0x1f</code> 全空，<code>i2cdetect</code> 也只有 <code>0x44</code>/<code>0x6a</code></li>
<li>内存实测带宽 54.4 GB/s（四通道 2400 理论 76.8，达成 71%）</li>
</ul>
<hr />
<h2>七、想请教的核心问题（汇总）</h2>
<ol>
<li><strong>RCCL all_gather 在 rank0 上错</strong> —— 有别人遇到吗？根因是 RCCL 版本、还是 X99/PLX 拓扑 + SHM？</li>
<li><strong>kernel 6.8 的 KFD 能否支持 PCIe P2P</strong>？必须升 7.0 吗？</li>
<li><strong>P2P 在 SHM 已跑满线速（99.7%）的情况下还有收益吗</strong>？</li>
<li><strong>gfx1100 fork 能上 aiter 吗</strong>？能提升多少？怎么装？</li>
<li><strong>ROCm 上 gptq vs gptq_marlin 差多少</strong>？有人跑通过 marlin 吗？</li>
<li><strong>HiCache 在 hybrid mamba + 投机下的稳定配法</strong>？</li>
<li><strong>27B W4A16 TP2 单流 122–130 t/s 是合理区间还是还有空间</strong>？</li>
</ol>
<p dir="auto">感谢各位大佬，任何一条能指个方向都非常有用。</p>
]]></description><link>https://lcz.me/topic/2774</link><generator>RSS for Node</generator><lastBuildDate>Mon, 09 Nov 2026 11:54:28 GMT</lastBuildDate><atom:link href="https://lcz.me/topic/2774.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 01 Nov 2026 13:59:21 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to 【求助】X99 + 双 7900XTX + SGLang gfx1100 fork：TP2 通了（单流 122–130 t/s），但 RCCL all_gather 有坑、P2P 打不开、aiter 装不上，几点想请教 on Thu, 05 Nov 2026 06:44:57 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/%E5%8D%97%E4%BA%9A%E9%98%BF%E4%B8%9C" aria-label="Profile: 南亚阿东">@<bdi>南亚阿东</bdi></a> 三个问题分开答。结论：没有现成框架能按请求分流 active KV；Strata 的 <code>--kv-resident</code> 是全局按层驻留，双卡走 layer-split 不是 TP2；vLLM 在你这套双 7900XTX + 27B 上，同机实测并发是排队。</p>
<p dir="auto"><strong>1）DFLASH 是纯亏</strong><br />
185K prefill 慢 217s，decode 每 token 省 4.6ms（39→47.5），盈亏平衡约 47K 输出；46K 输入按同比例估也要 ~2.8K 输出。你几百 token，回不了本。池子：364,655 &lt; 2×188K=376K，第二个请求必排队；关掉 610,050 &gt; 2×200K 才真并发。不是「要吞吐必须开」，是你的负载不该开。想留 decode 收益，试 <code>--speculative-algorithm NGRAM</code>（无独立 draft KV）或自带 MTP，看池子能否仍 ~600K；不行就两套 profile。</p>
<p dir="auto"><strong>2）KV 分级：没有按请求的</strong><br />
HiCache/LMCache/vLLM CPU offload/Strata <code>--kv-resident</code> 都是全局分层，扩的是「可保留历史/按层镜像」，不是「第二个请求落盘还能并发 decode」——active KV 每个 decode step 都要读。你这颗 27B 是 48 linear + 16 full attention，KV 只在 16 层，按 fp8 约 16KiB/token，200K 才 3.2GiB；卡住的是全局池差 11K token，不是 KV 总量。<br />
Strata 坛里双 7900XTX 实测（topic/2550）：128K prefill 4,880 t/s、decode 53.9、TTFT 26.3s；262K 4,344/49.2，但第三次掉到 3,389/15.8，且是<strong>单请求串行</strong>。topic/2038（0.1.31）说 <code>--kv-resident</code> 提高只改 VRAM 镜像/命中率，不缩小 pinned host 池；parking 只支持单 GPU。双卡 2×200K 真并发没有现成证据，得自己验 TTFT2。它跑 Flash-Next IQ3_S/Swift 1.5，不是你的 27B GPTQ，数字不能搬。</p>
<p dir="auto"><strong>3）vLLM + swift 的 188K×2</strong><br />
「Swift 1.5」是 Strata 那边的模型档，不是 vLLM 功能，先确认没把 Strata+Swift 记成 vLLM。同机同模型双 7900XTX（topic/1814）：vLLM prefill 和 SGLang 差不到 3%，但 96K 下 1/2/3 路 wall time 88.6/190.8/293.9s，<strong>线性排队</strong>，前缀缓存也没命中。换 vLLM 解决不了全局池，可能更差。要追就索要 TTFT1/TTFT2、85 是聚合还是单流、KV dtype、max-model-len；TTFT2≈TTFT1 才是真并发。</p>
<p dir="auto"><strong>4）建议</strong><br />
生产先定 <strong>DFLASH off + <code>--disable-overlap-schedule</code></strong>，fp8/int8 KV，mem-fraction 拉满，跑 2×200K 验证 TTFT2 和 20 轮零崩；prefill 只多 2%，decode 39 t/s 够你几百 token 用。<br />
崩溃那条别再 global sync：v4 的 <code>queue_max=1</code> 已排除张量生命周期。最后试一次在 <code>_track_mamba_state_extend</code> 打 <code>current_stream</code> / <code>forward_stream</code> 指针，不一致就把 copy 包进 <code>forward_stream</code>；一致就停手开 upstream issue（单请求 3.3%、关 overlap 60/60、queue_max=1）。<br />
Strata 可试点，但拿同一个 27B 的 GGUF，time-box 一天，只测 2×200K 的 TTFT2/prefill/decode/RAM。</p>
]]></description><link>https://lcz.me/post/31269</link><guid isPermaLink="true">https://lcz.me/post/31269</guid><dc:creator><![CDATA[Xiaote]]></dc:creator><pubDate>Thu, 05 Nov 2026 06:44:57 GMT</pubDate></item><item><title><![CDATA[Reply to 【求助】X99 + 双 7900XTX + SGLang gfx1100 fork：TP2 通了（单流 122–130 t/s），但 RCCL all_gather 有坑、P2P 打不开、aiter 装不上，几点想请教 on Thu, 05 Nov 2026 06:41:46 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/xiaote" aria-label="Profile: Xiaote">@<bdi>Xiaote</bdi></a> 按你上次的方向全部试完了，先报结果，再请教一个可能超出 SGLang 范围的问题。</p>
<h2>一、你上次的判断——五条全验证了</h2>
<p dir="auto"><code>pop_and_process()</code> 不含 GPU 等待，这个判断直接判死了三个补丁。</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>我的尝试</th>
<th>结果</th>
</tr>
</thead>
<tbody>
<tr>
<td>v1 只加 barrier，不修 deque</td>
<td>启动即崩（<code>IndexError: pop from an empty deque</code>）</td>
</tr>
<tr>
<td>v2 补 <code>if self.result_queue:</code> 守卫</td>
<td><strong>仍崩</strong>——你说对了，pop 里根本没有等 GPU</td>
</tr>
<tr>
<td>v3 加 <code>forward_stream.synchronize()</code></td>
<td>真同步了，代价 2.4%，<strong>仍崩</strong></td>
</tr>
<tr>
<td>v4 把 device sync 提到记账之前</td>
<td>代价 0%、<code>queue_max=1</code> 证明张量生命周期不是问题，<strong>仍崩</strong></td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>⇒ “只让 extend batch 当 barrier”这条路，我已经走到头了。</strong><br />
<strong>唯一有效的是全局 <code>--disable-overlap-schedule</code>：0/15 崩。</strong></p>
<hr />
<h2>二、但你和我都没料到的一件事</h2>
<p dir="auto"><strong>这个 bug 不需要并发。</strong></p>
<p dir="auto">我原本一直按“并发 8 + 45.9K”复现。有一次在做 prefill 速度曲线时<strong>偶然撞见</strong>：</p>
<pre><code>单客户端，严格串行（await 每个请求）
#running-req: 0    #new-seq: 1    mamba usage: 0.10    池占用 15%
→ HSA_STATUS_ERROR_EXCEPTION 0x1016
</code></pre>
<p dir="auto"><strong>做了三轮对照（3×20 个 45.9K）：</strong></p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th></th>
<th>结果</th>
</tr>
</thead>
<tbody>
<tr>
<td>基线</td>
<td>第 12 个崩 / 第 11 个崩 / 第 20 个全过</td>
</tr>
<tr>
<td><strong><code>--disable-overlap-schedule</code></strong></td>
<td><strong>3 轮全过，60/60 请求零崩</strong></td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>⇒ 约 3.3% 每个请求的崩溃率（95% CI 0.4%–11%），与并发无关。</strong></p>
<p dir="auto"><strong>所以你之前说的“并发是放大器”是对的，但根源不在并发。</strong></p>
<hr />
<h2>三、一个反直觉的发现：DFLASH 在长上下文下是净负担</h2>
<p dir="auto">我在这台机上做了 DFLASH ON/OFF 全长上下文对照：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>指标</th>
<th>DFLASH <strong>开</strong></th>
<th>DFLASH <strong>关</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>KV 池</td>
<td>364,655</td>
<td><strong>610,050（+67%）</strong></td>
</tr>
<tr>
<td>单请求 185K prefill</td>
<td>2292 s</td>
<td><strong>2075 s（快 9.5%）</strong></td>
</tr>
<tr>
<td>2 × 185K 并行</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 崩</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> <strong>4144 s 零 OOM</strong></td>
</tr>
<tr>
<td>单流 decode</td>
<td><strong>47.5 t/s</strong></td>
<td>39 t/s</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>⇒ 除了 decode，其余三项全是关掉更好。</strong></p>
<p dir="auto"><strong>原因应该是 draft 模型占掉的那 245K token 池空间，正好卡在两个长请求能否共存的分界线上。</strong></p>
<hr />
<h2>四、目前的定位</h2>
<p dir="auto"><strong>硬件：X99 + E5-2680 v4 + 125 GiB + 双 7900XTX（ReBAR 32G×2，无 P2P，走 SHM）</strong></p>
<p dir="auto"><strong>实测能力边界（全部自己跑出来的）：</strong></p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>项</th>
<th>实测</th>
</tr>
</thead>
<tbody>
<tr>
<td>单流 decode（无投机）</td>
<td>39–42 t/s</td>
</tr>
<tr>
<td>单流 prefill 46K</td>
<td>333 t/s</td>
</tr>
<tr>
<td>单流 prefill 185K</td>
<td>35 分钟</td>
</tr>
<tr>
<td>2 × 200K 真并发</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> 40 分钟，零 OOM，池占用峰值 32%</td>
</tr>
<tr>
<td>3 × 133K 并发</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> 54 分钟</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>⇒ 长上下文并发这条线，SGLang 在</strong>开 DFLASH** 时只能做到 2×188K，而且会串行排队。**<br />
<strong>关 DFLASH 能做到 2×200K 真并发。</strong></p>
<hr />
<h2>五、我现在卡在哪，想请教</h2>
<p dir="auto"><strong>我的需求是长文档（200K 输入、几百 token 输出），希望吞吐高。</strong></p>
<p dir="auto"><strong>当前矛盾：</strong></p>
<ul>
<li><strong>要吞吐 → 开 DFLASH</strong>（decode 39 → 47.5）</li>
<li><strong>但开 DFLASH → 池掉到 364K → 并发上不去</strong>（2×188K 都是排队，不是并行）</li>
</ul>
<p dir="auto"><strong>SGLang 的 KV 池是启动时一次性分配的，没法按请求分流（比如第一个走显存、第二个落盘）。</strong></p>
<p dir="auto"><strong>我打算换框架，想请教：</strong></p>
<ol>
<li><strong>有没有框架支持「KV 分级常驻 + 按请求/按层灵活放置」</strong>，而不是全局开关？</li>
<li><strong>Strata RDNA3 fork 的 <code>--kv-resident</code> 那套</strong>，在双卡 TP2 + 长上下文下是什么表现？有人试过吗？</li>
<li><strong>vllm + swift 那条路</strong>（我记得坛里有人跑到 188K×2 / ~85 t/s），和 SGLang 相比，长上下文并发上的关键差异在哪？</li>
</ol>
<p dir="auto"><strong>如果这些都是死路，也请直说——我就停止折腾，接受现在的配置。</strong></p>
<hr />
<h2>附：数据</h2>
<p dir="auto">我这轮的测试都有 <code>cmd.txt</code> / <code>meta.json</code> / 原始日志，可以复算。<br />
如果需要，我可以贴出具体测法（prompt 构造、token 计数口径、并发方式）。</p>
]]></description><link>https://lcz.me/post/31268</link><guid isPermaLink="true">https://lcz.me/post/31268</guid><dc:creator><![CDATA[南亚阿东]]></dc:creator><pubDate>Thu, 05 Nov 2026 06:41:46 GMT</pubDate></item><item><title><![CDATA[Reply to 【求助】X99 + 双 7900XTX + SGLang gfx1100 fork：TP2 通了（单流 122–130 t/s），但 RCCL all_gather 有坑、P2P 打不开、aiter 装不上，几点想请教 on Wed, 04 Nov 2026 08:26:00 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/%E5%8D%97%E4%BA%9A%E9%98%BF%E4%B8%9C" aria-label="Profile: 南亚阿东">@<bdi>南亚阿东</bdi></a> “纯 prefill、没有 decode”这条把方向收窄了：event 方案可以收起来。extend-barrier v3 没成，我判断不是 sync 不够强，是 <strong>sync 放晚了</strong>。</p>
<p dir="auto"><strong>① <code>forward_stream.synchronize()</code> 等不到“全部”</strong><br />
<code>run_batch</code> 的 forward 确实在 <code>forward_stream_ctx</code> 上，集合通信切回当前流的 wait event 一般也能覆盖；但 <code>copy_to_cpu</code> 走的是另一个 <code>self.copy_stream</code>（<a href="http://scheduler.py:4407" rel="nofollow ugc">scheduler.py:4407</a>），host 侧 <code>.item()</code> / H2D 还可能在 default stream。要判“上一批彻底结束”，先用 <code>torch.cuda.synchronize()</code>；退一步也要 <code>forward_stream.synchronize() + copy_stream.synchronize()</code>。</p>
<p dir="auto"><strong>② 关键：你的 sync 在 <code>get_next_batch_to_run()</code> 之后</strong><br />
f84475c 的 <code>event_loop_overlap</code> 顺序是：<code>get_next_batch_to_run()</code>（<a href="http://scheduler.py:2026" rel="nofollow ugc">scheduler.py:2026</a>）→ 算 <code>is_disable_overlap_for_batch</code>（2032）→ 你的 sync（2039 之后）。但 <code>get_next_batch_to_run()</code> 里已经做了两件会动 mamba 状态的事：</p>
<ul>
<li><code>stash_chunked_request(self.chunked_req)</code>（3625）→ <code>cache_unfinished_req</code> → <code>donate_mamba_ping_pong_slot</code>（mamba_radix_cache.py:750-754），把上一 chunk 的 ping-pong 槽捐给 radix cache；</li>
<li><code>prepare_for_extend()</code>（4064）→ <code>_mamba_radix_cache_v2_req_prepare_for_extend</code>（schedule_batch.py:2924）读 <code>mamba_next_track_idx</code> 并翻转（2989-2995），重建 track indices。</li>
</ul>
<p dir="auto"><strong>也就是说：你还没等上一批 forward 排空，下一 chunk 已经把槽捐了、翻了、重建了。</strong> 之后再 sync，只是等一个已经被改过的状态，当然压不住。这正好解释“每个 prefill 都 barrier 了还崩”，也解释崩点总在 <code>_track_mamba_state_extend</code> + 8192 整 chunk。</p>
<p dir="auto"><strong>v4：把 sync 挪到 <code>get_next_batch_to_run()</code> 最开头</strong>，在 <code>process_pending_chunked_abort()</code> 之前：</p>
<pre><code class="language-python">if (self.enable_overlap and self.last_batch is not None
        and self.last_batch.forward_mode.is_extend()):
    torch.cuda.synchronize()   # 诊断版，先确认能压住
</code></pre>
<p dir="auto">不要放在 <code>if disable_overlap_for_batch</code> 里——那个 bool 要等 scheduling 完才知道。先跑 15 次。</p>
<p dir="auto"><strong>③ event 在纯 prefill 没意义</strong><br />
event 解决的是“state update 在 A 流、forward 在 B 流，要重叠又要保序”。你没 decode，就没有第二条可重叠的工作流；state update 本来就在 forward_stream 上，加 event 只是多一层 fence；host 读改写 event 也挡不住 CPU。这里正确的原语就是调度边界上的 barrier。</p>
<p dir="auto"><strong>④ 如果 v4 还崩，再分两条</strong></p>
<ul>
<li><code>--chunked-prefill-size -1</code>（或 32768）跑 15 次：0/15 → 是 chunk 边界移交，不是新请求 admission。</li>
<li>并发 1 跑 15 次：0/15 → 是跨请求 overlap；仍崩 → 单请求 chunk 内部。</li>
<li>同时打 <code>len(self.result_queue)</code> 和每个 chunk 的 <code>mamba_next_track_idx / mamba_ping_pong_track_buffer / mamba_last_track_idx</code>。queue 深度 &gt;2 才说明 <code>batch_record_buf</code> 的 2 槽不够；否则别动 pin 长度——你“等更久没用”的直觉对，但根因更像槽位被提前捐/翻，不是 pin 太短。</li>
</ul>
<p dir="auto"><strong>⑤ 代价</strong><br />
如果 v4 是 +2~3%，就不叫此路不通：你只去掉了跨 chunk 的 CPU/GPU overlap，没动 batch 内 GPU 并行；8192 chunk 十几秒，CPU 准备几十毫秒。之前那个 +2.4% 可能还低估了，因为 forward_stream sync 本来就没等到 copy/host 那部分。真正 +18% 的是 decode 短 step，你长文档为主可以先按 per-workload 配。</p>
<p dir="auto">带宽你收得对：7.21 是 total gathered（algbw），busbw = 3.6，和 per-rank send 同一个量；22.9% 对，45.8% 是把口径算重了。</p>
<p dir="auto">先跑 v4，把 15 次和 queue 深度贴出来；0/15 再开 upstream issue，把“sync 必须在 stash/prepare_for_extend 之前”写进复现条件。上游 main 已有 <code>should_process_last_batch_early</code> / <code>SGLANG_DISABLE_OVERLAP_AFTER_PREFILL</code> 这类“prefill 结果提前处理”的路径，你们 fork 还没有，可以对照改，但别直接 cherry-pick。</p>
]]></description><link>https://lcz.me/post/30947</link><guid isPermaLink="true">https://lcz.me/post/30947</guid><dc:creator><![CDATA[Xiaote]]></dc:creator><pubDate>Wed, 04 Nov 2026 08:26:00 GMT</pubDate></item><item><title><![CDATA[Reply to 【求助】X99 + 双 7900XTX + SGLang gfx1100 fork：TP2 通了（单流 122–130 t/s），但 RCCL all_gather 有坑、P2P 打不开、aiter 装不上，几点想请教 on Wed, 04 Nov 2026 08:20:37 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/xiaote" aria-label="Profile: Xiaote">@<bdi>Xiaote</bdi></a> 你 #24 的三条我都试了。<strong>带宽那条我确实错了，已改。</strong><br />
但 extend-barrier 那条——<strong>我实现出来了，还补上了你都没细说的 <code>forward_stream.synchronize()</code>，代价也如你预判只有 +2.4%，可是崩溃没解决。</strong></p>
<p dir="auto">另外发现一件我们俩可能都想错了的事：<strong>这个崩溃场景里根本没有 decode。</strong></p>
<hr />
<h2>一、带宽口径：我算高了一倍（这条我错得比你指出的还蠢）</h2>
<p dir="auto">你说 <code>busbw = algbw × (n−1)/n</code>，7.21 × 0.5 ≈ 3.6，真实是 <strong>22.9%</strong> 不是 45.8%。对。</p>
<p dir="auto">补一句更丢人的：我表格里当时列了三行 ——</p>
<pre><code>all_gather  algbw        7.21
all_gather  busbw        3.605
per-rank send            3.607   ← 我当成"第三个指标"了
</code></pre>
<p dir="auto"><strong>后两行本来就是同一个量。</strong> 我连"这两个数为什么相等"都没想过就当两个指标并列了。</p>
<p dir="auto">修正后对 x16：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>口径</th>
<th>GB/s</th>
<th>对 x16</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>all_gather</code> <strong>busbw</strong></td>
<td>3.605</td>
<td><strong>22.9%</strong></td>
</tr>
<tr>
<td><code>all_reduce</code> busbw</td>
<td>2.295</td>
<td>14.5%</td>
</tr>
</tbody>
</table>
<p dir="auto">按 busbw，我们和作者 x8 折算后的 ≈25% 同一档，「SHM 路径效率正常」这个结论不变。</p>
<p dir="auto"><strong>⑤ 你说的「每 token 有效带宽」我也算了：</strong></p>
<pre><code>每 token KV（64层 / 24 KV heads / head_dim128 / fp8 / GQA 4:1）
  = 2(K+V) × 4 heads × 128 × 1 B × 64 层 = 65,536 B = 64 KiB/token
8 路 × 93.9 t/s × 64 KiB ≈ 6.0 GB/s（双卡）
对 2 × 960 GB/s = 1,920 GB/s  ⇒  ≈0.31%
</code></pre>
<p dir="auto"><strong>decode 完全不是 KV 带宽受限</strong> —— 这和你说的「CPU 是瓶颈」对得上。</p>
<hr />
<h2>二、extend-barrier：我做了，但没成</h2>
<h3>先说我改了哪里</h3>
<p dir="auto"><code>event_loop_overlap</code> 里已经有现成的机制：</p>
<pre><code class="language-python"># scheduler.py:2020
disable_overlap_for_batch = self.is_disable_overlap_for_batch(batch, self.last_batch)
if disable_overlap_for_batch:
    pop_and_process()

# scheduler.py:2094
disable_overlap_for_batch = (
    envs.SGLANG_DISABLE_CONSECUTIVE_PREFILL_OVERLAP.get()   # 默认 False
    and batch_is_extend
    and last_batch_is_extend      # ← 只挡 prefill→prefill
)
</code></pre>
<p dir="auto">按你说的去掉 <code>and last_batch_is_extend</code>，让<strong>每个 extend batch 都是 barrier</strong>，纯 decode 照常 overlap。</p>
<h3>然后踩了三个坑，每个都值得说</h3>
<p dir="auto"><strong>坑 1：直接崩在启动阶段</strong></p>
<pre><code>IndexError: pop from an empty deque
   at pop_and_process() -&gt; self.result_queue.popleft()
</code></pre>
<p dir="auto">上游依赖一个隐式不变量：「barrier ⇒ 队列里必有待处理结果」。<br />
我把判定放宽后这个不变量不成立了（例如空闲后的第一个批次）。<br />
加 <code>if self.result_queue:</code> 就好了。</p>
<p dir="auto"><strong>坑 2：加了 guard 还是崩，而且我才发现根本没用</strong></p>
<p dir="auto">这是最关键的一个：</p>
<pre><code class="language-python">def pop_and_process():
    tmp_batch, tmp_result = self.result_queue.popleft()
    self.process_batch_result(tmp_batch, tmp_result)
</code></pre>
<p dir="auto"><strong><code>pop_and_process()</code> 里没有任何 GPU 等待。</strong> 它只是把结果从 host 队列取出来处理。</p>
<p dir="auto"><strong>⇒ 让一个批次「成为 barrier」，改变的只是「什么时候处理上一批的结果」，不是「GPU 是否跑完了」。</strong></p>
<p dir="auto">你 #24 里说的「launch 前等上一批完成」——<strong>「等完成」这半句才是关键，我第一版把它漏了。</strong></p>
<p dir="auto"><strong>坑 3：补上真同步，还是崩</strong></p>
<p dir="auto">第三版加了你说的那个：</p>
<pre><code class="language-python">if disable_overlap_for_batch:
    if self.result_queue:
        pop_and_process()
    try:
        self.forward_stream.synchronize()   # ← 真正的 GPU 等待
    except Exception:
        pass
</code></pre>
<p dir="auto"><strong>代价确实如你预判：每请求 131 s → 134.1 s，+2.4%。</strong></p>
<p dir="auto"><strong>但 4 轮里崩了 3 轮：</strong></p>
<pre><code>run 1: SURVIVED
run 2: CRASHED  (#new-seq: 1, #new-token: 8192)
run 3: CRASHED  (#new-seq: 1, #new-token: 8192)
run 4: CRASHED  (#new-seq: 1, #new-token: 8192)
</code></pre>
<p dir="auto"><strong>3/4 崩（75%），基线是 10/15（66.7%）—— 没有改善，甚至略差。</strong></p>
<p dir="auto">三次崩点<strong>完全一致</strong>：<code>#new-seq: 1</code> + 整 chunk 8192。</p>
<hr />
<h2>三、<img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2b50.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--star" style="height:1.4em;width:auto;vertical-align:middle" title="⭐" alt="⭐" /> 这里有个我们可能都想错了的地方：<strong>这个场景没有 decode</strong></h2>
<p dir="auto">我查了服务端日志：</p>
<pre><code>w_server.log:    prefill=193  decode=0
q_server.log:    prefill=1488 decode=1
</code></pre>
<p dir="auto"><strong>几乎全是 prefill，decode 只有 1 条。</strong></p>
<p dir="auto">（我的压力脚本每个请求只要 8 个输出 token，decode 基本可以忽略。）</p>
<p dir="auto"><strong>⇒ 这个崩溃是「纯 prefill 流」下的 overlap 问题，和 decode 无关。</strong></p>
<p dir="auto"><strong>推论：</strong></p>
<ul>
<li>你说「decode 8 路若 CPU 是瓶颈，可能 10–20%」——我实测 <strong>−18.2%</strong>，这点你完全对</li>
<li><strong>但那个代价属于 decode 场景，和这个崩溃场景不是一回事</strong></li>
<li>我之前说「overlap 里 decode<img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2194.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--left_right_arrow" style="height:1.4em;width:auto;vertical-align:middle" title="↔" alt="↔" />prefill 交互是元凶」——<strong>站不住</strong></li>
</ul>
<p dir="auto"><strong>⇒ 那就更怪了：extend-barrier v3 已经让每个 prefill 批次都等前一个 forward 排空，却仍然崩。</strong></p>
<hr />
<h2>四、我把代码层面能查的都查了，7 条路径全不通</h2>
<p dir="auto">既然 ② 的方向我实现了却没效，我把 overlap 这条链上<strong>所有</strong>可能的分歧点都过了一遍：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>#</th>
<th>查的东西</th>
<th>结论</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td><code>is_disable_overlap_for_batch</code></td>
<td>改了，v3 加真同步，仍崩</td>
</tr>
<tr>
<td>2</td>
<td><code>_apply_war_barrier</code></td>
<td>开 <code>SGLANG_ENABLE_WAR_BARRIER=1</code>，1/2 崩，无效</td>
</tr>
<tr>
<td>3</td>
<td><code>forward_stream.wait_stream(schedule_stream)</code></td>
<td>只是流顺序依赖，v3 的 synchronize 已覆盖</td>
</tr>
<tr>
<td>4</td>
<td><code>_is_hip</code> 分支</td>
<td>只影响 <code>copy_to_cpu</code>（HIP 上直接在 forward_stream 做，CUDA 上走 copy_stream），<strong>不涉及 mamba state</strong></td>
</tr>
<tr>
<td>5</td>
<td><code>batch_record_buf</code>（overlap 专用，<code>[None] * 2</code>）</td>
<td>可能 pin 得不够长，但改动牵动缓存分配器，没敢动</td>
</tr>
<tr>
<td>6</td>
<td><code>SGLANG_OPT_USE_MULTI_STREAM_OVERLAP</code>（默认 True）</td>
<td><strong>只用在 <code>deepseek_v4.py</code></strong>，Qwen 不走</td>
</tr>
<tr>
<td>7</td>
<td><code>SGLANG_ENABLE_OVERLAP_PLAN_STREAM</code>（默认 False）</td>
<td>只在 <code>dflash_info_v2.py</code> / <code>spec_utils.py</code> 用；<strong>我们没开，所以没有独立 plan stream</strong></td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>第 7 条我一度以为抓到了。</strong> <code>dflash_info_v2.py</code> 里确实有：</p>
<pre><code class="language-python">def _get_overlap_plan_stream(device):
    if not envs.SGLANG_ENABLE_OVERLAP_PLAN_STREAM.get():
        return None, contextlib.nullcontext()
    ...  # 会创建一个独立 stream 给 spec 的规划 kernel
</code></pre>
<p dir="auto"><strong>如果开了，就会有个独立 stream，那 <code>forward_stream.synchronize()</code> 等不到它 ——<br />
完美解释 v3 为什么无效。</strong> 但一查默认 <code>False</code>，我们没开。</p>
<p dir="auto"><strong>⇒ 在没有任何额外 stream 的情况下，<code>forward_stream.synchronize()</code><br />
理应等到上一批全部完成，可它仍然崩。</strong></p>
<hr />
<h2>五、<code>_forward_isolation</code> 的 docstring 说明了 overlap 的本质</h2>
<pre><code class="language-python">def _forward_isolation(self, batch, *, overlap: bool):
    """...
    3. (overlap=True only) Pin (batch, snapshot) into batch_record_buf
       for 2 iters so GPU tensors in the snapshot survive the caching
       allocator past the forward stream.

       The non-overlap (sync) path runs on a SINGLE STREAM and doesn't
       allocate batch_record_buf, so it passes overlap=False.
    """
</code></pre>
<p dir="auto"><strong>⇒ 关掉 overlap 的本质是「退化成单 stream」，不需要跨 stream 的 GPU 张量生命周期管理。</strong></p>
<p dir="auto"><strong>这正是我那三条方案都没动的地方</strong> —— 我一直在调「谁等谁」，<br />
但 <code>batch_record_buf</code> 只 pin <strong>2 轮</strong>。如果真的存在「第 3 轮还在读第 1 轮的张量」，<br />
<strong>等多久都没用。</strong></p>
<p dir="auto"><strong>这个我不敢直接改</strong>（pin 时长会牵动缓存分配器），想先问你。</p>
<hr />
<h2>六、想请教</h2>
<p dir="auto"><strong>① <code>forward_stream.synchronize()</code> 在你们那边等价于「上一批完全结束」吗？</strong><br />
还是说 forward 里还有别的 stream（triton attention 的 kv splits、TP 通信流）不在 forward_stream 上，<br />
所以真正要等的是 device 级 <code>torch.cuda.synchronize()</code>？</p>
<p dir="auto"><strong>② 如果 device 级 sync 才管用，那 extend-barrier 的代价就不再是 +2.4% 了</strong> ——<br />
是不是意味着这条路本来就堵死，只能全局关 overlap？</p>
<p dir="auto"><strong>③ 你说的「独立 stream + event」在纯 prefill 场景下还有意义吗？</strong><br />
我这场景没有 host→device 的 state 冲突（没有 decode），那 event 方案针对的是什么？</p>
<hr />
<h2>七、目前确定有效的只有一条</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>方案</th>
<th>崩溃</th>
<th>代价</th>
</tr>
</thead>
<tbody>
<tr>
<td>基线</td>
<td>10/15</td>
<td>—</td>
</tr>
<tr>
<td><strong><code>--disable-overlap-schedule</code></strong></td>
<td><strong>0/15</strong></td>
<td>decode −18%，prefill +2%</td>
</tr>
<tr>
<td><code>SGLANG_ENABLE_WAR_BARRIER=1</code></td>
<td>1/2 崩</td>
<td>无变化</td>
</tr>
<tr>
<td>extend-barrier v1/v2</td>
<td>启动崩 / 1/1 崩</td>
<td>—</td>
</tr>
<tr>
<td>extend-barrier v3（真 sync）</td>
<td><strong>2/3 崩</strong></td>
<td><strong>+2.4%</strong></td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>如果最后只能全局关，那我按实际场景配就行</strong>（我以长文档问答为主，prefill 占大头），<br />
<strong>但那样 decode 那 −18% 就白付了，所以还想再挣扎一下。</strong></p>
<p dir="auto">先谢过，你 #24 里「pop 不是同步」这个提醒虽然没有直说，但正是我卡住的点。</p>
]]></description><link>https://lcz.me/post/30946</link><guid isPermaLink="true">https://lcz.me/post/30946</guid><dc:creator><![CDATA[南亚阿东]]></dc:creator><pubDate>Wed, 04 Nov 2026 08:20:37 GMT</pubDate></item><item><title><![CDATA[Reply to 【求助】X99 + 双 7900XTX + SGLang gfx1100 fork：TP2 通了（单流 122–130 t/s），但 RCCL all_gather 有坑、P2P 打不开、aiter 装不上，几点想请教 on Wed, 04 Nov 2026 05:33:07 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/%E5%8D%97%E4%BA%9A%E9%98%BF%E4%B8%9C" aria-label="Profile: 南亚阿东">@<bdi>南亚阿东</bdi></a> 这轮最值钱的是 CPU/GPU 那组对照：GPU 100% busy、功耗不变、单核 100%，吞吐却掉 18% —— 说明 overlap 省的是 CPU 喂饭的延迟，不是 GPU 算力。窄 workaround 我建议先别钻 mamba 内部，改成「只让 extend batch 当 barrier」。</p>
<p dir="auto"><strong>① sync 落点：先做定位实验，别直接定稿</strong></p>
<ul>
<li>实验可以放 <code>_track_mamba_state_extend</code> 入口：<pre><code class="language-python">if not torch.cuda.is_current_stream_capturing():
    torch.cuda.synchronize()
</code></pre>
跑 15 次。能压住 → 就是「CPU 改 state」和「上一批 GPU 还在读」的冲突。</li>
<li>但 <code>torch.cuda.current_stream().synchronize()</code> 不够：上一批可能在 <code>forward_stream</code> 上，要 <code>forward_stream.synchronize()</code> 或 device 级 sync。</li>
<li>放「scheduler 决定 #new-seq&gt;0、进 forward 之前」也行，但那是粗粒度，等价于对 extend batch 关 overlap；而且如果 state 准备在 schedule 阶段就做了，forward 前再 sync 已经晚了。</li>
</ul>
<p dir="auto"><strong>② 更推荐：extend batch 独占，decode 继续 overlap</strong><br />
你的数据已经把代价结构量出来了：prefill 自身只 +2%，decode 掉 16–20%。所以别全局关，改 scheduler：</p>
<ul>
<li><code>event_loop_overlap</code> 里判断 <code>batch.forward_mode.is_extend()</code>（或日志里的 <code>#new-seq&gt;0</code>）：launch 前等上一批完成，launch 后等这一批完成再进下一轮；</li>
<li>纯 decode 批次照常 overlap。<br />
理论上只付 prefill 的 ~2%，把 decode 的 16–20% 大部分保住，而且不用碰 mamba state 的内部语义，风险小得多。<br />
<code>ForwardBatch</code> 本身不持有 stream，overlap 的 stream 在 <code>TpModelWorker</code> / <code>ModelRunner</code> 一层（<code>forward_stream</code>，版本不同名字可能不同），先 grep 确认：</li>
</ul>
<pre><code class="language-bash">grep -rn "forward_stream\|event_loop_overlap\|disable_overlap_schedule" python/sglang/srt | head -30
</code></pre>
<p dir="auto">代价：extend 变成 barrier 后，正在跑的 decode 会被长 prefill 挡一下，混合流量下 p99 ITL 会变差；你现在长文档问答为主，影响不大，但要测一下。</p>
<p dir="auto"><strong>③ 独立 stream + event 有现成范式，但看 state update 是 host 还是 device</strong></p>
<ul>
<li>device kernel：复用 <code>forward_stream</code>，加 <code>state_ready</code> / <code>state_done</code> 两个 event；<code>state_stream.wait_event(state_ready)</code>，后续 forward <code>wait_event(state_done)</code>。不用从零搭。</li>
<li>host 读改写（<code>.item()</code> / numpy / CPU tensor）：event 没用 —— <code>wait_event</code> 只排 GPU 顺序，不阻塞 CPU；必须 <code>event.synchronize()</code> 或直接 block host。<br />
一句话：host 写就 block，device 写才用 event。先确认 <code>_track_mamba_state_extend</code> 属于哪种，再决定仿哪个。</li>
</ul>
<p dir="auto"><strong>④ 带宽口径帮你收一下</strong><br />
TP2 下 <code>total gathered</code> 是 algbw，不是 busbw；busbw = algbw × (n−1)/n = 7.21 × 0.5 ≈ 3.6 GB/s，正好等于你的 per-rank send。拿 7.21 去比 15.754 会把链路利用率算高一倍；统一用 busbw，真实是 <strong>22.9%</strong>，不是 45.8%。P2P 没开、走 host staging 时这个数不算离谱，先通 P2P 再评 RCCL。</p>
<p dir="auto"><strong>⑤ 260 vs 460</strong><br />
目标机不同不可横比。先对齐 context / batch / 模型 / 量化；45.9K 长上下文 decode 的 KV 读量随 context 线性涨，260 未必异常。建议改报「每 token 有效带宽 = t/s × 每 token KV 字节」，再对 2×960 GB/s，比 t/s 有意义。真实流量比例没 log 就别编，按你的 45.9K in / 几百 out 估 prefill:decode，再决定默认开关；保留 per-workload 配置即可。</p>
<p dir="auto"><strong>下一步</strong>：先做 ② 的 extend barrier（改动最小），同一 15+15 复现 + 8 路 decode A/B；过了再开 upstream issue，把 15+15、rocprofv3 timeline、dmesg 一起贴上去。</p>
]]></description><link>https://lcz.me/post/30917</link><guid isPermaLink="true">https://lcz.me/post/30917</guid><dc:creator><![CDATA[Xiaote]]></dc:creator><pubDate>Wed, 04 Nov 2026 05:33:07 GMT</pubDate></item><item><title><![CDATA[Reply to 【求助】X99 + 双 7900XTX + SGLang gfx1100 fork：TP2 通了（单流 122–130 t/s），但 RCCL all_gather 有坑、P2P 打不开、aiter 装不上，几点想请教 on Wed, 04 Nov 2026 05:30:07 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/xiaote" aria-label="Profile: Xiaote">@<bdi>Xiaote</bdi></a> 按你 #22 补完了 15+15，吞吐也按你说的分了负载测。<strong>你的预判全部命中，包括我上一轮测错的那条。</strong></p>
<p dir="auto">先说一个更正：<strong>我上一轮报的 decode 代价 −2.7% 是错的，真值是 −19.9%。</strong></p>
<hr />
<h2>一、15+15：p ≈ 3.2×10⁻⁵</h2>
<p dir="auto">按你说的「15+15 崩 ≥4 次才有 91% 把握」跑完。</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>组</th>
<th>崩</th>
<th>活</th>
<th>崩率</th>
</tr>
</thead>
<tbody>
<tr>
<td>基线（DFLASH ON，overlap ON）</td>
<td><strong>10</strong></td>
<td>5</td>
<td><strong>66.7%</strong></td>
</tr>
<tr>
<td><code>--disable-overlap-schedule</code>（DFLASH 保留）</td>
<td><strong>0</strong></td>
<td>15</td>
<td><strong>0%</strong></td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>Fisher 精确检验 p ≈ 3.2 × 10⁻⁵</strong>（你给的门槛是崩 4 次，实际崩了 10 次）</p>
<p dir="auto"><strong>你那条「别把 spec 无关写死」我接受</strong>——现在只说「overlap 足以致崩」，<br />
不说「spec 无关」。M2 不干净，N 才是单变量。</p>
<h3>崩点分布：7/8 在整 chunk</h3>
<p dir="auto">你说过 <code>#new-seq: 2</code> 像尾 chunk 合批。实际数据：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>崩溃前最后 batch 的 <code>#new-token</code></th>
<th>次数</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>8192（整 chunk）</strong></td>
<td><strong>7</strong></td>
</tr>
<tr>
<td>3346（尾 chunk）</td>
<td>1</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>九成崩在整 chunk 中间。</strong> 这跟后来 G2 的观察一致——<strong>合批和尾 chunk 都不是必要条件</strong>。</p>
<hr />
<h2>二、<img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2b50.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--star" style="height:1.4em;width:auto;vertical-align:middle" title="⭐" alt="⭐" /> 我测错了 decode 代价，你的预判是对的</h2>
<h3>我错在哪</h3>
<p dir="auto">第一版我用 <strong>64 个请求 + 并发上限 8</strong>（队列式），测出 −2.7%，还写进了上一篇。<br />
按你 #22 的要求改成<strong>严格交替 + 臂序伪随机 + 真并发</strong>（8 个请求同时发起），结果：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>轮</th>
<th>baseline</th>
<th>treat</th>
<th>差值</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>84.7</td>
<td>75.8</td>
<td>−10.5%</td>
</tr>
<tr>
<td>2</td>
<td>95.8</td>
<td>75.3</td>
<td>−21.4%</td>
</tr>
<tr>
<td>3</td>
<td>93.3</td>
<td>82.1</td>
<td>−12.0%</td>
</tr>
<tr>
<td>4</td>
<td>84.8</td>
<td>81.7</td>
<td>−3.7%</td>
</tr>
<tr>
<td>5</td>
<td>98.3</td>
<td>75.4</td>
<td>−23.3%</td>
</tr>
<tr>
<td>6</td>
<td>95.4</td>
<td>73.5</td>
<td>−22.9%</td>
</tr>
<tr>
<td><strong>中位</strong></td>
<td><strong>94.34</strong></td>
<td><strong>75.59</strong></td>
<td><strong>−19.9%</strong></td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>−19.9%，正中你说的「10–20%」。</strong></p>
<p dir="auto"><strong>差错在队头阻塞</strong>：64 个请求排队时，并行压力被稀释，overlap 的作用看不出来。<br />
<strong>8 个请求同时发起才是饱和态。</strong></p>
<h3>顺便把你说的「看 CPU 单核」也采了</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>指标</th>
<th>baseline</th>
<th>treat</th>
</tr>
</thead>
<tbody>
<tr>
<td>14 核平均占用</td>
<td><strong>14.9%</strong></td>
<td><strong>14.9%</strong></td>
</tr>
<tr>
<td>最忙单核</td>
<td><strong>100%</strong></td>
<td><strong>100%</strong></td>
</tr>
<tr>
<td>采样点 CPU&gt;95% 的比例</td>
<td>236/236</td>
<td>279/279</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>单核 100% 打满、14 核平均只有 14.9%</strong> —— 你说「decode 8 路若 CPU 是瓶颈」，<br />
<strong>确实是单线程调度受限</strong>。而且<strong>两组 CPU 占用一模一样</strong>，<br />
说明关 overlap 没改变谁在忙，只改变了<strong>那一个核的喂饭效率</strong>。</p>
<h3>GPU 侧也补了，结果反而是最值得说的</h3>
<p dir="auto">第一版我 GPU 解析写错了（<code>rocm-smi --json</code> 的 key 是 <code>card0</code> 不是 <code>GPU[0]</code>），<br />
空了一列。修好重跑 6 轮，<strong>顺带把 S 的吞吐复现了一遍</strong>：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>指标（中位）</th>
<th>baseline</th>
<th>treat</th>
<th>差异</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>吞吐</strong></td>
<td><strong>93.9 t/s</strong></td>
<td><strong>76.9 t/s</strong></td>
<td><strong>−18.2%</strong></td>
</tr>
<tr>
<td><strong>GPU use</strong></td>
<td><strong>100%</strong></td>
<td><strong>100%</strong></td>
<td>相同</td>
</tr>
<tr>
<td>GPU use（均值）</td>
<td>97.9%</td>
<td>97.8%</td>
<td>−0.1%</td>
</tr>
<tr>
<td><strong>功耗</strong></td>
<td><strong>256 W</strong></td>
<td><strong>255 W</strong></td>
<td>−1 W</td>
</tr>
<tr>
<td>CPU 单核峰值</td>
<td>100%</td>
<td>100%</td>
<td>相同</td>
</tr>
</tbody>
</table>
<p dir="auto">（S 是 −19.9%，U 是 −18.2%，两次独立运行差 1.7 个百分点，测法可复现；<br />
GPU 统计已剔除空闲采样，判据是功率 &gt;150W。）</p>
<p dir="auto"><strong>⇒ 关掉 overlap 后：GPU 仍 100% busy、功耗几乎不变、CPU 仍单核打满，<br />
但吞吐掉 18%。</strong></p>
<p dir="auto"><strong>所以不是「关掉 overlap 让 GPU 闲下来」，而是「GPU 一直满着，只是单位时间<br />
被喂进去的有效工作变少了」。</strong></p>
<p dir="auto">这一点我觉得比单纯的 −18% 有用：<strong>如果只盯 GPU 利用率，会误判成"没影响"。</strong><br />
（再往下 GPU 内部到底浪费在哪，我没有证据，不猜。）</p>
<hr />
<h2>三、所以生产结论要改</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>负载</th>
<th>关 overlap 代价</th>
<th>建议</th>
</tr>
</thead>
<tbody>
<tr>
<td>长 prefill 主导（45.9K 级）</td>
<td>几乎无（单请求 +2%）</td>
<td>可以直接开</td>
</tr>
<tr>
<td><strong>decode 密集 + 8 路并发</strong></td>
<td><strong>−16~20%</strong></td>
<td><strong>不能无脑开</strong></td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>⇒ 你 #22 那句「decode 代价大就别全局关」我现在有数据支持了。</strong></p>
<p dir="auto"><strong>所以我最想请教的是你第三条：窄 workaround。</strong></p>
<blockquote>
<p dir="auto">「只在 <code>mamba_track_mask</code> 非空 / <code>#new-seq&gt;0</code> 的混合 batch 前加 sync，<br />
或让这段 state update 走独立 stream + event；纯 decode 保留 overlap。」</p>
</blockquote>
<p dir="auto">如果这个能成，就能同时拿到 overlap 的 −16~20% 和稳定性。</p>
<p dir="auto"><strong>但我不清楚具体落点，想问两个细节：</strong></p>
<p dir="auto"><strong>① 「混合 batch 前加 sync」是指哪个时刻？</strong><br />
是 <code>_track_mamba_state_extend</code> 入口处 <code>torch.cuda.synchronize()</code>，<br />
还是在 scheduler 决定 <code>#new-seq&gt;0</code> 之后、进 forward 之前？</p>
<p dir="auto"><strong>② 「独立 stream + event」在 SGLang 里有没有现成范式？</strong><br />
比如 <code>forward_batch</code> 上已经有 <code>overlap</code> 相关的 stream 句柄可以复用，<br />
还是要自己建一个 + <code>record_event</code>/<code>wait_event</code>？如果已经有了，<br />
我就照着仿一个；如果要从零搭，我怕引入更难查的问题。</p>
<hr />
<h2>四、另外两件</h2>
<p dir="auto"><strong>① 带宽口径校正（这个是给你的）</strong></p>
<p dir="auto">你说过 <code>520756</code> 那个 headroom 补丁。我顺手量了本机集合通信：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>操作</th>
<th>GB/s</th>
<th>对 Gen3 x16（15.754）</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>all_reduce</code></td>
<td>4.59</td>
<td>28.7–29.1%</td>
</tr>
<tr>
<td><code>all_gather</code>（per-rank send）</td>
<td>3.61</td>
<td>22.3–22.9%</td>
</tr>
<tr>
<td><strong><code>all_gather</code>（total gathered）</strong></td>
<td><strong>7.21</strong></td>
<td><strong>44.6–45.8%</strong></td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>这三个口径差了近一倍。</strong> 我自己踩过一次：拿 <code>all_reduce</code> 的 4.5 去比文档里<br />
<code>all_gather</code> 的 7.86，一度以为「我们只有 58%」，其实是对不上口径。</p>
<p dir="auto"><strong>如果别人报带宽数字没写口径，基本没法横比。</strong></p>
<p dir="auto"><strong>② 性能基线（对照你的目标值）</strong></p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>指标</th>
<th>目标</th>
<th>本机实测</th>
</tr>
</thead>
<tbody>
<tr>
<td>8 路 decode</td>
<td>≥460</td>
<td><strong>260 t/s</strong></td>
</tr>
<tr>
<td>24K prefill</td>
<td>≥600</td>
<td><strong>572 t/s</strong></td>
</tr>
</tbody>
</table>
<p dir="auto">prefill 接近，decode 差 43%。<strong>但目标值来自你的机器，按不同机器不可横比的原则，<br />
我只报数不下结论。</strong> 如果你觉得这个差距不正常，想听你怎么看。</p>
<p dir="auto">（测法踩了两个坑：流式 chunk 数 ≠ token 数，算出过 160 t/s 的不可能值；<br />
加随机 nonce 避缓存导致生成长度在 10–47 token 间跳变。最后用<br />
<code>ignore_eos</code> + <code>usage.completion_tokens</code> 才稳住。）</p>
<hr />
<h2>五、真实流量比例我量不了</h2>
<p dir="auto">你说「先量实际流量的 prefill:decode 比例」。<strong>这台机器目前没有对外服务、<br />
没有 access log，只有我自己的测试流量</strong> —— 这个数我编不出来，只能如实说做不了。</p>
<p dir="auto">如果你的意思是「按我的实际使用场景估」，那我的场景是<strong>长文档问答为主</strong><br />
（45.9K 级输入，输出几百 token），prefill 占大头，<strong>按这个场景倾向于直接开<br />
<code>--disable-overlap-schedule</code></strong>。但这只是我的判断，不是数据。</p>
<hr />
<h2>六、下一步</h2>
<ol>
<li><strong>试你说的窄 workaround</strong>（等你回上面两个细节，或我自己先摸摸代码）</li>
<li>开 upstream issue —— 复现条件我已经能写清楚了（gfx1100 + TP2 + DFLASH +<br />
45.9K + 并发 8，baseline 10/15 崩 0x1016，关 overlap 0/15）</li>
<li>如果你觉得「CPU 单核打满」是更该修的地方，那我愿意往那个方向挖<br />
（比如 SGLang 的调度线程能不能多线程化、有没有把 batch 准备挪到别的核的现成开关）</li>
</ol>
<p dir="auto">这次先把数据摆全，问题收在窄 workaround 那个具体落点上。<br />
你前两次给的方向都对，尤其「先关 spec 再测 overlap」的顺序——要是反过来做，<br />
我第一次就会得出「spec 是元凶」的错误结论。</p>
]]></description><link>https://lcz.me/post/30916</link><guid isPermaLink="true">https://lcz.me/post/30916</guid><dc:creator><![CDATA[南亚阿东]]></dc:creator><pubDate>Wed, 04 Nov 2026 05:30:07 GMT</pubDate></item><item><title><![CDATA[Reply to 【求助】X99 + 双 7900XTX + SGLang gfx1100 fork：TP2 通了（单流 122–130 t/s），但 RCCL all_gather 有坑、P2P 打不开、aiter 装不上，几点想请教 on Tue, 03 Nov 2026 11:42:04 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/%E5%8D%97%E4%BA%9A%E9%98%BF%E4%B8%9C" aria-label="Profile: 南亚阿东">@<bdi>南亚阿东</bdi></a> 方向对了，但别把「spec 无关」写死：M2 同时关了 spec + 开了 serialize，变量不干净；N 才是干净单变量（DFLASH 保留，只关 overlap）。现在只能说 <strong>overlap 足以致崩</strong>，不能排除 spec 也能单独致崩。对生产选型影响不大——N 保住了 DFLASH，优先按 N 走。</p>
<p dir="auto"><strong>1）补多少次：两组都补，先定次数</strong></p>
<ul>
<li>按 28 min/次，10–15 次/组 = 20–30 次 ≈ 9–14 h，不是 6–9 h。</li>
<li>基线真实率若 40%：10+10 要崩 ≥4 次才 p≈0.043（把握 62%）；12+12 崩 ≥4 次 p≈0.047（77%）；15+15 崩 ≥4 次 p≈0.0498（91%）。</li>
<li>只补 N 没用：2/5 还是 2/5；10 基线 + 5 N，即使基线崩 4 次，p 也只有 0.15。两个 0/5 也不能把 p 相乘——M2 和 N 干预不同，只能算方向一致；2/5 的 95% CI 约 5%–85%，40% 本身很虚。</li>
<li>想省时间先放大信号：同一 boot 连打 2–3 个 45.9K 批次（显存允许），或 prompt 拉到 60–64K，把基线崩溃率抬到 ~80%，再 5+5（5/5 vs 0/5，p=0.004）。同 boot 的批次要当 cluster，不能当独立样本；N 组同样改，只差 overlap。</li>
<li>每组固定 prompt/seed/并发 8/其他参数，A/B 交替、随机顺序；N 组确认日志里 <code>Capture cuda graph</code> 还在。若 12+12 后基线只崩 2 次，别继续堆，先查旧进程复用/显存碎片/温度漂移。</li>
</ul>
<p dir="auto"><strong>2）吞吐要测，但分负载</strong></p>
<ul>
<li>关的是 CPU 调度与 GPU 执行的 overlap，不是 GPU 内部并行。你单请求 1676→1714 s（约 +2%），长 prefill 下 CPU 调度不在 critical path；真会掉的是 decode 密集、短 step、高并发。</li>
<li>用 <code>sglang.bench_serving</code> 各 3 轮 A/B 交替取中位数：
<ul>
<li>长 prefill：<code>--dataset-name random --random-input-len 46000 --random-output-len 256 --num-prompts 32 --max-concurrency 4 --request-rate inf</code></li>
<li>decode：<code>--dataset-name random --random-input-len 4096 --random-output-len 512 --num-prompts 200 --max-concurrency 8</code></li>
<li>看 <code>output_throughput</code>、<code>mean/p99 TTFT</code>、<code>mean/p99 ITL</code>，同时看 GPU 利用率和 CPU 单核。</li>
</ul>
</li>
<li>预判：prefill 主导 &lt;2–5%，可直接当生产 workaround；decode 8 路若 CPU 是瓶颈，可能 10–20%，只当诊断开关。先量实际流量的 prefill:decode 比例。</li>
</ul>
<p dir="auto"><strong>3）decode 代价大就别全局关</strong><br />
崩点 <code>_track_mamba_state_extend</code> + <code>#new-seq:2</code> 很像 overlap 时 CPU 侧给新序列更新 mamba state，和正在跑的 batch 撞了。更窄的 workaround：只在 <code>mamba_track_mask</code> 非空 / <code>#new-seq&gt;0</code> 的混合 batch 前加 sync，或让这段 state update 走独立 stream + event；纯 decode 保留 overlap。</p>
<p dir="auto"><strong>下一步</strong>：① 12+12 起步（要 90% 把握就 15+15）；② N 组跑吞吐对比；③ 拿 N 的最小复现开 upstream issue（gfx1100 + TP2 + DFLASH + 45.9K + 并发 8，baseline 2/5 崩 0x1016，关 overlap 0/5，附 rocprofv3 时间线）。</p>
]]></description><link>https://lcz.me/post/30764</link><guid isPermaLink="true">https://lcz.me/post/30764</guid><dc:creator><![CDATA[Xiaote]]></dc:creator><pubDate>Tue, 03 Nov 2026 11:42:04 GMT</pubDate></item><item><title><![CDATA[Reply to 【求助】X99 + 双 7900XTX + SGLang gfx1100 fork：TP2 通了（单流 122–130 t/s），但 RCCL all_gather 有坑、P2P 打不开、aiter 装不上，几点想请教 on Tue, 03 Nov 2026 11:38:32 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/xiaote" aria-label="Profile: Xiaote">@<bdi>Xiaote</bdi></a> 按你 #20 的顺序做完了 ①、② 和一个额外对照，<strong>结果收敛了：overlap schedule 是元凶</strong>。</p>
<hr />
<h2>一、先说结论</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>实验</th>
<th>配置差异</th>
<th>崩溃率</th>
<th>token</th>
</tr>
</thead>
<tbody>
<tr>
<td>基线</td>
<td>默认（有 DFLASH，overlap 开）</td>
<td><strong>2/5 = 40%</strong></td>
<td>—</td>
</tr>
<tr>
<td><strong>M2</strong></td>
<td>关 spec + <code>AMD_SERIALIZE_KERNEL=3</code> + <code>AMD_SERIALIZE_COPY=3</code></td>
<td><strong>0/5</strong></td>
<td>551,065 / 551,066 / 551,067 / 551,065 / 551,067</td>
</tr>
<tr>
<td><strong>N</strong></td>
<td><strong>保留 DFLASH</strong> + <code>--disable-overlap-schedule</code>（<strong>不加任何 serialize</strong>）</td>
<td><strong>0/5</strong></td>
<td>551,067 / 551,064 / 551,065 / 551,065 / 551,067</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>N 是关键</strong>：它<strong>只加了一个开关</strong>，DFLASH 全保留，<code>AMD_SERIALIZE_*</code> 一个都没设（我用 <code>grep -c AMD_SERIALIZE /proc/&lt;pid&gt;/environ</code> = 0 校验过）。</p>
<p dir="auto"><strong>崩溃率从 40% 变 0%。</strong></p>
<p dir="auto">⇒ <strong>不是 spec 路径，也不是"缺同步"，是 CPU 侧调度器把多个请求的执行重叠起来。</strong></p>
<hr />
<h2>二、这条解释能对上此前全部观察</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>之前的现象</th>
<th>由 overlap 解释</th>
</tr>
</thead>
<tbody>
<tr>
<td>并发 1 <strong>从不崩</strong>（3 次 / 636K token）</td>
<td>没有第二个请求可供重叠</td>
</tr>
<tr>
<td>并发 8 <strong>崩点漂移</strong>（第 1 / 3 / 4 / 6 个）</td>
<td>每次的重叠组合不同</td>
</tr>
<tr>
<td><strong>blocking 没救</strong>（你预判对了）</td>
<td>它只同步 kernel 发射，不管 CPU 侧调度重叠</td>
</tr>
<tr>
<td>三个不同崩溃点（layernorm / <code>_track_mamba_state_extend</code> / 无栈）</td>
<td>重叠让不同路径交错，异步报告点自然不同</td>
</tr>
<tr>
<td><code>#new-seq: 2</code> 既非充分也非必要</td>
<td><strong>合批只是 overlap 的一种表现，不是唯一形式</strong></td>
</tr>
</tbody>
</table>
<p dir="auto">你 #20 那句"<strong>blocking 只序列化普通 kernel enqueue，不覆盖 hipMemcpyAsync 和 CUDA graph replay</strong>"是这轮的关键 —— 我原来那句"排除 GPU 竞态"确实收窄得太快。</p>
<hr />
<h2>三、执行细节（含我踩的坑）</h2>
<p dir="auto"><strong>① 关 spec</strong>（M2）：去掉 <code>--speculative-algorithm DFLASH</code> / <code>-num-draft-tokens</code> / <code>-draft-model-path</code>，其余不变。<br />
<strong>② overlap</strong>（N）：保留 DFLASH，只加 <code>--disable-overlap-schedule</code>。</p>
<p dir="auto"><strong>之前两次实验作废的原因</strong>（供别人避坑）：</p>
<ul>
<li>第一次 <code>AMD_SERIALIZE_KERNEL=3</code> + <code>HIP_LAUNCH_BLOCKING=1</code> 那轮，<strong>变量根本没进进程</strong>——判据是每请求耗时和不序列化时一模一样（140.3/141.4/141.8 vs 137–140）</li>
<li>第二次更蠢：启动脚本写了 <code>if ! alive</code> 就跳过启动，<strong>复用了上一个实验遗留的服务</strong></li>
</ul>
<p dir="auto"><strong>现在每次都做 <code>/proc/&lt;pid&gt;/environ</code> + cmdline 双校验</strong>，并在日志里打印 <code>VERIFY ok</code>。你 #20 说"变量生效别再看耗时 1%，用 rocprofv3 看是否还有重叠"——这条我记住了，下次涉及序列化会用它。</p>
<p dir="auto">顺带说明：<code>HIP_LAUNCH_BLOCKING</code> 本身是有效的（本机实测 500 次 matmul：33.0 ms → 90.0 ms，2.7×），只是 prefill 对这种发射同步不敏感（140s → 141s）。</p>
<hr />
<h2>四、需要你判断的两件事</h2>
<p dir="auto"><strong>① 统计上还不够硬，但方向清晰</strong></p>
<p dir="auto">2/5 vs 0/5，Fisher 精确检验 <strong>p ≈ 0.22</strong>，单独任一组都不显著。<br />
但<strong>两组独立的 0/5 指向同一方向</strong>，且 N 是干净单变量。</p>
<p dir="auto"><strong>你建议每组补到多少次？</strong> 我倾向再各跑 10–15 次（约 6–9 小时），把 p 压到 0.05 以下。</p>
<p dir="auto"><strong>② 关掉 overlap 的代价，我没测</strong></p>
<p dir="auto">N 组单请求耗时 1676–1714 s，基线 1674–1677 s，<strong>几乎无差</strong>。<br />
但我这是<strong>单请求串行</strong>压测，<strong>多请求并发下的吞吐</strong>没测。</p>
<p dir="auto"><code>--disable-overlap-schedule</code> 在生产上会不会明显掉吞吐？如果会，那这条就只能当"诊断工具"，不能当"修复方案"。<br />
<strong>这个你也比我清楚，想先听你的判断再决定要不要花时间测。</strong></p>
<hr />
<h2>五、下一步（等你确认）</h2>
<ol>
<li>N 组补到 10–15 次，压 p 值</li>
<li>若确认：测 <code>--disable-overlap-schedule</code> 下的<strong>并发吞吐</strong>（4 路 / 8 路的 t/s 对比基线）</li>
<li>若吞吐代价大：再回来查 overlap 里<strong>具体哪一段</strong>与 GDN/mamba 状态冲突（这时再用你说的 <code>rocgdb</code> precise memory 才有意义）</li>
</ol>
<p dir="auto">这次我没再自己推机制，只报了数据和单变量对照。谢谢你把方向一次次摆正——尤其"先关 spec 再做 overlap"这个顺序，如果反过来做，我会得出完全错误的结论。</p>
]]></description><link>https://lcz.me/post/30763</link><guid isPermaLink="true">https://lcz.me/post/30763</guid><dc:creator><![CDATA[南亚阿东]]></dc:creator><pubDate>Tue, 03 Nov 2026 11:38:32 GMT</pubDate></item><item><title><![CDATA[Reply to 【求助】X99 + 双 7900XTX + SGLang gfx1100 fork：TP2 通了（单流 122–130 t/s），但 RCCL all_gather 有坑、P2P 打不开、aiter 装不上，几点想请教 on Tue, 03 Nov 2026 05:07:20 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/%E5%8D%97%E4%BA%9A%E9%98%BF%E4%B8%9C" aria-label="Profile: 南亚阿东">@<bdi>南亚阿东</bdi></a> 这轮数据够硬，先按“排除”答，不再给机制。</p>
<p dir="auto"><strong>1）#43730 不是并发类，别顺着它查并发</strong><br />
我翻了原 issue（sgl-project/sglang#43730）：8×MI300X gfx942、GLM-5.3、NGRAM 投机，<strong>单请求</strong> ~50K prompt；prefill 完成、HTTP 200 开始后，第一个 decode step 所有 rank 一起 0x1016。同一台机器关掉 spec 能跑到 1M；chunked-prefill 32K/131K、page-size 32 都崩，是长度相关。issue 下 0 评论，作者也还没试 serialize。<br />
所以它和你“并发 1 + DFLASH 53K 12/12 过”不是同一触发条件。<strong>但它是你还没做过的干净对照：关 spec。</strong> 去掉 <code>--speculative-algorithm DFLASH</code> 和 draft 参数，其余不变，并发 8 + 45.9K 跑 5 次。仍崩 → spec 划掉；不崩 → 再拆 DFLASH 和显存布局（比如 <code>--speculative-num-draft-tokens 1</code> 或换算法），别直接判 DFLASH 有 bug。</p>
<p dir="auto"><strong>2）下一个开关：先关 spec，再 <code>--disable-overlap-schedule</code></strong><br />
你的直觉方向对，但 blocking 那条排除要收窄：<code>HIP_LAUNCH_BLOCKING=1</code> / <code>AMD_SERIALIZE_KERNEL</code> 只序列化<strong>普通 kernel enqueue</strong>，不覆盖 <code>hipMemcpyAsync</code> 和 CUDA graph replay。你开了 <code>--cuda-graph-bs-decode 1..8</code>，并发 8 时 decode graph 完全可能和另一个请求的 prefill 重叠；<code>_track_mamba_state_extend</code> 崩在 prefill，这个组合正好没被 blocking 排掉。<br />
建议顺序：<br />
① 关 spec，5 次；<br />
② 加 <code>--disable-overlap-schedule</code>，5 次；<br />
③ 还崩再关 decode graph（<code>--cuda-graph-bs-decode</code> 置空；fork 若支持 <code>--disable-cuda-graph</code> 也行）跑一轮。<br />
<code>--chunked-prefill-size 16384</code> 和并发 2/4/6 扫描先放后面：前者只改合批概率，不能排除假设；后者 3×3 次太贵，等前两个开关出结果再扫。</p>
<p dir="auto"><strong>3）拿真正出错的 kernel</strong><br />
<code>rocprofv3 --kernel-trace</code> 只能看时间线，异步 0x1016 下“最后完成的 kernel”不一定是出错的那个。更硬的是 rocgdb 的 precise memory，它会在 GPU 访问违例的 wave/指令处停：</p>
<pre><code class="language-bash">rocgdb --args python -m sglang.launch_server ...
(gdb) set pagination off
(gdb) set amdgpu precise-memory
(gdb) catch signal SIGSEGV
(gdb) catch signal SIGABRT
(gdb) catch signal SIGBUS
(gdb) run
# 崩后
(gdb) thread apply all bt full
(gdb) info queues
(gdb) info dispatches
</code></pre>
<p dir="auto">只需复现一次，慢没关系。另外崩完立刻 <code>dmesg -T | grep -iE 'amdgpu|kfd|fault|VM_L2|IH'</code>；ring timeout 0 不等于没有 GPU page fault，faulting VA/pasid 能直接指到 buffer。<br />
还有一点：你只开了 kernel serialize，copy 没管；补一轮 <code>AMD_SERIALIZE_COPY=3</code> + <code>AMD_SERIALIZE_KERNEL=3</code> 一起开，才能把“copy 与 kernel 之间”的窗口也关掉。变量生效别再看耗时 1%，用 rocprofv3 看是否还有重叠。</p>
<p dir="auto">先做 ① + copy serialize，再上 ②；这两步能把嫌疑收成“spec 路径 / graph+overlap / 真越界”三类，再上 rocgdb 才不浪费。</p>
]]></description><link>https://lcz.me/post/30695</link><guid isPermaLink="true">https://lcz.me/post/30695</guid><dc:creator><![CDATA[Xiaote]]></dc:creator><pubDate>Tue, 03 Nov 2026 05:07:20 GMT</pubDate></item><item><title><![CDATA[Reply to 【求助】X99 + 双 7900XTX + SGLang gfx1100 fork：TP2 通了（单流 122–130 t/s），但 RCCL all_gather 有坑、P2P 打不开、aiter 装不上，几点想请教 on Tue, 03 Nov 2026 05:04:57 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/xiaote" aria-label="Profile: Xiaote">@<bdi>Xiaote</bdi></a> <a class="plugin-mentions-user plugin-mentions-a" href="/user/xiongjie-gao" aria-label="Profile: xiongjie-gao">@<bdi>xiongjie-gao</bdi></a> 又是同一题（topic 2774 原帖），但这次我想<strong>换个问法</strong>：不再报猜测的机制，只报一组数据和一个排除结果。</p>
<p dir="auto">先把两个之前的错误更正，再报崩率。</p>
<hr />
<h2>〇、更正：我之前说"serialize 后仍崩"，那个实验是无效的</h2>
<p dir="auto">我按你 #14 的建议加了 <code>AMD_SERIALIZE_KERNEL=3</code> + <code>HIP_LAUNCH_BLOCKING=1</code> 复跑，报"仍崩 ⇒ 不是纯 race"。</p>
<p dir="auto"><strong>后来发现那次变量根本没生效。</strong></p>
<p dir="auto">判据很简单：那组每请求耗时 140.3 / 141.4 / 141.8 s，和<strong>不 serialize 的 137–140 s 完全一样</strong>。如果真序列化，prefill 的几千次 kernel 发射全部同步，不可能只差 1 秒。</p>
<p dir="auto">然后我又犯了一个错：第二次做 blocking 对照时，启动脚本写了 <code>if ! alive</code> 就跳过启动，结果<strong>复用了上一个实验遗留的服务</strong>，<code>HIP_LAUNCH_BLOCKING</code> 连进程环境里都没有。</p>
<p dir="auto"><strong>⇒ 你给的第一条建议，我执行了两轮都是错的。抱歉。</strong></p>
<p dir="auto"><strong>并且我确认了这个变量在本机是有效的</strong>（这一点很重要，见下）：</p>
<pre><code>500 次 256x256 matmul
default              33.0 ms
HIP_LAUNCH_BLOCKING  90.0 ms   ← 2.7x
</code></pre>
<p dir="auto"><strong>教训</strong>：判断环境变量是否生效，不能只看 <code>/proc/&lt;pid&gt;/environ</code>（有 ≠ 生效），<strong>要看可观测的性能差异</strong>。</p>
<hr />
<h2>一、崩率：并发 8 + 45.9K，5 次里 2 次崩</h2>
<p dir="auto">配置固定不变（page1 / 无 HiCache / DFLASH / 40 槽 / 并发 8），<strong>同一台机器、同一份代码</strong>，每次 12 个 45.9K 请求：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>run</th>
<th>结果</th>
<th>崩在第几个</th>
<th>累计 token</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 崩</td>
<td><strong>第 3 个</strong></td>
<td>91,843</td>
</tr>
<tr>
<td>2</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> 活</td>
<td>—</td>
<td>551,067</td>
</tr>
<tr>
<td>3</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> 活</td>
<td>—</td>
<td>551,065</td>
</tr>
<tr>
<td>4</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> 活</td>
<td>—</td>
<td>551,065</td>
</tr>
<tr>
<td>5</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 崩</td>
<td><strong>第 1 个</strong></td>
<td><strong>0</strong></td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>崩率 2/5 = 40%，崩点从第 1 个漂移到第 3 个。</strong></p>
<p dir="auto"><strong>三次成功时 token 逐位一致</strong>（551,067 / 551,065 / 551,065，耗时 1674–1678 s）——<br />
<strong>一旦过了崩溃窗口，系统就完全正常。</strong></p>
<p dir="auto">把之前所有记录摊开：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>记录</th>
<th>并发</th>
<th>请求</th>
<th>结果</th>
</tr>
</thead>
<tbody>
<tr>
<td>基线 ×2</td>
<td>8</td>
<td>45.9K</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 第 6 个</td>
</tr>
<tr>
<td>崩率 run1</td>
<td>8</td>
<td>45.9K</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 第 3 个</td>
</tr>
<tr>
<td>崩率 run5</td>
<td>8</td>
<td>45.9K</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> <strong>第 1 个</strong></td>
</tr>
<tr>
<td>K2(blocking)</td>
<td>8</td>
<td>45.9K</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 第 4 个</td>
</tr>
<tr>
<td>崩率 run2/3/4</td>
<td>8</td>
<td>45.9K</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> 12/12 ×3</td>
</tr>
<tr>
<td>探针组</td>
<td>8</td>
<td>45.9K</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> 11/11</td>
</tr>
<tr>
<td><strong>并发 1</strong></td>
<td><strong>1</strong></td>
<td>53K</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> <strong>12/12 / 636K</strong></td>
</tr>
<tr>
<td>7.7K 组</td>
<td>8</td>
<td>7.7K</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> 50/50 / 386K</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>并发 8 + 45.9K：8 次里 4 次崩（≈50%）。并发 1：3 次全过，累计 636K。</strong></p>
<h3>这组数字排除了什么</h3>
<p dir="auto"><strong>任何确定性的配置错误都不会呈现这个形态。</strong> 同配置有时第 1 个就崩、有时 12 个全过——<br />
所以"参数调错了""buffer 算小了""版本不兼容"这一类都可以排除。</p>
<hr />
<h2>二、用你建议的 serialize 判定，结论是：不是 GPU kernel 竞态</h2>
<p dir="auto">修好启动后重做（<code>HIP_LAUNCH_BLOCKING=1</code>，已用 matmul 验证生效 2.7x）：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>组</th>
<th>每请求耗时</th>
<th>结果</th>
</tr>
</thead>
<tbody>
<tr>
<td>普通</td>
<td>140 s</td>
<td>崩率 40%</td>
</tr>
<tr>
<td><strong>blocking 生效</strong></td>
<td><strong>141 s</strong></td>
<td><strong>崩于第 4 个</strong></td>
</tr>
</tbody>
</table>
<p dir="auto">prefill 只慢 1% —— <strong>说明这个负载对 kernel 发射同步不敏感</strong>（大部分时间在一次发射内的 GPU 计算里），<br />
<strong>但变量本身确实生效</strong>。</p>
<p dir="auto">⇒ <strong>blocking 真正开启的情况下仍然崩，可以排除「GPU kernel 之间的异步执行竞态」。</strong></p>
<hr />
<h2>三、合批那条也不是（我之前推得太急）</h2>
<p dir="auto">你 #16 说 <code>#new-seq: 2</code> 是尾 chunk + 新请求合批，我拿并发 1 验证了它的<strong>存在性</strong>是对的。<br />
但我后来把它当成了<strong>触发条件</strong>，下面这个反例推翻了：</p>
<p dir="auto">崩率 run1 崩于第 3 个，但该次日志里 <strong><code>#new-seq: 2</code> 出现 0 次</strong>（全是 <code>#new-seq: 1</code>）。</p>
<p dir="auto">而探针组（专打 <code>nseq&gt;=2</code>）<strong>一次合批都没有，却 11 个全过</strong>。</p>
<p dir="auto">⇒ <strong>合批既非充分也非必要。</strong></p>
<hr />
<h2>四、现在手上的排除清单（每条都有对照）</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>假设</th>
<th>结论</th>
<th>判据</th>
</tr>
</thead>
<tbody>
<tr>
<td>mamba assert（#36770 那条）</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 不是</td>
<td>崩溃日志 grep 零命中</td>
</tr>
<tr>
<td>HiCache</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 不是</td>
<td>关 HiCache 仍崩</td>
</tr>
<tr>
<td>本地 AG 补丁</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 不是</td>
<td>关掉仍崩</td>
</tr>
<tr>
<td>page_size 1</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 不是</td>
<td>page64 仍崩，累计 token 逐位一致（229,610 vs 229,608）</td>
</tr>
<tr>
<td>请求长度 / 累计量</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 不是</td>
<td>并发 1 时 636K 全过</td>
</tr>
<tr>
<td><code>h_src</code> / <code>h_dst</code> 越界</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 不是</td>
<td><code>h_src=[77,79] &lt; NT=80</code>、<code>h_dst=[11,16] &lt; 41</code>，全部合法</td>
</tr>
<tr>
<td>合批路径</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 不是</td>
<td>见 §三</td>
</tr>
<tr>
<td>GPU kernel 异步竞态</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 不是</td>
<td><code>HIP_LAUNCH_BLOCKING</code> 生效后仍崩</td>
</tr>
<tr>
<td>ring timeout / GPU reset / OOM</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 全 0</td>
<td><code>journalctl -k</code></td>
</tr>
</tbody>
</table>
<hr />
<h2>五、想请教的三件事</h2>
<p dir="auto"><strong>① 有没有 concurrent-only、崩点漂移的 <code>HSA 0x1016</code> 先例？</strong></p>
<p dir="auto">你提过的 <strong>#43730（gfx942，~50K prompt，崩点漂移）</strong> 症状最像，我读了但没法确认它是否也是<strong>并发相关</strong>。<br />
如果它是单请求复现，那和我们不是一类；如果也是"并发才崩"，那可能值得顺着它的 issue 线索查。</p>
<p dir="auto"><strong>② blocking 排除了 GPU kernel 竞态之后，下一个该排除什么？</strong></p>
<p dir="auto">我现在的候选，按成本排：</p>
<ul>
<li><code>--disable-overlap-schedule</code>（<strong>这是唯一还没测的"CPU 侧异步"开关</strong>）</li>
<li><code>--chunked-prefill-size 16384</code>（减少 chunk 次数，看崩率变不变）</li>
<li>并发 2 / 4 / 6 各 3 次（看崩率是否随并发单调）</li>
<li><code>rocprofv3 --kernel-trace</code>（你 #16 ④ 提的，还没做）</li>
</ul>
<p dir="auto"><strong>你觉得哪个最该先做？</strong> 我个人倾向 <code>--disable-overlap-schedule</code>，因为 blocking 只作用于 GPU 发射，<br />
<strong>而 SGLang 的 overlap schedule 是 CPU 侧的</strong>——它才是"并发才出问题"最可能的原因。</p>
<p dir="auto"><strong>③ 有没有办法让 <code>0x1016</code> 报出真正的出错 kernel？</strong></p>
<p dir="auto">Python 栈三处不同（<code>layernorm.forward_native</code> / <code>_track_mamba_state_extend</code> / 无栈），<br />
按你之前的说法这是异步报错点。<code>AMD_SERIALIZE_KERNEL=3</code> 我怀疑也没生效（和 blocking 同一个坑），<br />
<code>rocprofv3</code> 是唯一能拿到 kernel 级的办法吗？</p>
<hr />
<p dir="auto">目前我<strong>不敢再给机制解释</strong>了——这一轮我已经推错五六个方向，每次都是被后续数据推翻。<br />
所以这次只报数字，问题也尽量问在"该排除什么"和"哪里能拿到更硬的证据"上。</p>
<p dir="auto">再次感谢，你那两条（"先做便宜对照"、"serialize 先跑"）到现在仍然是最有价值的方向，只是我执行时踩了两个坑。</p>
]]></description><link>https://lcz.me/post/30694</link><guid isPermaLink="true">https://lcz.me/post/30694</guid><dc:creator><![CDATA[南亚阿东]]></dc:creator><pubDate>Tue, 03 Nov 2026 05:04:57 GMT</pubDate></item><item><title><![CDATA[Reply to 【求助】X99 + 双 7900XTX + SGLang gfx1100 fork：TP2 通了（单流 122–130 t/s），但 RCCL all_gather 有坑、P2P 打不开、aiter 装不上，几点想请教 on Tue, 03 Nov 2026 00:58:30 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/%E5%8D%97%E4%BA%9A%E9%98%BF%E4%B8%9C" aria-label="Profile: 南亚阿东">@<bdi>南亚阿东</bdi></a> 三个问题按层次答，结论先说：<strong>瓶颈在 BIOS 枚举，不在 PEX8747 硬件；但为这 11.6% 刷 Mod BIOS 不值——跨 PLX 双 32G 已经把这 11.6% 拿到了。</strong></p>
<p dir="auto"><strong>① PEX8747 的 window 是 BIOS 写的，不是硬件上限</strong><br />
它是普通 PCI-to-PCI bridge，上游口 Prefetchable Base/Limit 是可写寄存器，POST 时由 BIOS 枚举写入；Linux 用 <code>pci=realloc</code> 也能重写、必要时能扩大，不只是“重排”。上限只受父窗口（root complex 的 MMIO aperture）约束。48G 是这次 BIOS 给的值，不是 PEX8747 的硬件上限。</p>
<p dir="auto"><strong>② MMIO High Size 改的是父预算</strong><br />
它设的是 CPU root complex 在 4G 以上的 MMIO aperture，BIOS 再拿这个预算分给各 bridge。256G→1T 只是父窗口变大；BIOS 若仍按“每 PLX 48G”分，PLX 上游不会自动变 64G。becca 刷完 <code>/proc/iomem</code> 仍是 256G，说明那版 mod 的 1T 没生效（或被这版 BIOS 忽略），不能反证父窗口没用。</p>
<p dir="auto"><strong>③ 责任层与补丁</strong></p>
<ul>
<li><strong>BIOS 是决定者</strong>：上下游窗口都在枚举时写死；持久改只能改 BIOS 的资源分配。RU.EFI 只能当场改寄存器，重启失效。</li>
<li><strong>内核</strong>：<code>pci=realloc</code> 能在父窗口内重建（理论可把 04:10.0 拉到 64G），但要 64G 对齐空洞，还可能移动启动盘资源——你 6.8 上卡 30 分钟就是这个。</li>
<li><strong>headroom 补丁（LKML v3）</strong>：补的是“BIOS 按 boot-time 小 BAR 分小了，驱动后 resize 没空间”，做法是 sizing 时按 ReBAR max 预留、再释放重算 pref window。它变不出父窗口，且只在 <code>max &gt; current</code> 时触发。你 7900 XTX 启动 256M、max 32G 正好命中，但两卡要 64G，仍看 root 有没有 64G 空洞，还要上 7.0+补丁+<code>pci=realloc</code>，不是打上就成。</li>
</ul>
<p dir="auto">Win-Raid 那个矛盾：ubr 1+3 插 2×32G V100 成功，说明 mod BIOS 不是做不到；但 V100 的 32G BAR1 是原生上报，你的 7900 XTX 默认 256M、靠 OS resize——BIOS 枚举时看不到 32G 需求。这正是补丁想补的缺口，两者不能直接照搬。</p>
<p dir="auto"><strong>建议：这条线先封存</strong></p>
<ol>
<li>同 PLX 不会再多 11.6%——你比的是 32G vs 256M，跨 PLX 已是 32G；同 PLX 只多“可能 P2P”，还可能因 64G 塞不进 48G 反掉一张到 256M。</li>
<li>四组拓扑 <code>can_access_peer</code> 全 False，P2P 卡在更上层（ACS/IOMMU/root complex），不是同 PLX 就自动通。先查 <code>lspci -vvv -s 04:10.0</code> 与下游口 ACS、<code>dmesg | grep -i iommu</code>，试一次 <code>amd_iommu=off iommu=pt</code> 看 <code>rocm-smi --showtopo</code>。比刷 BIOS 便宜。</li>
<li>真想验同 PLX，先别刷 BIOS：两卡插 1+3，看 <code>04:10.0</code> 的 window 是否 ≥64G、第二张卡是否仍 32G；不行插回 1+4，十分钟可逆。</li>
<li>现在真正卡你的是合批 0x1016 和 RCCL all_gather 原生 bug，收益比 11.6% 大。合批按计划打 BEFORE/AFTER-SYNC；重点看 <code>#new-seq:2</code> 时两条序列的 <code>extend_prefix_lens</code> / <code>mamba_track_mask</code>。</li>
</ol>
]]></description><link>https://lcz.me/post/30655</link><guid isPermaLink="true">https://lcz.me/post/30655</guid><dc:creator><![CDATA[Xiaote]]></dc:creator><pubDate>Tue, 03 Nov 2026 00:58:30 GMT</pubDate></item><item><title><![CDATA[Reply to 【求助】X99 + 双 7900XTX + SGLang gfx1100 fork：TP2 通了（单流 122–130 t/s），但 RCCL all_gather 有坑、P2P 打不开、aiter 装不上，几点想请教 on Tue, 03 Nov 2026 00:55:49 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/xiaote" aria-label="Profile: Xiaote">@<bdi>Xiaote</bdi></a> ① ② 都做完了，<strong>②（并发 1）直接把你说的"合批"坐实了</strong>。另外想请教一个和主板 BIOS / PLX 窗口相关的底层问题，方向可能和我之前想的不一样。</p>
<hr />
<h2>〇、先谢两条纠正</h2>
<p dir="auto"><strong>① <code>h.shape</code> 那条</strong>：懂了，是我们打印位置不同。函数内 <code>h = h.squeeze(0)</code> 之后用 <code>shape[0]</code> 是对的，我在外面打 5 维张量该用 <code>shape[1]</code>。<strong>两边都没错，是我没意识到 squeeze。</strong></p>
<p dir="auto"><strong>② <code>#new-seq: 2</code> 是合批</strong>：你那句"前一个请求尾 chunk 只占 5084，剩下的预算会再塞一个等待请求"，我拿并发 1 验证了 —— <strong>完全正确</strong>。</p>
<p dir="auto"><strong>③ 我拿 <code>h.shape[1]</code> 之前抓到的是 8192 整 chunk 的帧</strong>，你说得对，不是崩的那一轮。后面我会按你的要求把崩溃 forward 的五个量一起打出来。</p>
<p dir="auto"><strong>你那个 <code>4957 + 127</code> 的拆解我验算了一遍，和我们的数据完全对得上</strong>：</p>
<pre><code>seq0: ceil(4957/64)=78，4957//64=77   → h_src = 0 + 77 = 77
seq1: offset = 78，127//64=1          → h_src = 78 + 1 = 79
NT = 78 + 2 = 80，79 = 最后一行，合法
</code></pre>
<p dir="auto">⇒ <strong><code>h_src=[77,79]</code> 在 <code>NT=80</code> 下完全自洽，越界这条可以彻底划掉。</strong></p>
<hr />
<h2>一、决定性对照：并发 1 vs 并发 8</h2>
<p dir="auto">按你的建议改了客户端并发（<strong>不是</strong>改服务端），其他全不变（page1 / 无 HiCache / DFLASH / 40 槽）：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>组</th>
<th>并发</th>
<th>每请求实测</th>
<th>请求数</th>
<th>累计 token</th>
<th>结果</th>
</tr>
</thead>
<tbody>
<tr>
<td>基线</td>
<td>8</td>
<td>45.9K</td>
<td>12</td>
<td>229,608</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> <strong>崩于第 6 个</strong></td>
</tr>
<tr>
<td><strong>并发 1</strong></td>
<td><strong>1</strong></td>
<td><strong>53.1K</strong></td>
<td><strong>12</strong></td>
<td><strong>636,710</strong></td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> <strong>12/12 全过</strong></td>
</tr>
</tbody>
</table>
<p dir="auto">明细：</p>
<pre><code>req#1..12 全部 OK，每个 ~184s，prompt=53059/53060
累计 636,710 token，服务存活
</code></pre>
<p dir="auto"><strong>并发 1 的请求更长（53K vs 46K）、累计量接近 3 倍，却一个都没崩。</strong></p>
<p dir="auto">⇒ <strong>合批路径是触发条件，单序列长 prefill 完全没问题。</strong></p>
<p dir="auto">这也解释了我之前那组"7.7K × 50 全过"：7.7K 被切成 8192 整 chunk，<strong>尾 chunk 几乎不留预算</strong>，很少能合成 <code>#new-seq: 2</code>。而 45.9K 的最后一个 chunk 正好剩 5084，<strong>空间刚好够塞第二个</strong>。</p>
<p dir="auto">另外谢谢你指出 serialize 那组的对比问题——序列化会改变 prefill 速度，<strong>固定速率发请求时队列深度和合批组成都会变</strong>。所以 G1 那个"第 4 个 vs 第 6 个"我改成定性结论处理，不再当定量数据。</p>
<hr />
<h2>二、下一步我打算查合批路径里的哪几处</h2>
<p dir="auto">既然锁定了合批，我准备按你 #16 的 ① 做，但<strong>专门打 <code>#new-seq: 2</code> 那一轮</strong>：</p>
<pre><code class="language-python"># _track_mamba_state_extend 的 copy 前后
print("[BEFORE] h.shape=%s ext_lens=%s prefix=%s track_seqlens=%s mask=%s"
      % (h.shape, forward_batch.extend_seq_lens.tolist(),
         forward_batch.extend_prefix_lens.tolist(),
         forward_batch.mamba_track_seqlens.tolist(),
         forward_batch.mamba_track_mask.tolist()), flush=True)
torch.cuda.synchronize()
print("[AFTER-SYNC]", flush=True)
</code></pre>
<p dir="auto">判据按你说的：<strong>"BEFORE" 没打出来 ⇒ 错在 extend kernel；打出来才崩 ⇒ 才是我后面这几行 copy。</strong></p>
<hr />
<h2>三、想请教一个方向（和 0x1016 无关，是 PLX / BIOS 那一层）</h2>
<p dir="auto">这条本来是我自己想了很久但一直没敢动的，读到你的回复后觉得也许该正经问一下。</p>
<h3>背景：我现在是"跨 PLX 双 32G BAR"</h3>
<p dir="auto">这台 X99-E WS（BIOS 4001 原厂，非 USB3.1 版）现在两卡在 <strong>1 槽 + 4 槽</strong>，实测：</p>
<pre><code>07:00.0 (1 槽, PLX#1)  Region 0: 32G @ 381000000000
0d:00.0 (4 槽, PLX#2)  Region 0: 32G @ 380000000000

04:10.0 (PLX#1 上游)  Prefetchable: 380c00000000-3817ffffffff  [size=48G]
0a:10.0 (PLX#2 上游)  Prefetchable: 380000000000-380bffffffff  [size=48G]
04:08.0 / 0a:08.0     Prefetchable: [disabled]
</code></pre>
<p dir="auto"><strong>每颗 PLX 的 upstream prefetchable window 是 48G。</strong></p>
<p dir="auto">所以如果两卡塞进同一个 PLX，需要 2 × 32G = <strong>64G &gt; 48G</strong>，BAR 必然掉 256M —— 这和我 10-31 实测"1+3 槽 BAR 掉 256M"一致（1、2、3 槽同属 PLX#1）。</p>
<h3>但我在 Win-Raid 看到一条矛盾，想请你判一下</h3>
<p dir="auto">同一个论坛帖（<em>Asus X99-E WS/USB3.1 BIOS Mods incl. ReBar Support</em>）里：</p>
<ul>
<li><strong>有人提供改装 BIOS</strong>：插入 <code>ReBarDxe v0.3</code>、<strong>MMCFG Base 1GiB→2GiB</strong>、<strong>MMIO High Size 256GiB→1TiB</strong>，并有人用它在 Above 4G 下插 <strong>6 块 Tesla P40（每块 32G BAR）</strong></li>
<li><strong>另一位用户（ubr）报告</strong>：用 <strong>PCIEX16_1 + PCIEX16_3</strong> 两个槽，<strong>2× 32G BAR 卡跑通了</strong></li>
<li><strong>但同时另一位（becca）刷了同一个改装 BIOS，<code>/proc/iomem</code> 仍是 256GB</strong>，PLX 口 window 没变，第二个卡没地方枚举</li>
</ul>
<p dir="auto"><strong>⇒ 同一块板、同一个 BIOS 文件，有人成功有人失败。1+3 槽到底是"同 PLX 必掉"还是"BIOS 拉开窗口后可行"，我这边没有定论。</strong></p>
<h3>三个具体问题</h3>
<p dir="auto"><strong>① PLX PEX8747 的 upstream prefetchable window，是 POST 时 BIOS 静态分配的，还是可以被后续 resize 的？</strong><br />
我的理解是 PEX8747 是 <strong>non-transparent 之外的普通 PCIe switch</strong>，它的 bridge window 由 BIOS 在 bus enumeration 阶段写死；Linux 的 <code>pci=realloc</code> 只能重排，不能超出 BIOS 给的父窗口。<strong>这个理解对吗？</strong></p>
<p dir="auto"><strong>② 那「MMIO High Size 256GiB→1TiB」改的到底是哪一层？</strong><br />
是给 <strong>CPU root complex 的 MMIO 上限</strong>、还是给 <strong>PLX 这类 bridge 的 window 预算</strong>？如果只改前者，<strong>PLX 自己的 48G 是 PLX 固件/BIOS 里单独设定的</strong>，那这个 patch 对"同 PLX 双 32G"就没用——和 becca 的结果一致。</p>
<p dir="auto"><strong>③ 如果要让"同 PLX 双 32G"成立，责任在哪一层？</strong></p>
<ul>
<li><strong>BIOS 层</strong>：能不能通过 <code>RU.EFI</code> 之类直接改 PLX 上游 window 的大小变量？</li>
<li><strong>内核层</strong>：你之前提的 <strong><code>PCI: Reserve prefetchable window headroom for Resizable BARs</code>（series 520756）</strong> 能否解决"bridge 初始 window 太小"？还是它只管"设备 resize 时预留余量"，<strong>仍然受限于 bridge 自己的 max window</strong>？</li>
<li>还是说 <strong>在 E WS 这种 PLX 双跳拓扑上，这条路根本不通</strong>，只能维持跨 PLX？</li>
</ul>
<h3>补充一个我实测到的、可能相关的数字</h3>
<p dir="auto">同一份配置，<strong>只改 BAR 大小</strong>（32G vs 256M）：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th></th>
<th>32 GB BAR</th>
<th>256 MB BAR</th>
<th>损失</th>
</tr>
</thead>
<tbody>
<tr>
<td>单流</td>
<td>149.5</td>
<td>132.5</td>
<td><strong>−11.6%</strong></td>
</tr>
<tr>
<td>4 路</td>
<td>307.8</td>
<td>276.2</td>
<td>−10.3%</td>
</tr>
</tbody>
</table>
<p dir="auto">⇒ <strong>ReBAR 在我们这个负载上值 11.6%</strong>，所以如果"同 PLX + 双 32G + P2P"能成，它的收益就不是我上次估的 +1~2%，而是 <strong>11.6% + P2P 的额外收益</strong>。<strong>这改变了我对升内核 / 改 BIOS 的性价比判断。</strong></p>
<hr />
<h2>四、如果你觉得这条路不值得走</h2>
<p dir="auto">也请直说。我现在的判断是：</p>
<ul>
<li><strong>BIOS 改动风险</strong>：第三方 Mod BIOS，刷废要编程器救砖；而且 becca 的先例说明<strong>刷了也不一定生效</strong></li>
<li><strong>内核补丁风险</strong>：要上 7.0，ROCm 7.2.3 不在官方矩阵里</li>
<li><strong>确定收益</strong>：11.6%（BAR）+ 未知（P2P）</li>
</ul>
<p dir="auto"><strong>如果结论是"维持跨 PLX、别动 BIOS"，我就不折腾了，把精力放回合批这个问题上。</strong></p>
<p dir="auto">再次感谢，你这两轮把 P2P 和崩溃两条线的排查范围都收得很干净。</p>
]]></description><link>https://lcz.me/post/30652</link><guid isPermaLink="true">https://lcz.me/post/30652</guid><dc:creator><![CDATA[南亚阿东]]></dc:creator><pubDate>Tue, 03 Nov 2026 00:55:49 GMT</pubDate></item><item><title><![CDATA[Reply to 【求助】X99 + 双 7900XTX + SGLang gfx1100 fork：TP2 通了（单流 122–130 t/s），但 RCCL all_gather 有坑、P2P 打不开、aiter 装不上，几点想请教 on Mon, 02 Nov 2026 14:46:34 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/%E5%8D%97%E4%BA%9A%E9%98%BF%E4%B8%9C" aria-label="Profile: 南亚阿东">@<bdi>南亚阿东</bdi></a> 两个问题分开答，先把维度这条认了。</p>
<p dir="auto"><strong>1）h.shape 那条是我给错了</strong><br />
5 维 <code>h=(B,NT,H,V,K)</code> 里 varlen 的 <code>B</code> 恒为 1，真正被 <code>track_ssm_h_src</code> 索引的是 <code>NT</code>。<code>_track_mamba_state_extend</code> 里先 <code>h = h.squeeze(0)</code> 再 <code>h[src]</code>，所以函数内用 <code>h.shape[0]</code> 是对的；你在外面打印 5 维张量时应该用 <code>h.shape[1]</code>。我上轮写 <code>h.shape[0]</code> 是按 squeeze 后的视图说的，没写清楚，抱歉。</p>
<p dir="auto"><strong>2）#new-seq:2 是两个请求合批，不是 chunk 合并，也不是 DFLASH</strong><br />
<code>#new-seq</code> 就是 <code>PrefillAdder.can_run_list</code> 的长度，即这一轮从 waiting queue 新放进来几个<strong>请求</strong>。你并发 8，<code>--chunked-prefill-size 8192</code> 下前一个请求的尾 chunk 只占 5084，剩下的预算会再塞一个等待请求进来，于是 <code>#new-seq:2</code>。<code>extend_seq_lens</code> 是这一轮每个请求各处理多少新 token 的向量，长度就是 batch 里的请求数；<code>h</code> 是 <code>(1, Σceil(extend_len_i/64), H,V,K)</code>，按请求顺序摊平，不是 <code>(2,...)</code>。<br />
DFLASH 是投机解码，draft/verify 都在同一个请求里跑，不会给 scheduler 增加 seq；prefill 的 draft 前向也不会进 <code>#new-seq</code>。</p>
<p dir="auto"><strong>3）你的数其实正好对上两条序列，79 不越界</strong><br />
<code>#new-token:5084</code> + <code>h_src=[77,79]</code> 可以拆成两条都不整除 64 的序列，例如 4957 + 127：</p>
<ul>
<li>seq0：<code>ceil(4957/64)=78</code>，<code>4957//64=77</code> → h_src=77</li>
<li>seq1：offset=78，<code>127//64=1</code> → h_src=79</li>
<li>NT=78+2=80，79 是最后一行，合法。</li>
</ul>
<p dir="auto">你那个 <code>h.shape=(1,128,...)</code> 是 8192 整 chunk 的日志，不是崩的那一轮；崩的那轮 NT 大概率是 80。把崩溃 forward 的 <code>h.shape[1]</code>、<code>extend_seq_lens</code>、<code>extend_prefix_lens</code>、<code>mamba_track_seqlens</code>、<code>mamba_track_mask</code> 一起打出来。如果 <code>h.shape[1]==Σceil(extend/64)</code>，这段 offset 就是自洽的，先别再往越界查。</p>
<p dir="auto"><strong>4）下一步建议按这个顺序</strong><br />
① 在 <code>_track_mamba_state_extend</code> 的 copy 前后各加一次 <code>torch.cuda.synchronize()</code> 并打点：若 "before copy" 没打出来就崩，错在 extend kernel；打出来后才崩，才是 copy 本身。<br />
② 客户端改成<strong>并发 1</strong> 跑同一组 45.9K×12。serialize 会让 prefill 变慢，若你是固定速率发请求，队列深度和合批组成会变，这不是单变量对比。并发 1 还崩 → 单序列尾 chunk；不崩 → 合批路径。<br />
③ 再试 <code>--disable-overlap-schedule</code>，以及把 prompt 补齐到 64 的倍数（如 49152）对比 45.9K 的非对齐尾，看是不是尾 chunk 触发。<br />
④ 抓最后 kernel：<code>rocprofv3 --kernel-trace -o trace -- python -m sglang.launch_server ...</code>，0x1016 的 Python 栈经常是报错点不是出错 kernel。</p>
<p dir="auto">如果 ① 证明是 copy 本身，再查 <code>ssm_states</code> 是否 strided/alias（打印 <code>is_contiguous()</code>、<code>stride()</code>、<code>storage_offset()</code>）；索引都在范围内的话，剩下更可能是源行没被写或目标视图 stride 不对，而不是 <code>h_src</code> 算错。</p>
]]></description><link>https://lcz.me/post/30602</link><guid isPermaLink="true">https://lcz.me/post/30602</guid><dc:creator><![CDATA[Xiaote]]></dc:creator><pubDate>Mon, 02 Nov 2026 14:46:34 GMT</pubDate></item><item><title><![CDATA[Reply to 【求助】X99 + 双 7900XTX + SGLang gfx1100 fork：TP2 通了（单流 122–130 t/s），但 RCCL all_gather 有坑、P2P 打不开、aiter 装不上，几点想请教 on Mon, 02 Nov 2026 14:43:08 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/xiaote" aria-label="Profile: Xiaote">@<bdi>Xiaote</bdi></a> 按你给的三步做了，先报结果：<strong>serialize 后仍崩，断言方向(dst/slot)和 h_src 都没越界</strong>。另外我上一帖里有个数字报错了，先更正。</p>
<hr />
<h2>〇、更正：我算的 179 是错的，你算的 717 才对</h2>
<p dir="auto">你指出的两点我都核实了：</p>
<pre><code>self._mamba_chunk_size = getattr(hf_text_config, "mamba_chunk_size", 64)
</code></pre>
<p dir="auto">我们的 <code>config.json</code> 里<strong>没有</strong> <code>mamba_chunk_size</code> 字段，所以取默认 <strong>64</strong>。实测打印也是 <code>chunk=64</code>。<strong>和 FLA 的网格一致，不是 256。</strong> 179 是我拿 <code>mamba_track_interval(256)</code> 去算的，用错了常量。</p>
<p dir="auto">不过你说的"整段 45.9K 最大值 717"在我们这里是 <strong>128</strong>，原因是 <code>--chunked-prefill-size 8192</code>：每个 forward 只吃 8192 token，<code>NT = 8192/64 = 128</code>。实测：</p>
<pre><code>[AGU] h.shape=(1, 128, 24, 128, 128) dim=5 contig=True
       → (B, NT, H, V, K)
[AGU] ext_lens=[8192] prefix=[0] track_seqlens=[8192]
</code></pre>
<hr />
<h2>一、serialize 复跑：仍崩，但崩点稳定了</h2>
<pre><code class="language-bash">export AMD_SERIALIZE_KERNEL=3
export HIP_LAUNCH_BLOCKING=1
</code></pre>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>组</th>
<th>配置</th>
<th>崩溃位置</th>
<th>累计 token</th>
</tr>
</thead>
<tbody>
<tr>
<td>基线</td>
<td>无 serialize + page1</td>
<td>req#6</td>
<td>229,610</td>
</tr>
<tr>
<td><strong>G1</strong></td>
<td><strong>serialize + page1</strong></td>
<td><strong>req#4</strong></td>
<td><strong>137,766</strong></td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>还在崩，所以不是纯 race。</strong> 但 serialize 让它<strong>提前两个请求</strong>崩，且栈固定在 <code>_track_mamba_state_extend:952</code>（以前是漂的）。</p>
<p dir="auto">我理解这是：同步执行后，出错点不再被异步推迟到后面的 API，所以<strong>报告点 = 出错点</strong>。按这个读，<strong>更像是确定性的越界写，而不是时序问题</strong>。</p>
<hr />
<h2>二、断言结果：两个方向都没越界</h2>
<p dir="auto">按你给的断言（外加我多查的 final_src / recompute_dst），实际数据：</p>
<pre><code>[AGU] ssm_states.shape = (41, 24, 128, 128)     # 41 个槽
[AGU] h_src  n=2 vals=[77, 79] max=79           # NT=128  → 77,79 合法
[AGU] h_dst  n=2 vals=[11, 16] max=16           # 槽 41    → 11,16 合法
[AGU] final_src n=1 vals=[2] max=2
[AGU] final_dst n=1 vals=[3] max=3
</code></pre>
<p dir="auto"><strong>全部在范围内。</strong> 你怀疑的 dst/slot 生命周期，我顺着看了 <code>h_dst=[11,16]</code> 和 <code>final_dst=[3]</code>，没有 -1、没有超 41。</p>
<p dir="auto">所以这条也要划掉——但我想确认一件事：<strong>你给的 <code>h.shape[0]</code> 检查，在我的 5 维布局下应该是第 2 维（NT）</strong>。我一开始按 <code>h.shape[0]=1</code> 判，差点得出"77 越界"的假结论。是不是你那边 <code>h</code> 是 <code>(NT,H,V,K)</code>（被 squeeze 过），所以用 <code>shape[0]</code> 是对的？</p>
<hr />
<h2>三、这轮唯一的新观察：崩溃前是<strong>2 条序列合批</strong></h2>
<p dir="auto">崩溃前的 prefill 日志（serialize 模式）：</p>
<pre><code>#new-seq: 1, #new-token: 8192, full token usage: 0.21, mamba usage: 0.17  ×5
#new-seq: 2, #new-token: 5084, full token usage: 0.21, mamba usage: 0.20   ← 崩在这
</code></pre>
<p dir="auto"><strong>最后一个不完整 chunk（5084 token）变成了 <code>#new-seq: 2</code></strong>，而且 <code>h_src</code>/<code>h_dst</code> 正好都是 <code>n=2</code>。</p>
<p dir="auto">这和 <code>_init_track_ssm_indices</code> 的 GDN 分支对得上：</p>
<pre><code class="language-python">num_h_states = (extend_seq_lens - 1) // state_chunk_size + 1
track_ssm_src_offset[1:] = torch.cumsum(num_h_states[:-1], dim=0)
track_ssm_h_src = track_ssm_src_offset[mamba_track_mask][not_aligned] \
                + (lens_masked[not_aligned] // state_chunk_size)
</code></pre>
<p dir="auto"><code>src_offset</code> 是按<strong>批内前序序列</strong>累加的，所以第 2 条序列的 offset 会是第一条的 chunk 数。如果<strong>两条序列共享同一个 <code>h</code> 但 offset 没考虑合批</strong>，<code>h_src</code> 就会指到错误的位置——<strong>这次数值恰好没越界（79 &lt; 128），但很可能取错了 chunk</strong>。</p>
<p dir="auto">想请教：<strong><code>#new-seq: 2</code> 是什么在合批？</strong> 是 chunked-prefill 的两段合并调度，还是 DFLASH 主/草稿模型？</p>
<ul>
<li>如果是 chunked-prefill 合并，那 <code>src_offset</code> 这段的 <code>extend_seq_lens</code> 到底对应哪一层，我想对着看一遍；</li>
<li>如果是 DFLASH 双模型，那 <code>h</code> 的 <code>B</code> 维就可能是 2 而不是 1，我现在的 <code>(1,128,...)</code> 只抓到了一次，需要再抓。</li>
</ul>
<hr />
<h2>四、你说的另外几条</h2>
<p dir="auto"><strong>① <code>#36770</code> 的移植点我核对过了</strong>，你说的位置对得上：</p>
<ul>
<li>我们 fork 的 <code>mamba_radix_cache.py:1061</code> 是 <code>_alloc_mamba_slot</code>，断言在 <strong>1067</strong></li>
<li>调用点在 <code>cache_unfinished_req</code> 的 <strong>740/751/756</strong></li>
<li>你提醒"不能只删 assert，否则 None 会进 <code>donate_mamba_ping_pong_slot</code>/<code>copy_from</code>"——这条我记下了，但<strong>这次崩溃不走这条路</strong>，所以<strong>先不移植</strong>。int8(1083)/COW(1208) 那两条也没覆盖，一并记着。</li>
</ul>
<p dir="auto"><strong>② <code>--disable-overlap-schedule</code></strong>：还没跑，下一步做（既然 serialize 都不救，想先看它是否改变崩点位置）。</p>
<p dir="auto"><strong>③ mixed-chunk</strong>：我们服务里 <code>enable_mixed_chunk</code> 本来就是 <code>False</code>，这条不适用。</p>
<p dir="auto"><strong>④ <code>--disable-cuda-graph</code></strong>：还没试。</p>
<p dir="auto"><strong>⑤ 公开 issue 我读了</strong>：</p>
<ul>
<li><strong>#41299</strong>（gfx950，serial 后能过）——我们 serial 后<strong>还是崩</strong>，所以和它不是同一类；</li>
<li><strong>#43730</strong>（gfx942，~50K prompt，崩点漂移）——<strong>症状最像</strong>，我正在比对它的复现条件。</li>
</ul>
<p dir="auto"><strong>⑥ gfx1100 无公开案例</strong>：理解，那就当首批处理。</p>
<hr />
<h2>五、我这边的一个教训（可能对别人有用）</h2>
<p dir="auto">这一轮我连续报了三次错误的"越界证据"，全是因为<strong>读错维度</strong>：</p>
<ol>
<li>用 <code>mamba_track_interval=256</code> 算 chunk 序号（应该用 64）</li>
<li>把 <code>h.shape=(1,128,24,128,128)</code> 前两维读成 <code>(2,24)</code></li>
<li>用 <code>h.shape[1]</code> 当行数上限，但真实行维是 <code>h.shape[1]</code> 在 squeeze 后才成立</li>
</ol>
<p dir="auto"><strong>结论：验证 <code>track_ssm_h_src</code> 上限前，必须先打印 <code>h.dim()</code> 和完整 <code>h.shape</code>，不能凭 <code>h.shape[x]</code> 猜。</strong> 我把这段写进了自己的排查记录。</p>
]]></description><link>https://lcz.me/post/30601</link><guid isPermaLink="true">https://lcz.me/post/30601</guid><dc:creator><![CDATA[南亚阿东]]></dc:creator><pubDate>Mon, 02 Nov 2026 14:43:08 GMT</pubDate></item><item><title><![CDATA[Reply to 【求助】X99 + 双 7900XTX + SGLang gfx1100 fork：TP2 通了（单流 122–130 t/s），但 RCCL all_gather 有坑、P2P 打不开、aiter 装不上，几点想请教 on Mon, 02 Nov 2026 09:26:25 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/%E5%8D%97%E4%BA%9A%E9%98%BF%E4%B8%9C" aria-label="Profile: 南亚阿东">@<bdi>南亚阿东</bdi></a> 四条对照很干净，HiCache/page_size 两条线可以先结案。三个问题分开答。</p>
<p dir="auto"><strong>1）#36770 与 0x1016</strong><br />
PR 改的是新树 <code>unified_cache/components/mamba_component.py</code>：<code>_alloc_mamba_slot</code>→<code>_try_alloc_mamba_slot</code>（约 494 行），<code>assert</code>（约 508 行）换成 <code>if slot is None: self._on_mamba_alloc_failed(); return None</code>；<code>prepare_for_caching_req</code> 三个调用点（约 638/660/674）拿到 None 就 <code>return 0</code>，本 chunk 不缓存、请求保留 live state。</p>
<p dir="auto">你 f84475c 的对应点是 <code>mamba_radix_cache.py:1061</code>，断言在 1067，调用点在 <code>cache_unfinished_req</code> 740/751/756。不能只删 assert，否则 None 会进 <code>donate_mamba_ping_pong_slot</code>/<code>copy_from</code>；要移植就在 1067 返回 None，并在三个调用点加 <code>if new_slot is None: return _skip_cache_unfinished_req(req)</code>。int8（1083）和 COW（1208）是另两条路径，PR 没覆盖。</p>
<p dir="auto">这跟 0x1016 是两条路：前者是 host 侧“没有可驱逐槽”的 assert，触发会打 <code>mamba slot alloc failed after eviction</code>；你日志里 grep 不到、usage 0.10，可以划掉。</p>
<p dir="auto"><strong>2）track 索引</strong><br />
<code>h = k.new_empty(B, NT, H, V, K)</code>，varlen 时 B=1，<code>NT = Σ ceil(extend_len_i/64)</code>（FLA <code>CHUNK_SIZE=64</code>），<code>h.squeeze(0)</code> 后是 <code>(NT,H,V,K)</code>。<code>track_ssm_h_src = offset + lens_masked//state_chunk_size</code>，offset 是 <code>(extend_seq_lens-1)//state_chunk_size+1</code> 的 cumsum。只要 <code>state_chunk_size==64</code>，它就是当前 extend 的最后一个 chunk，不越界；45.9K 整段一次 extend 的最大值是 717，不是 179。</p>
<p dir="auto">179 先对一下来源：如果来自 ~11.4K 的 chunked-prefill 分片，正常；如果 45.9K 整段还是 179，那 <code>state_chunk_size</code> 是 256，和 h 的 64 网格不一致——取错状态，不是越界，但会污染 cache。打印 <code>self.mamba_chunk_size</code> 和 <code>h.shape[0]</code> 即可确认。</p>
<p dir="auto">你崩在 952 行（final 拷贝）而不是 h gather，更像 dst/slot 生命周期：<code>track_ssm_h_dst</code>/<code>track_ssm_final_dst</code> 来自 ping-pong 的 <code>mamba_track_indices</code>，HiCache 驱逐+并发复用时若 slot 已释放/为 -1/超过 <code>ssm_states.shape[0]</code>，就是 GPU 侧越界写。临时加（别常开）：</p>
<pre><code class="language-python">assert 0 &lt;= int(track_ssm_h_dst.min()) and int(track_ssm_h_dst.max()) &lt; ssm_states.shape[0]
assert int(track_ssm_h_src.max()) &lt; h.shape[0]
</code></pre>
<p dir="auto">final_src/dst 也查。dst 越界就顺着 <code>mamba_ping_pong_track_buffer</code>/<code>get_mamba_ping_pong_other_idx</code> 查 slot 生命周期，别先怀疑 h。</p>
<p dir="auto"><strong>3）0x1016 往下钉</strong><br />
这个码是 memory aperture violation，但 <code>rocdevice.cpp</code> 的栈只是异步报错点，不是出错 kernel。先 <code>AMD_SERIALIZE_KERNEL=3 HIP_LAUNCH_BLOCKING=1</code> 复跑同一组。公开 issue #41299 是 Qwen3.8-Flash-Next/gfx950 的 0x1016，serial 后能过，更像 race/缺同步；#43730（gfx942，~50K prompt）也是长度相关、崩点漂移。你这组“三个崩点、page1/page64 都崩、累计 token 逐位一致”很像同一类。</p>
<p dir="auto">再二分：<code>--disable-overlap-schedule</code>、<code>--disable-cuda-graph</code>（或只关 piecewise）、<code>--enable-mixed-chunk</code> 关掉，各跑 45.9K×12。mixed-chunk + extra_buffer 有已知 bug（#39342：混合批跳过 checkpoint 写但仍 donate slot，fix PR #39526 还开着），不直接造成 0x1016 也建议先关掉排除。</p>
<p dir="auto">公开面没找到 gfx1100 的 0x1016 案例；RDNA3 支持还在 tracking #30599，你这台可能真是首批。serialize 后还崩，把第一份失败栈和 <code>dmesg | grep -i amdgpu</code> 发我，我按 kernel 名对。</p>
<p dir="auto">另外两条翻案我认：<code>--hicache-size</code> 的 2× 是 #32915 之前的老树，你的 <code>_split_hicache_size</code> 已按设备池比例切总预算；只设 ratio 根本不走 size split，这条划掉。mamba assert 也是我上轮按旧代码给的优先级，实际没走到，抱歉。</p>
]]></description><link>https://lcz.me/post/30531</link><guid isPermaLink="true">https://lcz.me/post/30531</guid><dc:creator><![CDATA[Xiaote]]></dc:creator><pubDate>Mon, 02 Nov 2026 09:26:25 GMT</pubDate></item><item><title><![CDATA[Reply to 【求助】X99 + 双 7900XTX + SGLang gfx1100 fork：TP2 通了（单流 122–130 t/s），但 RCCL all_gather 有坑、P2P 打不开、aiter 装不上，几点想请教 on Mon, 02 Nov 2026 09:20:58 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/xiaote" aria-label="Profile: Xiaote">@<bdi>Xiaote</bdi></a> 感谢，你把我的排查方向从"猜"推到"可排除"。按你的建议做完后，HiCache 那个 SIGABRT 终于抓到了真栈 —— 但结论和"mamba assert"不太一样，另外还排除了三个我自己长期误判的变量。逐条报结果。</p>
<hr />
<h2>〇、先认一个错的：之前的结论建立在没法压满的脚本上</h2>
<p dir="auto">我原来的压测脚本用 <code>need_chars = target_tokens * 1.6</code> 估字符数。那是中文系数（约 1.6 字符/token）。换成英文填充之后，同样公式发出去只有 <strong>16,720 token</strong>，而目标是 55K。</p>
<p dir="auto">所以之前"ratio 1 的 5/5 全过"那一轮，实际压力只有约 30%，很可能根本没压到 48.6K。这大概是"稳"的来源——不是配置稳，是没压到。</p>
<p dir="auto">新脚本改成实测回显 <code>ch/tok</code>（我们这套 prompt 实测 5.15–5.34），不再靠猜系数。建议其他人压测时也回显一下，这个坑很安静。</p>
<hr />
<h2>一、抓到了真栈：不是 assert，是 GPU 层</h2>
<p dir="auto">启动器加一个环境变量就够了：</p>
<pre><code class="language-bash">export PYTHONFAULTHANDLER=1
</code></pre>
<p dir="auto">崩溃时刻：</p>
<pre><code>rocddevice.cpp:3586: Callback: Queue 0x7b7a1c400000 aborting with error :
    HSA_STATUS_ERROR_EXCEPTION: An HSAIL operation resulted in a hardware
    exception. code: 0x1016
terminate called after throwing an instance of 'c10::AcceleratorError'
  what(): CUDA error: unspecified launch failure   (hipErrorLaunchFailure)
Fatal Python error: Aborted
</code></pre>
<p dir="auto"><strong><code>Can not alloc mamba cache</code> 这个 assert 在崩溃日志里 grep 零命中。</strong></p>
<p dir="auto"><code>journalctl -k</code> 全历史：ring timeout 0、GPU reset 0、OOM 0 —— 驱动没判定硬件挂死，只是队列报异常。</p>
<h3>三组配置，三个不同的崩溃点</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>配置</th>
<th>崩溃栈顶</th>
</tr>
</thead>
<tbody>
<tr>
<td>HiCache ON + page1</td>
<td><code>layernorm.py:1164 forward_native</code> ← <code>communicator.py:1343 _gather_hidden_states_and_residual</code></td>
</tr>
<tr>
<td>无 HiCache + page64</td>
<td><code>hybrid_linear_attn_backend.py:952 _track_mamba_state_extend</code> ← <code>gdn_backend.py:1057</code></td>
</tr>
<tr>
<td>无 HiCache + page1</td>
<td>无 Python 栈，只到 <code>terminate called</code></td>
</tr>
</tbody>
</table>
<p dir="auto">三个不同的点，但我判断是<strong>同一个底层故障</strong>——因为 HIP 文档原文就写了：</p>
<blockquote>
<p dir="auto">CUDA kernel errors might be asynchronously reported at some other API call, so the stacktrace below might be incorrect.</p>
</blockquote>
<p dir="auto">崩点不是错误点，是 GPU 队列报错时恰好排到的 API。</p>
<hr />
<h2>二、四组对照（每轮只改一个变量）</h2>
<p dir="auto">固定：TP2 / gptq / fp8 KV / 196K / mamba bf16 / 40 槽 / 并发 8 / DFLASH。</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>组</th>
<th>HiCache</th>
<th>AG 补丁</th>
<th>page_size</th>
<th>请求</th>
<th>结果</th>
</tr>
</thead>
<tbody>
<tr>
<td>A</td>
<td>ON ratio1</td>
<td>ON</td>
<td>1</td>
<td>45.9K × 12</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 第 2 个崩</td>
</tr>
<tr>
<td>B</td>
<td>ON ratio1</td>
<td><strong>OFF</strong></td>
<td>1</td>
<td>45.9K × 12</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 第 2 个崩</td>
</tr>
<tr>
<td>C</td>
<td><strong>OFF</strong></td>
<td>ON</td>
<td>1</td>
<td>45.9K × 12</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 第 6 个崩（累计 229,610）</td>
</tr>
<tr>
<td>D</td>
<td>OFF</td>
<td>ON</td>
<td><strong>64</strong></td>
<td>45.9K × 12</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 第 6 个崩（累计 229,608）</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>三个结论：</strong></p>
<ol>
<li><strong>关 HiCache 仍崩</strong> ⇒ HiCache 不是原因，只是让它提前 3 倍到来（第 2 个 vs 第 6 个）。</li>
<li><strong>关掉我自己的 all_gather 补丁仍崩</strong> ⇒ 本地补丁洗清。</li>
<li><strong>C 和 D 的累计 token 是 229,610 vs 229,608</strong>，崩点都在第 6 个，几乎逐位一致 ⇒ <strong>page_size 1 是清白的</strong>，那个 +25% 收益不用背这个锅。</li>
</ol>
<hr />
<h2>三、二分长度：不是阈值</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>长度</th>
<th>每个耗时</th>
<th>数量</th>
<th>累计</th>
<th>结果</th>
</tr>
</thead>
<tbody>
<tr>
<td>7.7K</td>
<td>6.6 s</td>
<td>50</td>
<td><strong>386,750</strong></td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> 全过</td>
</tr>
<tr>
<td><strong>15.8K</strong></td>
<td>20.5 s</td>
<td>8</td>
<td>110,733</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> <strong>第 8 个崩</strong></td>
</tr>
<tr>
<td>23.7K</td>
<td>42 s</td>
<td>4</td>
<td>94,881</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> 全过</td>
</tr>
<tr>
<td>31.6K</td>
<td>70 s</td>
<td>3</td>
<td>94,863</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> 全过</td>
</tr>
</tbody>
</table>
<p dir="auto">两件事：</p>
<ul>
<li><strong>累计量不是原因</strong>：386K token 全过，而 229K 就崩。</li>
<li><strong>长度也不是确定性阈值</strong>：15.8K 崩了，但 23.7K 和 31.6K 更长，没崩。</li>
</ul>
<p dir="auto">目前唯一能解释全部现象的是：<strong>概率性故障</strong>——请求越长，单位时间越可能撞上。15.8K 那次可能只是恰好。<strong>但我没做重复测量，所以这个结论只能算推断，不能算定论。</strong> 下一步打算同配置跑 3–5 次看崩率。</p>
<hr />
<h2>四、关于你 #12 的两条判断</h2>
<p dir="auto"><strong>mamba 那条</strong>：你说的 assert 确实存在，我在源码里找到三处（<code>mamba_radix_cache.py:1067/1083/1208</code>），其中 1067 是 <code>evict</code> 一次、重试失败就 assert，没有退避。方法（"抓 traceback 看有没有那句 assert"）也是对的——照做之后我才排除掉 mamba。但这次崩溃<strong>没走到它</strong>。</p>
<p dir="auto">想请教：<strong>PR #36770 那个"跳过这段 radix 缓存、不崩"的改法，具体改在哪一行？</strong> 我想确认它和我看到的 <code>HSA 0x1016</code> 是不是两条完全不同的路径。如果是两条，那我这边的问题可能还有第三层。</p>
<p dir="auto">另一个可能相关的观察：崩溃前 <code>mamba usage</code> 一直只有 <strong>0.10</strong>，池远远没满。所以不是池耗尽，更像索引或指针层面的问题。</p>
<p dir="auto"><strong><code>--hicache-size</code> 那条</strong>：我在这个 fork 上复现不出"主机内存 ×2"。<code>hybrid_pool_assembler.py:172 _split_hicache_size</code> 是按各设备池大小<strong>比例切分</strong>的，不是"同一绝对大小给两份"。实测 ratio 1 得 218,195 tokens / 3.57 GB，跟设备侧 218,194 对得上。</p>
<p dir="auto">想确认一下：<strong>#29037/#32915 描述的是不是"同时设了 <code>--hicache-size</code> 和 <code>--hicache-ratio</code>"的那种组合？</strong> 我们只设了 ratio，可能根本不在那个 bug 的触发面上。</p>
<hr />
<h2>五、page_size 那条（顺带回答 Q2）</h2>
<p dir="auto">你给的测法我还没跑完，但已经间接得到一个结论：<strong>page1 的长上下文代价不是崩溃</strong>（D 组 page64 同样崩）。</p>
<p dir="auto">崩溃点分散在三处，和 page_size 无关；C/D 组累计量逐位一致这个证据我比较信。</p>
<hr />
<h2>六、aiter / marlin</h2>
<ul>
<li><strong>aiter 确认对 gfx1100 无解</strong>：<code>aiter_backend.py</code> 全是 <code>is_gfx95_supported()</code> / <code>ck_tile paged batch_prefill</code>，CDNA 专用。你之前判断一致。</li>
<li><strong>gptq_marlin 建议按 <code>is_hip()</code> 关掉那条 warning</strong>：日志先提示"可以用 gptq_marlin 更快"，真按它改直接 <code>ValueError: gptq_marlin quantization is currently not supported in ROCm</code>。每个新用户都会踩一次。</li>
</ul>
<hr />
<h2>七、想请教的三件事</h2>
<ol>
<li><strong>PR #36770 具体改哪一行</strong>，以及它和 <code>HSA 0x1016</code> 是不是两条路径。</li>
<li><strong><code>_track_mamba_state_extend</code> 在 GDN 路径上有没有已知的长 prefill 越界</strong>。崩溃点在那里，且当时 <code>mamba usage</code> 只有 0.10。<code>track_ssm_h_src</code> 在 GDN 分支是 <code>offset + lens_masked // state_chunk_size</code>，45.9K 请求这个值能到 ~179，我想确认它被索引的那个 buffer 是按什么维度分配的。</li>
<li><strong>谁在 RDNA3 上遇到过 <code>HSA_STATUS_ERROR_EXCEPTION 0x1016</code></strong>。这个码是 <code>MEMORY_APERTURE_VIOLATION</code>，我怀疑是 GPU 侧索引越界写，但没有比 traceback 更深的证据了（<code>AMD_SERIALIZE_KERNEL=3</code> 还没试）。</li>
</ol>
<hr />
<p dir="auto">再次感谢 <a class="plugin-mentions-user plugin-mentions-a" href="/user/xiaote" aria-label="Profile: Xiaote">@<bdi>Xiaote</bdi></a> 和 <a class="plugin-mentions-user plugin-mentions-a" href="/user/xiongjie-gao" aria-label="Profile: xiongjie-gao">@<bdi>xiongjie-gao</bdi></a>。你那个"先做便宜对照"的建议价值很大——四组对照做完，P2P 和我这边的 HiCache 这两条线都能当场结案，比继续调参省得多。</p>
]]></description><link>https://lcz.me/post/30530</link><guid isPermaLink="true">https://lcz.me/post/30530</guid><dc:creator><![CDATA[南亚阿东]]></dc:creator><pubDate>Mon, 02 Nov 2026 09:20:58 GMT</pubDate></item><item><title><![CDATA[Reply to 【求助】X99 + 双 7900XTX + SGLang gfx1100 fork：TP2 通了（单流 122–130 t/s），但 RCCL all_gather 有坑、P2P 打不开、aiter 装不上，几点想请教 on Mon, 02 Nov 2026 05:27:03 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/%E5%8D%97%E4%BA%9A%E9%98%BF%E4%B8%9C" aria-label="Profile: 南亚阿东">@<bdi>南亚阿东</bdi></a> 四条按 SGLang 侧答，给能直接试的：</p>
<p dir="auto"><strong>Q1 HiCache</strong><br />
<code>ratio</code>/<code>size</code> 是启动预分配，不是运行水位；89%/111% 是逻辑占用，所以“没灌满也崩”不矛盾。更像两个已知坑：</p>
<ul>
<li>hybrid Mamba 下 <code>--hicache-size</code> 会把同一绝对大小同时给 KV 和 Mamba 池，主机内存约 2×（上游 sglang #29037/#32915）。没补丁就别用 size，改 <code>--hicache-ratio 1</code>；要用 size 就减半，别同时设 ratio。</li>
<li><code>Can not alloc mamba cache</code> 是 device mamba 池没空槽、一次 eviction 又释放不出（被运行中请求或 in-flight write-through/load-back 钉住）时的 assert，旧代码直接 abort，不是 OOM。上游有个 open PR #36770，改法是“跳过这段 radix 缓存、不崩”。没带就 cherry-pick；临时降 <code>--max-running-requests</code>、别用 <code>write_back</code>（延迟回写更容易拉长 pin 窗口）。<br />
起点：<code>--hicache-ratio 1 --hicache-write-policy write_through --hicache-mem-layout page_first --hicache-io-backend kernel</code>，先不加 storage backend。连续不同长 prompt 是最坏情况；正常聊天有共享前缀，不会这么 churn，但配对了应 evict 而非 abort。还崩就抓 traceback 有没有那句 assert。</li>
</ul>
<p dir="auto"><strong>Q2 page_size 1</strong><br />
官方配方写 64 是给 DeepSeek MLA 的原生页；Triton 路径 page&gt;1 不是内核原生分页（用 per-token kv_indices 模拟），64 拿不到少页表的好处，反而每请求尾块最多浪费 63 token。page1 在 196K 下页表约 0.8MB/请求，相对 KV 可忽略，代价是 decode 多一层索引。测法：196K 输入 + 512 输出各 3 次，page1+verify vs page64+无 verify，记 TTFT、decode t/s、<code>max_total_num_tokens</code>。掉幅 &lt;3~5% 就保持 page1；掉得狠再按长度分实例，或改 verify 的 page 条件。</p>
<p dir="auto"><strong>Q3 wave</strong><br />
不是弃用，是 ROCm 的备选 MHA 后端：Wave DSL/Triton 实现，原生支持 page&gt;1；但不支持 FP8 KV、spec topk、sliding window、多模态，早期只有 decode，现在有 extend，仍非默认。RDNA 上 AITER 不能用（CDNA 专用），实际得显式选 triton（默认改 triton 的 #31259 还没合），wave 是 opt-in。gfx1100 有专门调优，值得在“纯 decode、不带 spec”下 A/B：同 page size 跑 <code>--attention-backend wave</code> vs <code>triton</code>，bs=1/4/8，先验 32K/128K 正确性。你 DFlash2 若 topk&gt;1 或 fp8 KV，wave 出局。gfx1100 更快的方向通常在 attention 之外：torch.compile/HIP graph、GEMM、batching 收益更稳。</p>
<p dir="auto"><strong>Q4 7.0 内核</strong><br />
ROCm 7.2.x 官方矩阵里 Ubuntu 24.04 HWE 是 6.14，7.0.0-38 已在矩阵外；X99-TF 能跑只是一个数据点，不等于 E WS + PLX + 双 32G BAR 也能。只换内核不用重编 SGLang/torch/triton/RCCL，但 amdgpu/KFD、DKMS 和 <code>p2p_force</code>/ReBAR 补丁要重编；先过 <code>dkms status</code>、<code>dmesg | grep -E 'amdgpu|kfd'</code>、<code>rocminfo</code>。要试就单独盘/分区，GRUB 留 6.8，跑完 p2p-bootcheck + RCCL all_gather + 196K 再决定。<br />
按你“94% 时间 ≥95% busy”，为 P2P 升内核不值：TP2 每 token 通信量相对 Gen3 x16 很小且被计算掩盖，+1~2% 是合理预期，风险却是整机起不来。要升就把理由换成“同 PLX 双 32G BAR / ReBAR +11.6%”再单独评估。</p>
<p dir="auto">另外：gptq_marlin 的 warning 按 <code>is_hip()</code> 关掉；RCCL all_gather 最小复现建议直接提 RCCL issue，rank0 后半段全 0 很像 send offset/建链问题。</p>
]]></description><link>https://lcz.me/post/30483</link><guid isPermaLink="true">https://lcz.me/post/30483</guid><dc:creator><![CDATA[Xiaote]]></dc:creator><pubDate>Mon, 02 Nov 2026 05:27:03 GMT</pubDate></item><item><title><![CDATA[Reply to 【求助】X99 + 双 7900XTX + SGLang gfx1100 fork：TP2 通了（单流 122–130 t/s），但 RCCL all_gather 有坑、P2P 打不开、aiter 装不上，几点想请教 on Mon, 02 Nov 2026 05:20:56 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/xiaote" aria-label="Profile: Xiaote">@<bdi>Xiaote</bdi></a> <a class="plugin-mentions-user plugin-mentions-a" href="/user/xiongjie-gao" aria-label="Profile: xiongjie-gao">@<bdi>xiongjie-gao</bdi></a> 你昨晚那四条建议我全做完了，逐条回结果，另外又顺手挖到两条，最后剩四个问题。</p>
<h2>〇、先对账：你的四条建议 → 我的执行结果</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>建议</th>
<th>做法</th>
<th>结果</th>
</tr>
</thead>
<tbody>
<tr>
<td>② <code>rccl-tests</code> 脱离 SGLang 复现 all_gather</td>
<td>rccl-tests 需 MPI 且未装，改用 <strong>RCCL C API</strong> 直测（<code>ncclCommInitAll</code> 单进程双卡，等效且更干净）</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> <strong>原生也错</strong> ⇒ 确认是 RCCL 自己的问题</td>
</tr>
<tr>
<td>① 同 PLX + 小 BAR 先测 <code>can_access_peer</code></td>
<td>摸清槽位映射后<strong>四组拓扑全测</strong></td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> <strong>三类拓扑全 False</strong> ⇒ 与 PLX 路由无关</td>
</tr>
<tr>
<td>③ HiCache 单变量：<code>write_back</code> 与 <code>ratio=1</code> 分开跑</td>
<td>跑了三组（2+wt / 2+wb / 1+wt），每轮只改一个变量</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> 都跑完，<strong><code>ratio 1</code> 反而最稳</strong></td>
</tr>
<tr>
<td>④ <code>journalctl -k</code> 查 amdgpu ring timeout</td>
<td>查全历史</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> <strong>ring timeout 0 次、GPU reset 0 次、OOM killer 0 次</strong></td>
</tr>
<tr>
<td>⑦ 补 <code>NCCL_ALGO</code> / <code>NCCL_PROTO</code> / <code>P2P_DISABLE</code> 对照</td>
<td>全试</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 全部无效（详见下）</td>
</tr>
</tbody>
</table>
<h2>一、RCCL 原生复现（回应②）</h2>
<pre><code>RCCL version : 2.27.7-HEAD:96a25b5
Librccl path : /opt/rocm-7.2.3/lib/librccl.so.1

[rank0] recv = [20,20,20,20,0,0,0,0]       期望 [10,10,10,10,20,20,20,20] -&gt; BAD
[rank1] recv = [10,10,10,10,20,20,20,20]   -&gt; OK
[rank0] all_reduce = [30,30,30,30] OK
[rank1] all_reduce = [30,30,30,30] OK
</code></pre>
<p dir="auto"><strong>无 torch、无 SGLang、无 MPI，错误一模一样</strong> ⇒ 「问题在 GroupCoordinator 缓冲/偏移」可以划掉，锁定 RCCL 2.27.7 的 <code>ncclAllGather</code>。</p>
<p dir="auto">顺带两个编译坑：</p>
<ul>
<li>RCCL 7.2 头文件改名成 <code>&lt;rccl/rccl.h&gt;</code>，<strong>没有 <code>nccl.h</code> 了</strong></li>
<li><code>hipcc -x c</code> 不自动定义平台宏，必须手动加 <code>-D__HIP_PLATFORM_AMD__</code></li>
</ul>
<p dir="auto">另外把版本这条路也堵了：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>尝试</th>
<th>结果</th>
</tr>
</thead>
<tbody>
<tr>
<td>RCCL 2.27.7 另一构建（ROCm 7.2.4）</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 同一 bug</td>
</tr>
<tr>
<td>RCCL 2.26.6（ROCm 7.0.3）</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/26a0.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--warning" style="height:1.4em;width:auto;vertical-align:middle" title="⚠" alt="⚠" />️ 加载失败：<code>undefined symbol: ncclCommShrink</code></td>
</tr>
<tr>
<td>RCCL 2.22.3（ROCm 6.4.4）</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/26a0.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--warning" style="height:1.4em;width:auto;vertical-align:middle" title="⚠" alt="⚠" />️ 加载失败：<code>libamdhip64.so.6 missing</code></td>
</tr>
<tr>
<td><code>all_gather_single</code>（torch 2.13 新接口）</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 与 <code>all_gather_into_tensor</code> <strong>错法完全一样</strong></td>
</tr>
<tr>
<td><code>NCCL_MAX/MIN_NCHANNELS</code>、<code>ALGO=Tree</code>、<code>BUFFSIZE</code>、<code>CUMEM</code></td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 全无效</td>
</tr>
</tbody>
</table>
<p dir="auto">⇒ <strong>torch 2.13.0+rocm7.2 硬依赖 <code>ncclCommShrink</code>（2.27 才有），比 2.27 老的 RCCL 根本配不上。</strong> 所以换版本这条路在现有 torch 下走不通，补丁只能留着。</p>
<h2>二、P2P：便宜对照做完了，三类拓扑全部否（回应①）</h2>
<p dir="auto">先把槽位映射摸清了（全部实测）：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>PLX</th>
<th>CPU root</th>
<th>服务槽位</th>
</tr>
</thead>
<tbody>
<tr>
<td>PLX#1</td>
<td><code>00:03.0</code></td>
<td><strong>1、2、3 槽</strong>（下游口 10→9→8）</td>
</tr>
<tr>
<td>PLX#2</td>
<td><code>00:02.0</code></td>
<td><strong>4、5、6 槽</strong>（5 常被双槽卡挡住）</td>
</tr>
</tbody>
</table>
<p dir="auto">四组实测：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>组合</th>
<th>同交换机</th>
<th>链路</th>
<th>BAR</th>
<th><code>canAccessPeer</code></th>
</tr>
</thead>
<tbody>
<tr>
<td>1+4</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 跨 PLX</td>
<td>双 x16</td>
<td>双 32 G</td>
<td><strong>False</strong></td>
</tr>
<tr>
<td>2+4</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 跨 PLX</td>
<td>双 x16</td>
<td>双 32 G</td>
<td><strong>False</strong></td>
</tr>
<tr>
<td><strong>1+3</strong></td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> <strong>PLX#1</strong></td>
<td>双 x16</td>
<td>双 256 M</td>
<td><strong>False</strong></td>
</tr>
<tr>
<td><strong>4+6</strong></td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> <strong>PLX#2</strong></td>
<td><strong>双 x1</strong> <img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/26a0.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--warning" style="height:1.4em;width:auto;vertical-align:middle" title="⚠" alt="⚠" />️</td>
<td>双 256 M</td>
<td><strong>False</strong></td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>每轮都确认 <code>p2p_force</code> 钩子生效</strong>（<code>已卸载，强制 26/23 次，放行 0 次</code>），<br />
<code>hipDeviceCanAccessPeer</code> 与 <code>torch</code> 口径一致，<code>p2p-bootcheck.sh</code> 每轮 <code>[FAIL] KFD p2p 链路数=0</code>。</p>
<p dir="auto"><strong>⇒ 你那条假设（"若 256M 下已是 1，就先让 TP 跑起来再追 32G"）答案是否 —— 同 PLX + 256M 下也是 False。</strong><br />
三类拓扑穷举完毕，<strong>换槽这条路可以彻底排除了</strong>，剩下的变量只有内核。</p>
<p dir="auto">两条副产品：</p>
<ul>
<li><strong>4+6 槽同时插 → 链路掉 x1</strong>（Gen3 x1 ≈ 1 GB/s），这块板的硬限制，以后要避开</li>
<li><strong><code>pci=realloc</code> 不是双大 BAR 的必需项</strong>：2+4 那轮 cmdline 里没有它，两卡 BAR 照样 32 G（跨 PLX 时窗口装得下）</li>
</ul>
<h2>三、HiCache 单变量三组（回应③）</h2>
<p dir="auto">196K ctx + DFLASH + mamba，每次喂<strong>不同的</strong> 48.6K prompt（唯一前缀，强制 prefill miss）：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>配置</th>
<th>灌入 / host 池</th>
<th>结果</th>
</tr>
</thead>
<tbody>
<tr>
<td>ratio 2 + <code>write_back</code></td>
<td>97 K / 436 K（22%）</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 崩于第 3 个</td>
</tr>
<tr>
<td>ratio 2 + <code>write_through</code></td>
<td>389 K / 436 K（89%）</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 崩于第 9 个</td>
</tr>
<tr>
<td><strong>ratio 1 + <code>write_through</code></strong></td>
<td><strong>243 K / 218 K（111%）</strong></td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> <strong>5/5 全过，服务存活</strong></td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>灌到超过池容量 11%（必然触发驱逐）反而没崩，而 ratio 2 在 89% 就崩</strong> ⇒ 崩溃不是"池满比例"驱动，<br />
更像与 host 池规模有关（ratio 2 的 mamba + draft 主机内存是 ratio 1 的两倍）。</p>
<p dir="auto">配合你④的排查：<strong>ring timeout 0 次、GPU reset 0 次、OOM killer 0 次</strong>（全历史）⇒ 确实是进程内 abort。</p>
<p dir="auto">正面收益很明确：48.6K 的 prompt <strong>冷读 173 s → 前缀命中 2.1 s（≈82×）</strong>。</p>
<h2>四、另外两条新发现</h2>
<p dir="auto"><strong>① <code>gptq_marlin</code> 的提示是误导（浪费了我一次启动）</strong></p>
<p dir="auto">日志说：</p>
<pre><code>Detected that the model can run with gptq_marlin ... Use quantization=gptq_marlin for faster inference
</code></pre>
<p dir="auto">真按它改：</p>
<pre><code>ValueError: gptq_marlin quantization is currently not supported in ROCm.
</code></pre>
<p dir="auto"><strong>建议 ROCm 下把这条 warning 关掉</strong>，否则每个新用户都会踩一次。</p>
<p dir="auto"><strong>② ReBAR 的量化价值（之前帖子里只有定性说法，这次测出来了）</strong></p>
<p dir="auto">同一配置、同一张卡，只改 BAR：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th></th>
<th>32 GB BAR</th>
<th>256 MB BAR</th>
<th>损失</th>
</tr>
</thead>
<tbody>
<tr>
<td>单流</td>
<td>149.5</td>
<td>132.5</td>
<td><strong>−11.6%</strong></td>
</tr>
<tr>
<td>4 路</td>
<td>307.8</td>
<td>276.2</td>
<td><strong>−10.3%</strong></td>
</tr>
</tbody>
</table>
<h2>五、verify 路径 +25%（回应⑤的一半）</h2>
<p dir="auto"><code>SGLANG_RDNA_VLLM_VERIFY=1</code> 的资格判定里 <strong><code>page_size 1</code> 是硬条件</strong>，而 README 的 DFlash2 配方写的是 <code>--page-size 64</code> ⇒ 这条路径<strong>静默回退</strong>、连日志都不打。</p>
<p dir="auto">A/C 交替 2 轮 × 3 次（共 12 次测量）：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>配置</th>
<th>单流均值</th>
<th>4 路均值</th>
<th>单流波动</th>
</tr>
</thead>
<tbody>
<tr>
<td>page64，无 verify</td>
<td>117.3</td>
<td>249.6</td>
<td>103–132（±14%）</td>
</tr>
<tr>
<td><strong>page1 + verify=1</strong></td>
<td><strong>146.4</strong></td>
<td><strong>303.5</strong></td>
<td>141–149（±2.5%）</td>
</tr>
<tr>
<td>提升</td>
<td><strong>+24.8%</strong></td>
<td><strong>+21.6%</strong></td>
<td>波动大幅收窄</td>
</tr>
</tbody>
</table>
<p dir="auto">对照（page1 但<strong>不开</strong> verify）≈ 原状 ⇒ 收益全来自 verify，不是 page_size。8 路持平（452→455）。</p>
<blockquote>
<p dir="auto">⇒ 那份配方建议改成 <code>--page-size 1</code>，否则 fork 最强的优化一直关着。</p>
</blockquote>
<h2>六、四个问题</h2>
<p dir="auto"><strong>Q1 · HiCache 到底怎么配才稳？</strong><br />
你们的 <code>ratio</code> / <code>write policy</code> 是什么？我们这种"连续灌不同长 prompt"是否必然崩、还是实际用法里每次都前缀命中不触发？有没有已知规避法？</p>
<p dir="auto"><strong>Q2 · <code>page_size 1</code> 有没有长上下文代价？</strong><br />
我只测了 512 token 短请求（+25%）。它在 <strong>196K</strong> 下会不会有 KV 池碎片 / 长 decode 衰减？你们生产用 1 还是 64？如果还是 64，是踩过坑吗？</p>
<p dir="auto"><strong>Q3 · <code>wave</code> 后端是什么定位？</strong><br />
<code>wave_backend.py</code> 里有 gfx1100 专属调优（<code># M18: gfx1100-tuned override must not silently re-tune CDNA</code>、<code>is_rdna_supported</code>），但 README 说用 <code>triton</code>。wave 是实验性 / 已弃用 / 特定场景才用？gfx1100 上除 triton 还有更快的 attention 方向吗？</p>
<p dir="auto"><strong>Q4 · 7.0 内核下整套栈的兼容性（不只 P2P）</strong><br />
有人在 <strong>ROCm 7.2.3 + gfx1100 fork + 双卡 TP2</strong> 下跑过 7.0 内核吗？torch / triton / RCCL 都正常吗？SGLang 要不要重编？<br />
另外老实问一句：decode 时 GPU 有 94% 的时间 ≥95% busy（算力受限），P2P 就算通了折算 e2e 可能只有 +1~2% —— <strong>为这个升内核值不值？</strong></p>
<hr />
<p dir="auto">再次感谢两位。<a class="plugin-mentions-user plugin-mentions-a" href="/user/xiaote" aria-label="Profile: Xiaote">@<bdi>Xiaote</bdi></a> 那两条（"脱离 SGLang 复现"和"先做便宜对照"）直接帮我把问题从"猜"变成"定"了，尤其便宜对照一做，P2P 这条线当场就能结案。</p>
]]></description><link>https://lcz.me/post/30482</link><guid isPermaLink="true">https://lcz.me/post/30482</guid><dc:creator><![CDATA[南亚阿东]]></dc:creator><pubDate>Mon, 02 Nov 2026 05:20:56 GMT</pubDate></item><item><title><![CDATA[Reply to 【求助】X99 + 双 7900XTX + SGLang gfx1100 fork：TP2 通了（单流 122–130 t/s），但 RCCL all_gather 有坑、P2P 打不开、aiter 装不上，几点想请教 on Mon, 02 Nov 2026 01:37:59 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/%E5%8D%97%E4%BA%9A%E9%98%BF%E4%B8%9C" aria-label="Profile: 南亚阿东">@<bdi>南亚阿东</bdi></a> 这题论坛里已有实测答案，且就是 X99 + 交换卡 + 双 7900 XTX：</p>
<p dir="auto"><strong>1）补丁有，但不在 6.8 里</strong><br />
关键是 <code>PCI: Reserve prefetchable window headroom for Resizable BARs</code>（Geramy Loveless，series 520756，v3 2026-08-31）：它在 bridge sizing 阶段就给下游 ReBAR 预留窗口，不等驱动 resize 时再抢。laobenxiong 指了路（/post/20796），张光璞把补丁编进 7.0.14 实测（/post/20903）：旧内核 256M BAR / upstream 258M / P2P false；换新内核后两条下游链各 32GiB、upstream 64GiB、P2P true，RCCL 256MB allreduce 2.33 → 7.04 GB/s。他那台是 Broadcom PEX880xx，补丁逻辑对 PLX 同样适用，但要在 E WS 上复测。你 6.8 上 <code>pci=realloc</code> 卡 30 分钟，像是没有 headroom 逻辑时把整条 fabric（含启动盘）拆了重建，别在 6.8 硬凑。</p>
<p dir="auto"><strong>2）顺序</strong></p>
<ol>
<li>先量：<code>/proc/iomem</code> 的 prefetchable 够不够 64G；<code>lspci -vv</code> 看 PLX 上游 <code>Prefetchable memory behind bridge</code>。根窗口不够，补丁也变不出来，得先解决 BIOS 的 Above 4G / MMIO 窗口。</li>
<li>升 7.0.x（7.0.14 或 Ubuntu 7.0.0-38 都行），GRUB 加 <code>pci=realloc</code>，先跑基线。</li>
<li>打补丁（7.0.14 的 hunk #4 因 <code>pci_min_window_alignment</code> 改名 <code>window_alignment</code> 要手改），两卡同进 PLX#1 复测。</li>
<li>验收：两张卡 <code>Region 0 = 32G</code>、PLX 上游 <code>64G</code>、<code>rocm-smi --showtopo</code> 的 P2P weight；<code>NCCL_DEBUG=INFO</code> 确认走 <code>P2P/IPC</code> 不是 SHM。</li>
</ol>
<p dir="auto"><strong>3）先做便宜的对照</strong><br />
同 PLX + 256M BAR 先测 <code>can_access_peer</code>。BAR 影响大块映射效率，P2P 路由是 PLX 给的；若 256M 下已是 1，先让 TP 跑起来再追 32G，不必等内核。</p>
<p dir="auto">另：RCCL all_gather 再补 <code>NCCL_ALGO=Ring/Tree</code>、<code>NCCL_PROTO=Simple</code>、<code>NCCL_P2P_DISABLE=1</code> 三组对照，能分清算法/协议还是 P2P 路径；<code>page_size=1 + verify</code> 的 +25% 很值，顺带看 page1 对 prefix cache 影响。aiter 结论同意，gfx1100 不用再试。</p>
]]></description><link>https://lcz.me/post/30424</link><guid isPermaLink="true">https://lcz.me/post/30424</guid><dc:creator><![CDATA[Xiaote]]></dc:creator><pubDate>Mon, 02 Nov 2026 01:37:59 GMT</pubDate></item><item><title><![CDATA[Reply to 【求助】X99 + 双 7900XTX + SGLang gfx1100 fork：TP2 通了（单流 122–130 t/s），但 RCCL all_gather 有坑、P2P 打不开、aiter 装不上，几点想请教 on Mon, 02 Nov 2026 01:34:24 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/xiongjie-gao" aria-label="Profile: xiongjie-gao">@<bdi>xiongjie-gao</bdi></a> <a class="plugin-mentions-user plugin-mentions-a" href="/user/xiaote" aria-label="Profile: Xiaote">@<bdi>Xiaote</bdi></a> 两条新进展，外加一个 <strong>E WS 的硬约束</strong>想请教。</p>
<h2>一、原生 RCCL 复现：确认是 RCCL 自己的 bug（回应 <a class="plugin-mentions-user plugin-mentions-a" href="/user/xiaote" aria-label="Profile: Xiaote">@<bdi>Xiaote</bdi></a> 建议）</h2>
<p dir="auto">rccl-tests 需要 MPI 且本机没装，我改用 <strong>RCCL C API 直接测</strong>（<code>ncclCommInitAll</code> 单进程双卡，绕开 MPI）：</p>
<pre><code>RCCL version : 2.27.7-HEAD:96a25b5
Librccl path : /opt/rocm-7.2.3/lib/librccl.so.1

[rank0] recv = [20,20,20,20,0,0,0,0]       期望 [10,10,10,10,20,20,20,20] -&gt; BAD
[rank1] recv = [10,10,10,10,20,20,20,20]   期望 [10,10,10,10,20,20,20,20] -&gt; OK
[rank0] all_reduce = [30,30,30,30] OK
[rank1] all_reduce = [30,30,30,30] OK
</code></pre>
<p dir="auto"><strong>无 torch、无 SGLang、无 MPI，错误一模一样。</strong><br />
⇒ <strong>排除封装层，锁定 RCCL 2.27.7 的 <code>ncclAllGather</code> 实现</strong>。所以「问题在 SGLang 的 GroupCoordinator 缓冲/偏移」这个假设可以划掉了。</p>
<p dir="auto">顺手记两个编译坑（可能别人也会撞）：</p>
<ul>
<li>RCCL 7.2 的头文件改名成 <code>&lt;rccl/rccl.h&gt;</code>，<strong>没有 <code>nccl.h</code> 了</strong></li>
<li><code>hipcc -x c</code> 不会自动定义平台宏，必须手动加 <code>-D__HIP_PLATFORM_AMD__</code></li>
</ul>
<h2>二、fork 里有一条被 <code>page_size</code> 挡住的 +25%（可能对大家都有用）</h2>
<p dir="auto">对账 fork 的 DFlash2 生产配方时发现我们漏了 <code>SGLANG_RDNA_VLLM_VERIFY=1</code>。查代码后看到它的资格判定：</p>
<pre><code># Eligibility: target-verify or draft-extend-v2, page_size 1,
#             no sinks/window/score_mod, unity fp8 scales.
</code></pre>
<p dir="auto"><strong><code>page_size 1</code> 是硬条件。</strong> 而我一直在用 <code>--page-size 64</code> ⇒ 这条路径<strong>静默回退</strong>，连日志都不打。</p>
<p dir="auto">实测（A/C 交替 2 轮 × 3 次，共 12 次测量）：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>配置</th>
<th>单流 均值</th>
<th>4 路 均值</th>
<th>单流波动</th>
</tr>
</thead>
<tbody>
<tr>
<td>A：page64，无 verify</td>
<td>117.3</td>
<td>249.6</td>
<td>103.0–132.3（±14%）</td>
</tr>
<tr>
<td><strong>C：page1 + verify=1</strong></td>
<td><strong>146.4</strong></td>
<td><strong>303.5</strong></td>
<td>141.4–148.6（±2.5%）</td>
</tr>
<tr>
<td>提升</td>
<td><strong>+24.8%</strong></td>
<td><strong>+21.6%</strong></td>
<td>波动收窄</td>
</tr>
</tbody>
</table>
<p dir="auto">对照实验 B（page1 但<strong>不开</strong> verify）≈ A ⇒ <strong>收益全部来自 verify 路径，不是 page_size 本身</strong>。<br />
8 路聚合 452–462 → 455–462，<strong>持平</strong>（说明这条优化主要作用于低并发/单请求的 verify 阶段）。</p>
<blockquote>
<p dir="auto">⇒ 如果那份 DFlash2 配方还有人在用，<strong><code>--page-size 64</code> 建议改成 1</strong>，否则 fork 最强的优化等于关着。</p>
</blockquote>
<h2>三、<img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2b50.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--star" style="height:1.4em;width:auto;vertical-align:middle" title="⭐" alt="⭐" /> E WS 的硬约束：<strong>同 PLX 与 ReBAR 在这块板上互斥</strong></h2>
<p dir="auto">按 <a class="plugin-mentions-user plugin-mentions-a" href="/user/xiongjie-gao" aria-label="Profile: xiongjie-gao">@<bdi>xiongjie-gao</bdi></a> 的建议读了主板资料，再对照本机实测：</p>
<pre><code>CPU root 00:01.0 [x0 ] → bus 01  ← 空槽
CPU root 00:02.0 [x16] → bus 09 → PLX#2 ├ 0a:08.0 [x0] 空
                                        └ 0a:10.0 [x16] → GPU 0d
CPU root 00:03.0 [x16] → bus 03 → PLX#1 ├ 04:08.0 [x0] 空
                                        └ 04:10.0 [x16] → GPU 07
</code></pre>
<p dir="auto"><strong>每个 PLX 都还有一个空着的下游端口</strong>，看起来"把两卡塞进同一个 PLX"是最优解（PIX 本地路径）。但我 10-31 已经试过了：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>槽位方案</th>
<th>物理链路</th>
<th>BAR</th>
</tr>
</thead>
<tbody>
<tr>
<td>两卡分属两个 PLX（现状 4/6 槽）</td>
<td>双 x16 <img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /></td>
<td><strong>双 32 GB</strong> <img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /></td>
</tr>
<tr>
<td><strong>两卡同进 PLX#1（1/2 槽）</strong></td>
<td>双 x16 <img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /></td>
<td><strong>掉回 256 MB</strong> <img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /></td>
</tr>
</tbody>
</table>
<p dir="auto">内核日志给了原因：</p>
<pre><code>amdgpu 0000:0a:00.0: BAR 0 [mem size 0x800000000 64bit pref]: can't assign; no space
amdgpu 0000:07:00.0: BAR 0 [mem size 0x800000000 64bit pref]: can't assign; no space
</code></pre>
<p dir="auto"><strong>同一颗 PLX 的上游窗口装不下 2 × 32 GB = 64 GB</strong>，两块卡的大 BAR 只能退到 256 MB。<br />
我当时想用 <code>pci=realloc</code> 硬凑，结果<strong>机器卡在启动阶段约 30 分钟无法 ping 通</strong>，最后物理重启 + 分槽才救回来。</p>
<p dir="auto">⇒ 于是形成一个死结：</p>
<ul>
<li><strong>分槽（现状）</strong>：双 x16 + 双 32 GB BAR <img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" />，但两卡跨 PLX / 跨 root port ⇒ 路径 PHB ⇒ P2P 走不通</li>
<li><strong>同 PLX</strong>：P2P 的物理条件对了，但 <strong>BAR 掉到 256 MB</strong> ⇒ 显存访问变慢，得不偿失</li>
</ul>
<p dir="auto"><strong>问题</strong>：有没有人给这种 <strong>PLX 板</strong>打过内核的 BAR/realloc 补丁，让<strong>同一颗 PLX 下的两张卡都拿到大 BAR</strong>？<br />
我看到 lcz #1164 的作者提过一句「问题出在 kernel rescan 的逻辑上，需要 patch 内核，最终是可以做到两张卡都有 24G bar size」——如果那条路走得通，同 PLX + 双大 BAR 就都可能拿到，P2P 才有意义。</p>
<h2>四、aiter 确认对 gfx1100 无解（把我自己问题④划掉）</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>检查</th>
<th>结果</th>
</tr>
</thead>
<tbody>
<tr>
<td>PyPI 的 <code>aiter</code></td>
<td>是 <strong>2019 年的同名异步库</strong>（0.13.x），不是 AMD 那个</td>
</tr>
<tr>
<td>ROCm 7.2.3 / graphics 仓库</td>
<td><strong>没有 aiter 包</strong></td>
</tr>
<tr>
<td><code>aiter_backend.py</code> 的架构门槛</td>
<td>全是 <code>is_gfx95_supported()</code>、<code>gfx950 FP8 FMHA ASM kernels</code>、<code>ck_tile paged batch_prefill</code> ⇒ <strong>CDNA（MI300/MI350）专用</strong></td>
</tr>
</tbody>
</table>
<p dir="auto">⇒ gfx1100 上编出来也用不上那条 attention 路径，不必再试。</p>
<h2>五、接下来打算</h2>
<ol>
<li>若"同 PLX + 双大 BAR"有解 → 优先走这条（P2P 的物理前提 + ReBAR 都不丢）</li>
<li>内核升级到 7.0 的对照实验暂时押后（成本高，且要先确认上面那条有没有解）</li>
<li>HiCache 用 <code>write_back</code> / <code>ratio 1</code> 单变量各跑一轮 + 查 amdgpu ring timeout</li>
<li><code>gptq_marlin</code> 在 ROCm 上的差距量化</li>
</ol>
<p dir="auto">再次感谢两位，尤其 <a class="plugin-mentions-user plugin-mentions-a" href="/user/xiaote" aria-label="Profile: Xiaote">@<bdi>Xiaote</bdi></a> 那条"脱离 SGLang 复现"直接帮我把问题定死了。</p>
]]></description><link>https://lcz.me/post/30422</link><guid isPermaLink="true">https://lcz.me/post/30422</guid><dc:creator><![CDATA[南亚阿东]]></dc:creator><pubDate>Mon, 02 Nov 2026 01:34:24 GMT</pubDate></item><item><title><![CDATA[Reply to 【求助】X99 + 双 7900XTX + SGLang gfx1100 fork：TP2 通了（单流 122–130 t/s），但 RCCL all_gather 有坑、P2P 打不开、aiter 装不上，几点想请教 on Mon, 02 Nov 2026 00:05:17 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/%E5%8D%97%E4%BA%9A%E9%98%BF%E4%B8%9C" aria-label="Profile: 南亚阿东">@<bdi>南亚阿东</bdi></a> 补两个判断点，供你排优先级：</p>
<ol>
<li>
<p dir="auto"><strong>先把内核变量单独验证</strong>。已知打通的 X99-TF 案例是 7.0.0-38-generic，你跑的是 6.8.0-147；<code>p2p_force</code> 只把 <code>pci_p2pdma_distance_many</code> 的返回值改成 1，但 KFD 是否据此建 PCIe p2p link 是另一层（6.8 里 <code>kfd_build_p2p_node_entry</code> 主要服务 XGMI 路径）。在动 BIOS / PLX 拓扑前，先用 7.0 内核复跑同一套 <code>p2p-bootcheck</code>，能把「内核层」和「E WS 板级拓扑」拆开；否则后面每条结论都混着两个变量。</p>
</li>
<li>
<p dir="auto"><strong>RCCL all_gather 先脱离 SGLang 复现</strong>。用 rccl-tests 的 <code>all_gather_perf</code>（同机、同卡、同 RCCL 2.27.7）跑 1/2/4/8 MB，确认 rank0 结果错是否独立存在；再试 <code>NCCL_PROTO=Simple</code> 与换 RCCL 版本。若 rccl-tests 正常，问题就在 SGLang 的 GroupCoordinator 缓冲/偏移，不在 RCCL。</p>
</li>
</ol>
<p dir="auto">HiCache 的 SIGABRT 建议单变量：<code>write_back</code> 与 <code>ratio=1</code> 各跑一轮，别同时改；同时 <code>journalctl -k</code> 看有没有 amdgpu ring timeout。aiter 在 gfx1100 上不是全算子覆盖，编出来也只对部分 attention backend 有意义，优先级可放在 P2P 之后。</p>
]]></description><link>https://lcz.me/post/30398</link><guid isPermaLink="true">https://lcz.me/post/30398</guid><dc:creator><![CDATA[Xiaote]]></dc:creator><pubDate>Mon, 02 Nov 2026 00:05:17 GMT</pubDate></item><item><title><![CDATA[Reply to 【求助】X99 + 双 7900XTX + SGLang gfx1100 fork：TP2 通了（单流 122–130 t/s），但 RCCL all_gather 有坑、P2P 打不开、aiter 装不上，几点想请教 on Sun, 01 Nov 2026 16:18:03 GMT]]></title><description><![CDATA[<h2>P2P 路径与可行性</h2>
<p dir="auto"><img src="https://upload.lcz.me/uploads/d7e0656f-bde4-4bef-884b-4e9606f60455.jpeg" alt="image.jpeg" class="img-markdown  img-fluid" /></p>
<p dir="auto">这个有相当的可行性。好好研究一下。</p>
]]></description><link>https://lcz.me/post/30373</link><guid isPermaLink="true">https://lcz.me/post/30373</guid><dc:creator><![CDATA[xiongjie gao]]></dc:creator><pubDate>Sun, 01 Nov 2026 16:18:03 GMT</pubDate></item><item><title><![CDATA[Reply to 【求助】X99 + 双 7900XTX + SGLang gfx1100 fork：TP2 通了（单流 122–130 t/s），但 RCCL all_gather 有坑、P2P 打不开、aiter 装不上，几点想请教 on Sun, 01 Nov 2026 16:09:08 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/%E5%8D%97%E4%BA%9A%E9%98%BF%E4%B8%9C" aria-label="Profile: 南亚阿东">@<bdi>南亚阿东</bdi></a></p>
<ol>
<li>
<p dir="auto">那三个成功案例跑的是什么内核？ 仓库里我亲自验证并写进文档的只有一台：X99-TF + 7.0.0-38-generic 。cd3、t8是这个项目开发过程中的案例文档。目前项目包含的条件满足参考案例。</p>
</li>
<li>
<p dir="auto">关于正板不通寨板通的表示，是过于粗糙了。更严谨的表达应该是610和612南桥的X99，排除在外的是魔改X99。</p>
</li>
<li>
<p dir="auto">E WS这个板子情况特殊<br />
<img src="https://upload.lcz.me/uploads/56c5a292-c3fa-4632-bfaf-76f3fcad298a.jpeg" alt="image.jpeg" class="img-markdown  img-fluid" /></p>
</li>
</ol>
<p dir="auto">7个PCI槽，但直连CPU的还是40通道。更不要说它还额外增加了PLX的变数。这种情况下简单复制这个拓扑能一把成功，确实也是小概率事件。</p>
<p dir="auto">建议：从Bios设置入手，让AI阅读主板的说明书。设置好通道再设计拓扑补丁。</p>
]]></description><link>https://lcz.me/post/30364</link><guid isPermaLink="true">https://lcz.me/post/30364</guid><dc:creator><![CDATA[xiongjie gao]]></dc:creator><pubDate>Sun, 01 Nov 2026 16:09:08 GMT</pubDate></item><item><title><![CDATA[Reply to 【求助】X99 + 双 7900XTX + SGLang gfx1100 fork：TP2 通了（单流 122–130 t/s），但 RCCL all_gather 有坑、P2P 打不开、aiter 装不上，几点想请教 on Sun, 01 Nov 2026 15:14:32 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/xiongjie-gao" aria-label="Profile: xiongjie-gao">@<bdi>xiongjie-gao</bdi></a> 感谢！仓库完整跑完了，汇报结果：<strong>在 X99-E WS + kernel 6.8 上没打通</strong>。但用你的方法把卡点定位得很清楚了，另外有个<strong>矛盾</strong>想请教你。</p>
<h2>一、我的环境</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>项</th>
<th>值</th>
</tr>
</thead>
<tbody>
<tr>
<td>板 U</td>
<td><strong>ASUS X99-E WS</strong>（正牌）+ E5-2680 v4</td>
</tr>
<tr>
<td><strong>内核</strong></td>
<td><strong>6.8.0-147-generic</strong></td>
</tr>
<tr>
<td>ROCm / RCCL</td>
<td>7.2.3 / (2, 27, 7)</td>
</tr>
<tr>
<td>显卡</td>
<td>2× 7900 XTX（<code>1002:744c</code>, gfx1100）@ <code>07:00.0</code> / <code>0d:00.0</code></td>
</tr>
<tr>
<td>链路</td>
<td><strong>Gen3 x16 + x16</strong>（你的机器是上行 x8）</td>
</tr>
<tr>
<td>其他</td>
<td>128 G RDIMM ECC、Secure Boot off、<code>amdgpu.pcie_p2p=Y</code></td>
</tr>
</tbody>
</table>
<h2>二、前置条件 8 项逐条核对：全部通过</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>#</th>
<th>要求</th>
<th>实测</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>amdgpu 是模块</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> <code>.ko.zst</code></td>
</tr>
<tr>
<td>2</td>
<td><code>pci_p2pdma_distance_many</code> 导出</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> <code>T pci_p2pdma_distance_many</code></td>
</tr>
<tr>
<td>2b</td>
<td><code>CONFIG_KRETPROBES</code> / <code>CONFIG_PCI_P2PDMA</code> / <strong><code>CONFIG_HSA_AMD_P2P</code></strong></td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> 全 =y</td>
</tr>
<tr>
<td>3</td>
<td>Secure Boot off</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> disabled</td>
</tr>
<tr>
<td>4</td>
<td>IOMMU translated</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> 69 个组，两卡 group 55 / 62</td>
</tr>
<tr>
<td>5</td>
<td>BAR &gt; 4G 且 32 G</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> <code>at 380000000000 (64-bit, prefetchable) [size=32G]</code></td>
</tr>
<tr>
<td>6</td>
<td>ACS 关闭</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> 所有桥 <code>ECAP_ACS+0 = 0x000d</code>，<strong>bit6 <code>CtrEn = 0</code></strong></td>
</tr>
<tr>
<td>7</td>
<td>RCCL 2.27.x</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> (2, 27, 7)</td>
</tr>
</tbody>
</table>
<blockquote>
<p dir="auto">关于 ACS 我踩了个坑，可能对别人有用：<code>lspci -vv | grep -i ACS</code> 在我的板子上有 99 处命中，看起来像"ACS 开着"，但实际要看 <strong>ACS Control 寄存器的 bit6 <code>CtrEn</code></strong>。我的板子 <code>0x000d</code> —— <code>SrcValid/ReqRedir/UpstreamFwd</code> 这些位是默认值，<strong><code>CtrEn=0</code> 表示重定向并没有启用</strong>。用 <code>grep -i ACS</code> 判断会误判。</p>
</blockquote>
<h2>三、按你的流程执行</h2>
<pre><code class="language-bash">bash scripts/gen-topo.sh                       # 识别出 07:00.0 / 0d:00.0（另含内部交换机 06:00.0）
sudo bash kernel/install-p2p-kernel.sh --dkms  # DKMS + softdep + initramfs
sudo reboot
</code></pre>
<p dir="auto"><code>journalctl -k</code> 确认钩子在 amdgpu probe <strong>之前</strong>挂上（14:30:51 挂钩，amdgpu 之后才 probe）。</p>
<h2>四、结果：白名单确实被你绕过了，但 KFD 不上报链路</h2>
<p dir="auto">模块卸载时自己打印的计数：</p>
<pre><code>p2p_force: 已在 pci_p2pdma_distance_many 上挂钩（仅对 AMD 对端生效）
p2p_force: 已卸载，强制 26 次，放行 0 次
</code></pre>
<p dir="auto"><strong>26 次全部命中 AMD 对端、全部强制返回 1，放行 0 次</strong> —— 说明你设计的那道闸门在我这块板子上<strong>是通的</strong>。</p>
<p dir="auto">但同一时刻：</p>
<pre><code>node1: p2p_links_count = 0
node2: p2p_links_count = 0
canAccessPeer 0-&gt;1 = False    1-&gt;0 = False
</code></pre>
<p dir="auto"><code>p2p-bootcheck.service</code> 直接失败：</p>
<pre><code>[FAIL] KFD p2p 链路数=0（期望 &gt;=2）
</code></pre>
<p dir="auto"><code>p2p-preflight.sh</code> 在 <code>assert p01 and p10</code> 处退出。</p>
<p dir="auto"><strong>⇒ 我这边卡在第 3 层：6.8 的 amdgpu/KFD 没有依据"距离为正"去生成 PCIe p2p 链路。</strong> <code>kfd_build_p2p_node_entry</code> 这个符号在 6.8 的 amdgpu.ko 里存在，但可能只处理 XGMI。</p>
<h2>五、<img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2b50.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--star" style="height:1.4em;width:auto;vertical-align:middle" title="⭐" alt="⭐" /> 想请教的矛盾点</h2>
<p dir="auto">你上一条说：<strong>「cd3, t8, tf 都有一把打通的案例」</strong> —— 这三个（X99-CD3 / T8 / TF）都是<strong>华南克隆板</strong>。</p>
<p dir="auto">但你仓库 README 写得很明确：</p>
<blockquote>
<p dir="auto">Scope: genuine Intel X99 / C610 boards only … Clone "X99" boards (Huananzhi, JGINYUE, Maxsun and similar) typically ship with missing or broken VT-d, no Above-4G/ReBAR support, and ACS left on, so at least one of the gates fails. This repo offers no clone-board mode … Forcing peer mappings on firmware without working IOMMU translation can corrupt memory silently.</p>
</blockquote>
<p dir="auto"><strong>于是出现一个反例：克隆板都成功了，我这块正牌 E WS 反而失败。</strong></p>
<p dir="auto">所以想确认三件事：</p>
<ol>
<li><strong>那三个成功案例跑的是什么内核？</strong> 这是最关键的。
<ul>
<li>如果都是 ≥7.0 → 我的问题就是内核版本，答案明确了；</li>
<li>如果其中有 <strong>6.8</strong> 就跑通的 → 那就<strong>不是内核</strong>，而是 E WS 这块板的差异（PLX 拓扑 / BIOS），我的排查方向要换。</li>
</ul>
</li>
<li><strong>克隆板能跑通、正牌板跑不通，这个反例你怎么看？</strong> 是不是反过来说明那条"IOMMU 必须 translated"的门槛，克隆板在某些固件下反而更容易满足？还是说那三个案例其实没验证过 IOMMU 是否 translated？</li>
<li><strong>E WS 这块板有没有已知的额外坑？</strong>（比如 PLX 8747 在中间、两卡挂在不同 root port 下的组合）</li>
</ol>
<h2>六、顺便纠正我自己一个错误（影响价值判断）</h2>
<p dir="auto">我原帖写"SHM 已跑到 Gen3 x16 线速 <strong>99.7%</strong>，所以 P2P 对我没意义" —— <strong>这个算错了</strong>：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th></th>
<th>我之前</th>
<th>实际</th>
</tr>
</thead>
<tbody>
<tr>
<td>Gen3 <strong>x8</strong> 线速</td>
<td>—</td>
<td>7.877 GB/s</td>
</tr>
<tr>
<td>Gen3 <strong>x16</strong> 线速</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/274c.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--x" style="height:1.4em;width:auto;vertical-align:middle" title="❌" alt="❌" /> 说成 7.877</td>
<td><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:1.4em;width:auto;vertical-align:middle" title="✅" alt="✅" /> <strong>15.75 GB/s</strong></td>
</tr>
</tbody>
</table>
<p dir="auto">我把 x8 的线速当成 x16 了。真实对比：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th></th>
<th>你的机器（x8）</th>
<th>我的机器（x16）</th>
</tr>
</thead>
<tbody>
<tr>
<td>SHM 实测</td>
<td>3.96–4.14 GB/s</td>
<td><strong>7.857 GB/s</strong></td>
</tr>
<tr>
<td>占线速</td>
<td><strong>50%</strong></td>
<td><strong>50%</strong> ← 效率完全一致</td>
</tr>
<tr>
<td>P2P 实测</td>
<td><strong>5.03 GB/s = 64%</strong></td>
<td>未通</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>⇒ 两台的 SHM 效率一模一样都是 50%，你的 P2P 把 50% 提到 64%。</strong><br />
<strong>如果 6.8 能通，我这边应该能到 ~10 GB/s，即 +28%。</strong> 这个数字才是 P2P 对我真正的意义。</p>
<h2>七、我这边还剩的问题（如果你有思路，任何一条都很有用）</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>#</th>
<th>问题</th>
<th>现状</th>
</tr>
</thead>
<tbody>
<tr>
<td>①</td>
<td><strong>RCCL 2.27.7 <code>all_gather</code> 在 rank0 上算错</strong>（<code>all_reduce</code> 正常）</td>
<td>靠我在 SGLang <code>GroupCoordinator</code> 里打的补丁（用 all_reduce 手工实现 gather）绕过；torch 2.12.1/2.13.0 都一样错，gloo 正常</td>
</tr>
<tr>
<td>④</td>
<td><strong>aiter 未安装</strong></td>
<td><code>--attention-backend</code> 有 <code>aiter</code> 选项但库缺失；decode 时 GPU 93–94% 时间 ≥95% busy，怀疑是 GPTQ 反量化 + triton attention 的效率问题</td>
</tr>
<tr>
<td>⑤</td>
<td><strong><code>gptq_marlin</code> 在 ROCm 不可用</strong></td>
<td>只能走 <code>gptq</code>，差距未量化</td>
</tr>
<tr>
<td>⑥</td>
<td><strong>HiCache <code>write_through + ratio 2</code> 高负载 SIGABRT</strong></td>
<td>无 OOM 日志、离容量上限还远；<code>write_back</code> / <code>ratio 1</code> 还没试</td>
</tr>
<tr>
<td>⑦</td>
<td><strong>风扇控制写不进</strong></td>
<td><code>ppfeaturemask=0xffffffff</code> 已生效、功耗帽可写（231–402 W），但 <code>pwm1_enable</code>/<code>pwm1</code>/<code>fan1_target</code> 全部拒写</td>
</tr>
</tbody>
</table>
<h2>八、我的下一步打算</h2>
<ol>
<li><strong>换一个 RCCL 版本复测 all_gather</strong> —— 我目前只测过 2.27.7，如果别的版本正常，就能把补丁去掉（补丁每次 gather 多一次 all_reduce，是纯开销）</li>
<li>再尝试编 aiter（gfx1100）</li>
</ol>
<p dir="auto">如果你觉得这两条方向不对、或者有更该先试的，麻烦指一下。再次感谢，你仓库的文档（尤其"clone 板会静默损坏内存"那段）帮我省了很多判断时间。</p>
]]></description><link>https://lcz.me/post/30351</link><guid isPermaLink="true">https://lcz.me/post/30351</guid><dc:creator><![CDATA[南亚阿东]]></dc:creator><pubDate>Sun, 01 Nov 2026 15:14:32 GMT</pubDate></item></channel></rss>