<?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[双 2080 Ti（22G）跑 MiniMax-H3 张量并行 TP2 方案分享]]></title><description><![CDATA[<h1>双 2080 Ti（22G）跑 MiniMax-H3 张量并行</h1>
<h2>首先感谢原帖</h2>
<p dir="auto">这套东西能跑起来，全靠 <a href="https://lcz.me/topic/2643">《两张 7900 跑 MiniMax-H3 张量并行：每步 18.6 s → 8.3 s，每卡省 10 GiB》</a> 这个帖子的开路。原帖第 18 楼的代码（<code>tp/core.py</code>、<code>tp/tp_boot.py</code>、<code>tp/tp_linear.py</code>、<code>start_tp2.sh</code>）提供了完整的思路骨架，第 26 楼那张覆盖 832×480 到 1920×1088×362 的跑分表给了我们一个可以逐档对照的标尺。没有这些，下面的东西不存在。</p>
<p dir="auto">原帖是 2×W7900（48G、gfx1100、PCIe 4.0 x8 上行桥）。我们手上没有 48G 的卡，只有两张 22G 的 2080 Ti（sm_75、NV2 双 NVLink）。<strong>硬件代差整整三代，但最后在帖子自己发布的测试条件下跑到了同一水平线</strong>，中间靠的不是更聪明的算法，而是几处能不能把已经存在的内核真正用起来的差别。写出来给同核心、同显存的锤友做个参考。</p>
<hr />
<h2>一句话结论</h2>
<p dir="auto">832×480/124 帧/8 步：<strong>108.7 s</strong>（原帖 128 s），每步 8.21 s（原帖 7.68 s）。<br />
1600×896/124 帧/8 步：<strong>462.5 s</strong>（原帖 472 s），每步 <strong>45.49 s</strong>（原帖 46.9 s）。</p>
<p dir="auto">到 1600×896 我们<strong>反超</strong>。再往上 1920×1088 我们这两张 22G 卡装不下（1600×896 已用到 96.5% 显存），所以就此打住——这跟论坛里说"24G 单卡的上限大概在 1600×896"是一致的。</p>
<hr />
<h2>一、测试环境</h2>
<h3>硬件</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>项</th>
<th>规格</th>
</tr>
</thead>
<tbody>
<tr>
<td>GPU</td>
<td>2 × RTX 2080 Ti <strong>22 GB</strong>（改装版，22528 MiB），sm_75</td>
</tr>
<tr>
<td>GPU 互联</td>
<td><strong>NV2</strong> = 2 条 NVLink 绑定，单条 25.781 GB/s</td>
</tr>
<tr>
<td>CPU</td>
<td>Intel Xeon E5-2696 v4，22 核 44 线程</td>
</tr>
<tr>
<td>内存</td>
<td>64 GB</td>
</tr>
<tr>
<td>驱动</td>
<td>595.84</td>
</tr>
</tbody>
</table>
<h3>软件</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>项</th>
<th>版本</th>
</tr>
</thead>
<tbody>
<tr>
<td>系统</td>
<td>Ubuntu 24.04.4 LTS，内核 7.0.0-30</td>
</tr>
<tr>
<td>Python</td>
<td>3.12.3</td>
</tr>
<tr>
<td>PyTorch</td>
<td>2.14.1+cu130（CUDA 13.0）</td>
</tr>
<tr>
<td>ComfyUI</td>
<td>0.43.0（commit <code>7c4390a</code>）</td>
</tr>
<tr>
<td>ComfyUI-INT8-Fast</td>
<td>commit <code>48a88b2</code>，<strong>未做任何修改</strong></td>
</tr>
<tr>
<td>comfy-kitchen</td>
<td>0.2.40</td>
</tr>
<tr>
<td>comfy-aimdo</td>
<td>0.6.0</td>
</tr>
<tr>
<td>Triton</td>
<td>3.8（见下文：在 sm_75 上跑不了 INT8 dot）</td>
</tr>
</tbody>
</table>
<h3>模型</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>用途</th>
<th>文件</th>
</tr>
</thead>
<tbody>
<tr>
<td>DiT</td>
<td><code>minimax_h3_fl2va_pruned_int8_convrot.safetensors</code>（int8，per-output-row weight scale + Hadamard convrot group 256）</td>
</tr>
<tr>
<td>文本编码</td>
<td><code>qwen3vl_32b_minimax_h3_nvfp4_awq.safetensors</code></td>
</tr>
<tr>
<td>视频 VAE</td>
<td><code>minimax_h3_video_vae_fp16.safetensors</code></td>
</tr>
<tr>
<td>音频 VAE</td>
<td><code>minimax_h3_audio_vae_fp32.safetensors</code></td>
</tr>
</tbody>
</table>
<h3>测试方法</h3>
<ul>
<li>同一份工作流，先后提交到两个 ComfyUI 实例（rank0/rank1），一次只跑一个任务</li>
<li>启动参数：<code>--disable-async-offload --cache-none --use-ck-attention</code></li>
<li>832×480 / 124 帧 / 24 fps / <strong>8 步</strong>（<code>res_multistep</code> + <code>simple</code>，denoise 1.0）/ seed 145</li>
<li>"每步"取进度条的稳态值；"单镜耗时"取提交到两个 rank 都出片的墙钟时间（<strong>含加载、文本编码、VAE 解码、音频编解码</strong>）</li>
<li>显存按 0.5 s 间隔采样 <code>nvidia-smi</code>，取全程峰值</li>
</ul>
<hr />
<h2>二、方案长什么样</h2>
<h3>2.1 拓扑</h3>
<pre><code>                    ┌──────────────────────┐
   同一份工作流 ───▶ │ rank0（只看得到 GPU0）│ ─┐
                    └──────────────────────┘  │  NCCL 集合通信
                    ┌──────────────────────┐  │  （NV2 NVLink）
                 ───▶│ rank1（只看得到 GPU1）│ ─┘
                    └──────────────────────┘
</code></pre>
<ul>
<li>两个独立的 ComfyUI 进程，各自 <code>CUDA_VISIBLE_DEVICES</code> 只暴露一张卡</li>
<li><strong>每个进程的本地 device 恒为 0</strong>，这样 ComfyUI 主线程怎么设 current device 都不会和另一个 rank 撞同一张卡</li>
<li>两个进程用 NCCL 的一个 2-rank world，<code>MASTER_ADDR=127.0.0.1</code></li>
<li>工作流必须<strong>同时</strong>提交给两个 rank，DiT 里的 <code>all_reduce</code> 天然把它们锁在一起</li>
</ul>
<h3>2.2 切分方式（Megatron 式 TP）</h3>
<p dir="auto">只切 DiT，文本编码器 / VAE / final_layer 都不参与并行（残差流是复制的、不切）。</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>层</th>
<th>原形状</th>
<th>每卡形状</th>
<th>切法</th>
<th>通信</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>qkv_proj</code></td>
<td>[21504, 5376]</td>
<td>[10752, 5376]</td>
<td>列并行（56 头 → 每卡 28 头）</td>
<td>无</td>
</tr>
<tr>
<td><code>out_proj</code></td>
<td>[5376, 7168]</td>
<td>[5376, 3584]</td>
<td>行并行（K 轴切半）</td>
<td>1 次 all_reduce</td>
</tr>
<tr>
<td><code>mlp.fc1</code></td>
<td>[28672, 5376]</td>
<td>[14336, 5376]</td>
<td>列并行（gate/up 各切一半）</td>
<td>无</td>
</tr>
<tr>
<td><code>mlp.fc2</code></td>
<td>[5376, 14336]</td>
<td>[5376, 7168]</td>
<td>行并行（K 轴切半）</td>
<td>1 次 all_reduce</td>
</tr>
</tbody>
</table>
<p dir="auto">每个 block 2 次 all_reduce，50 个 block 共 100 次/步。</p>
<p dir="auto"><strong>关键技巧：在 state_dict 层切，不去改 ComfyUI 的模型代码。</strong> 切完 <code>qkv_proj</code> 行数从 21504 变成 10752，ComfyUI 会<strong>自己</strong>从张量形状推出 <code>heads=28</code>、<code>ffn=7168</code>，模型照半宽构造，不需要改一行源码，也避开了"先把 20G 全量读进来再切"的显存峰值。</p>
<p dir="auto">同样处理 <code>token_refiner</code> 的 2 个 bf16 block（它们的 qkv/fc1/fc2 形状和主 block 一致，会被同一套规则覆盖），并在加载时断言它们确实切到了 28 头——否则会静默地只切一半、然后对全宽结果多做一次 all_reduce，输出全错但不报错。</p>
<h3>2.3 每个 rank 都跑自己的一份完整流程</h3>
<p dir="auto">两个 rank 各自加载一半的 DiT 权重、各自的文本编码器、各自解码 VAE。看起来浪费，但<strong>它们并行执行，重复劳动被完全重叠掉了</strong>——实测两 rank 的 <code>Prompt executed</code> 相差 0.16%（333.29 s vs 333.81 s），所以合并 rank1 的文本编码对墙钟时间没有意义。</p>
<h3>2.4 音频</h3>
<p dir="auto">H3 的 DiT <code>forward</code> 返回的是 <code>[-video_out, -audio_out]</code> 一个嵌套 latent，采样器会把它整个带下去，<code>VAEDecodeAudio</code> 用 <code>samples["samples"].unbind()[-1]</code> 取音频。<strong>音频一直在算，缺的只是工作流里没接那条线</strong>：加一个音频 VAE 加载 + <code>VAEDecodeAudio</code>，再把 <code>CreateVideo</code> 的 <code>audio</code> 输入接上即可。实测音轨 32 kHz、时长与视频完全一致（5.167 s vs 5.167 s），100 ms 窗口 RMS 在 0.0025–0.0175 之间波动（有动态内容，不是静音）。</p>
<hr />
<h2>三、代码是什么样子的</h2>
<h3>3.1 文件清单</h3>
<pre><code>$LAB/
├── nodes/
│   ├── TP2Lab/__init__.py      (337 行)  张量并行钩子
│   ├── TP2FastOps/__init__.py  (280 行)  int8 内核选择 / 注意力后端 / profiler
│   └── TP2Profiler/__init__.py  ( 20 行)  ComfyUI 事件时序记录
├── tp2/slicing.py              ( 24 行)  state_dict 切分（与后端无关）
├── tools/
│   ├── arm.sh                  ( 85 行)  一次跑臂：起服务→提交→收产物→停服务
│   ├── add_audio.py            ( 37 行)  给工作流补音频分支
│   └── record-env.sh                     生成 env.lock（记录每次读数属于哪棵树）
├── start-tp2.sh                ( 21 行)  起两个 rank
├── start-comfy-cu130.sh        ( 20 行)  单实例启动 + 默认开关
└── benchmarks/                            工作流与全部测量结果
</code></pre>
<p dir="auto"><code>nodes/*</code> 以符号链接挂进 <code>&lt;ComfyUI&gt;/custom_nodes/</code>，这样源码留在自己的仓库里、ComfyUI 保持干净（上游三个仓库一行没改）。</p>
<h3>3.2 权重切分</h3>
<pre><code class="language-python"># tp2/slicing.py —— 在模型构造之前切 state_dict
def slice_state_dict(sd, rank, hidden=5376, heads=56, head_dim=128, ffn=14336):
    inner = heads * head_dim                       # 7168
    key = "blocks.0.attn.qkv_proj.weight"
    if key not in sd or tuple(sd[key].shape) != (3 * inner, hidden):
        raise ValueError("unexpected or already sliced checkpoint")

    half = inner // 2
    lo = rank * half
    inds = torch.arange(lo, lo + half)
    qidx = torch.cat([inds, inds + inner, inds + 2 * inner])   # q/k/v 三段各取本 rank 的头
    flo = rank * (ffn // 2)
    gidx = torch.cat([torch.arange(flo, flo + ffn // 2),
                      torch.arange(ffn + flo, ffn + flo + ffn // 2)])  # gate | up

    for k in list(sd):
        t = sd[k]
        if k.endswith(".attn.qkv_proj.weight") and tuple(t.shape) == (3 * inner, hidden):
            sd[k] = t[qidx].contiguous()
        elif k.endswith(".attn.out_proj.weight") and tuple(t.shape) == (hidden, inner):
            sd[k] = t[:, lo:lo + half].contiguous()
        elif k.endswith(".mlp.fc1.weight") and tuple(t.shape) == (2 * ffn, hidden):
            sd[k] = t[gidx].contiguous()
        elif k.endswith(".mlp.fc2.weight") and tuple(t.shape) == (hidden, ffn):
            sd[k] = t[:, flo:flo + ffn // 2].contiguous()
    return counts   # 还会断言四类投影数量一致，切漏了就抛
</code></pre>
<h3>3.3 行并行层的前向（技术特色之一，见第四节）</h3>
<pre><code class="language-python"># nodes/TP2Lab/__init__.py —— 行并行 int8 层：融合内核 + 一次归约
def quant_gemm(x, w, ws, bias, dtype):
    if bias is not None:
        raise RuntimeError("TP2 row bias unsupported")
    if x.ndim != 2:
        raise RuntimeError("TP2 row parallel expects 2D activations, got %s" % (tuple(x.shape),))

    # 一次 comfy_kitchen 融合调用完成 量化 + INT8 GEMM + 反量化
    out = _ck.int8_linear(x, w, ws.reshape(-1), None,
                          out_dtype=torch.float32, convrot=False)
    # 部分和在 fp32 下相加；每个 rank 用自己的量化 scale，
    # 只要在归约之前乘回去，和就是精确的
    dist.all_reduce(out, op=dist.ReduceOp.SUM)
    return out.to(dtype)
</code></pre>
<h3>3.4 block 前向：归约下移到层内</h3>
<pre><code class="language-python">def block_forward(self, x, t_emb, mod_segments, rope_freqs,
                  transformer_options={}, attention=None):
    att = self.attn if attention is None else attention
    sm, sc, gm, sf, sfc, gf = self.adaln_proj(t_emb)
    h = model._mod_scale_shift(self.norm1(x), sm, sc, mod_segments)
    a = att(h, rope_freqs=rope_freqs, transformer_options=transformer_options)
    # out_proj 内部已经做完了 all_reduce，这里不再重复
    if a.dtype != x.dtype:
        a = a.to(x.dtype)
    x = model._mod_gate(x, gm, a, mod_segments)
    h = model._mod_scale_shift(self.norm2(x), sf, sfc, mod_segments)
    m = self.mlp(h)                      # fc2 内部同样已经归约
    if m.dtype != x.dtype:
        m = m.to(x.dtype)
    return model._mod_gate(x, gf, m, mod_segments)
</code></pre>
<h3>3.5 角色标记 + fail-closed 分派</h3>
<p dir="auto">整张网里所有 int8 线性都被打上"是不是行并行"的标记，内核入口按标记决定走哪条路。<strong>在 DiT forward 内部碰到一个没有标记的 int8 线性就直接抛异常</strong>——那意味着有某条融合路径绕过了归约，静默继续会得到一个全错但不报错的结果。</p>
<pre><code class="language-python">def wrapper(x, w, ws, bias, dtype, _original=original):
    cur = getattr(ctx, "tp_cur", None)          # True=行并行, False=列并行, None=无标记
    if cur is True:
        return quant_gemm(x, w, ws, bias, dtype)
    if cur is False:
        return _original(x, w, ws, bias, dtype)
    if getattr(ctx, "in_model", False):
        raise RuntimeError("int8 linear reached the kernel from inside the DiT forward "
                           "without a role tag; a fused path bypassed the row-parallel "
                           "reduction. Refusing to continue.")
    return _original(x, w, ws, bias, dtype)     # 文本编码器等 DiT 之外的 int8 层
</code></pre>
<h3>3.6 启动</h3>
<pre><code class="language-bash"># start-tp2.sh —— rank1 先起，它会 block 在 init_process_group 等 rank0
TP2_RANK=1 CUDA_VISIBLE_DEVICES=1 MASTER_ADDR=127.0.0.1 MASTER_PORT=29675 \
  ./start-comfy-cu130.sh --listen 127.0.0.1 --port 18183 \
  --disable-async-offload --cache-none --output-directory $OUT/rank1
sleep 3
TP2_RANK=0 CUDA_VISIBLE_DEVICES=0 MASTER_ADDR=127.0.0.1 MASTER_PORT=29675 \
  ./start-comfy-cu130.sh --listen 127.0.0.1 --port 18182 \
  --disable-async-offload --cache-none --output-directory $OUT/rank0
</code></pre>
<pre><code class="language-bash"># start-comfy-cu130.sh —— 默认开关都在这里
export TP2_INT8_KERNEL="${TP2_INT8_KERNEL:-kitchen}"
export TP2_ROW_FUSED="${TP2_ROW_FUSED:-1}"
case "${TP2_ATTN_BACKEND:-ck}" in
  ck)   EXTRA_ATTN=(--use-ck-attention) ;;
  sdpa) EXTRA_ATTN=() ;;
esac
exec "$PY" main.py --listen 127.0.0.1 --port "${COMFY_PORT:-18181}" \
     --disable-auto-launch "$@" ${EXTRA_ATTN[@]+"${EXTRA_ATTN[@]}"}
</code></pre>
<hr />
<h2>四、两个真正提速的改动（技术特色）</h2>
<p dir="auto">这两处是整条链路上唯一<strong>显著</strong>的性能来源，其余改动都是正确性的。两处都不是自己写内核，而是<strong>把已经装在环境里、但默认没被用上的东西真正接上</strong>。</p>
<h3>特色 1：把注意力切到 Comfy Kitchen 的 INT8 实现 —— attention 快 3.47×</h3>
<p dir="auto"><strong>发现过程</strong>：一开始我们一直跑的是 PyTorch SDPA，日志每行都写 <code>Using pytorch attention</code>，跑了二十多次没人质疑。直到对着帖子发布的跑分表核对时才注意到：原帖那张表是 <code>--use-ck-attention</code> 跑出来的，而我们压根没开。</p>
<p dir="auto"><strong>为什么差别巨大</strong>：832×480/124 帧时序列长度 S ≈ <strong>14882</strong> token（注意这里包含音频 token，音频占 19% 却因为 O(S²) 吃掉 34% 的注意力时间）。在 sm_75 上，PyTorch 的 fp16 SDPA 走的是 <code>fmha_cutlassF_f16_aligned_32x128_rf_sm75</code>，实测 6.1 TFLOPS（fp32）/ 28.0 TFLOPS（fp16），一步要 11.72 s；而 Comfy Kitchen 的 INT8 注意力 <code>qk_int_sv_i8_attn_kernel</code> <strong>只要 3.38 s</strong>。</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>单卡，832×480×124</th>
<th>每步</th>
<th>单镜耗时</th>
</tr>
</thead>
<tbody>
<tr>
<td>fp32 注意力（PyTorch math 路径）</td>
<td>69.98 s</td>
<td>595.1 s</td>
</tr>
<tr>
<td>fp16 注意力（SDPA tensor core）</td>
<td>22.15 s</td>
<td>215.5 s</td>
</tr>
<tr>
<td><strong>CK INT8 注意力</strong></td>
<td><strong>14.31 s</strong></td>
<td><strong>150.0 s</strong></td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>一个坑</strong>：<code>comfy_kitchen.int8_attention_is_available(device)</code> 返回 True，但 <code>registry.get_implementation("int8_attention")</code> 报 "No backend available"。前者只查符号存在，<strong>这个探针不可信</strong>；实际调用走 <code>torch.ops</code>，是可用的。别因为 registry 报错就以为不能用。</p>
<pre><code class="language-bash"># 就这么简单，一个启动参数
python main.py --use-ck-attention ...
</code></pre>
<h3>特色 2：行并行层换成融合内核 —— 每步再省 10.7%，同时砍掉 100 次集合通信</h3>
<p dir="auto"><strong>改之前</strong>：行并行层是手写的一条 prologue——先把激活 upcast 到 fp32，求 per-row 的 <code>amax</code>，跨卡 <code>all_reduce(MAX)</code> 得到共享 scale，再 <code>div/round/clamp/to(int8)</code>，然后 <code>torch._int_mm</code>，最后 <code>acc.float() * scale * ws</code>。这条链每一层要好几次全量 HBM 往返，而且<strong>每层一次 <code>all_reduce(MAX)</code>，一步就是 100 次额外集合通信</strong>。</p>
<p dir="auto"><strong>改之后</strong>：一次 <code>comfy_kitchen.int8_linear</code>（量化 + INT8 GEMM + 反量化在同一个内核里），然后一次 <code>all_reduce(SUM)</code>。</p>
<p dir="auto"><strong>这里有个理论上的关键认识</strong>：原帖强调"行并行必须跨卡共享激活 scale"，否则每层约 1% 误差。这个结论在<strong>精度</strong>上是对的，但它不是<strong>正确性</strong>要求——只要每个 rank 在 <code>all_reduce</code> <strong>之前</strong>就用自己的 scale 把自己的部分和乘回去，求和的数学结果是精确的。所以我们放掉了共享 scale，换来一个完整内核，代价是量化网格和单卡不再逐点对齐（PSNR 15.23 dB 的差异，和这套管线上其他任何数值改动的量级一致）。</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>TP2，640×384×39</th>
<th>每步</th>
</tr>
</thead>
<tbody>
<tr>
<td>fp16 注意力 + 手写 prologue</td>
<td>2.41 s/it</td>
</tr>
<tr>
<td>CK 注意力 + 手写 prologue</td>
<td>1.49 s/it</td>
</tr>
<tr>
<td><strong>CK 注意力 + 融合行并行</strong></td>
<td><strong>1.33 s/it</strong></td>
</tr>
</tbody>
</table>
<p dir="auto">832×480×124 TP2 上：<strong>9.02 s/步 → 8.21 s/步，115.4 s → 108.7 s</strong>。</p>
<p dir="auto"><strong>另有一处被证伪的同类尝试</strong>（写出来省得大家重复踩）：把 convrot 的 Hadamard 旋转从"独立 fp32 matmul"折进 GEMM 的 prologue。数值上验证过两者是同一个 Regular-Hadamard 约定（相对误差 2.25e-4，用标准 Sylvester 做对照差 127.7），profile 里那个独立的 <code>volta_sgemm</code> 也确实消失了——<strong>但总时间 2.41 vs 2.39 s/it，净收益为零</strong>，因为 in-kernel 旋转本身要花掉等量的钱。默认关闭。</p>
<hr />
<h2>五、其余几处必要但不出速度的实现细节</h2>
<ol>
<li><strong>Triton 在 sm_75 上跑不了 INT8 dot。</strong> INT8-Fast 的 Triton 融合内核会编译失败（<code>TritonGPUAccelerateMatmul</code> pass 在 <code>target=cuda:75</code> 上直接 fail），所以它退化成 PyTorch fallback 路径。我们用 <code>comfy_kitchen.int8_linear</code> 顶上（实测比 fallback 快 1.5–2.0 倍，fp32 输入下数值差 1.8e-4），并且是<strong>两臂都换</strong>——单卡和 TP2 必须同一个内核，否则对照是假的。</li>
<li><strong><code>torch._scaled_mm</code> 在 sm_75 上不可用</strong>（要求 cc ≥ 8.9）。</li>
<li><strong>bf16 在 Turing 上是死路</strong>：没有 bf16 张量核，实测比 fp32 慢 23%；而且 sm_75 上没有 bf16 的 flash 内核，PyTorch 会退化成 materialize S×S 矩阵，S=12732 时要 33.8 GiB，直接 OOM。</li>
<li><strong>fp16 全局精度会溢出</strong>：int8 层的反量化输出会超出 fp16 的 65504 上限变成 inf，然后整条链变 NaN、出纯黑视频。逐层探针定位到第一个非有限值就出现在某个主 block 的 <code>out_proj</code> 输出上。所以<strong>残差流保持 fp32，只把注意力降到低精度</strong>——这也是特色 1 只改注意力的原因。</li>
<li><strong>rank0 的输入广播给 rank1</strong>：<code>x</code>/<code>timestep</code>/<code>context</code>/<code>denoise_mask</code> 每次求值前 broadcast，文本 embedding 也 broadcast 一次，保证两个 rank 从同一点出发。</li>
<li><strong><code>--cache-none</code> 是隐含的正确性依赖</strong>，不只是为了测量干净：两个 rank 的节点缓存状态若不对称，集合通信的次数就会错位，直接死锁。</li>
<li><strong>同步验证</strong>：两个 rank 产出的 mp4 <strong>SHA256 逐位相同</strong>，这一步比任何日志都能证明锁步、通信、拼接没出错。三档尺寸全部通过。</li>
</ol>
<hr />
<h2>六、测试结果</h2>
<h3>6.1 我们自己的三档（TP2，8 步，带音频）</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>分辨率</th>
<th>帧数</th>
<th>每步</th>
<th>单镜耗时</th>
<th>显存/卡</th>
<th>占 22G</th>
</tr>
</thead>
<tbody>
<tr>
<td>832×480</td>
<td>124</td>
<td><strong>8.21 s</strong></td>
<td><strong>108.7 s</strong></td>
<td>16,456 MiB</td>
<td>73.0%</td>
</tr>
<tr>
<td>1344×768</td>
<td>124</td>
<td><strong>28.01 s</strong></td>
<td><strong>299.1 s</strong></td>
<td>19,244 MiB</td>
<td>85.4%</td>
</tr>
<tr>
<td><strong>1600×896</strong></td>
<td>124</td>
<td><strong>45.49 s</strong></td>
<td><strong>462.5 s</strong></td>
<td><strong>21,732 MiB</strong></td>
<td><strong>96.5%</strong></td>
</tr>
</tbody>
</table>
<p dir="auto">三档全部：两 rank 输出逐位相同；音轨 32 kHz、时长与视频严格一致。</p>
<p dir="auto"><strong>1600×896 就是这张卡的顶。</strong> 96.5% 显存，再上一档 1920×1088 必然 OOM，所以没有测。</p>
<h3>6.2 与原帖跑分对比</h3>
<p dir="auto">原帖数据取自 <a href="https://lcz.me/topic/2643">topic/2643</a> 第 26 楼（2×W7900 48G，TP=2，PDD 8 步，<code>--use-ck-attention</code>）：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>分辨率</th>
<th>帧数</th>
<th>原帖每步</th>
<th><strong>我们每步</strong></th>
<th>每步比值</th>
<th>原帖单镜</th>
<th><strong>我们单镜</strong></th>
<th>单镜比值</th>
</tr>
</thead>
<tbody>
<tr>
<td>832×480</td>
<td>124</td>
<td>7.68 s</td>
<td>8.21 s</td>
<td>1.07× 慢</td>
<td>128 s</td>
<td><strong>108.7 s</strong></td>
<td><strong>0.85×</strong></td>
</tr>
<tr>
<td>1344×768</td>
<td>124</td>
<td>28.3 s</td>
<td><strong>28.01 s</strong></td>
<td>0.99×</td>
<td>297 s</td>
<td>299.1 s</td>
<td>1.01×</td>
</tr>
<tr>
<td>1344×768</td>
<td>175</td>
<td>46.6 s</td>
<td>未测</td>
<td>—</td>
<td>466 s</td>
<td>—</td>
<td>—</td>
</tr>
<tr>
<td><strong>1600×896</strong></td>
<td>124</td>
<td>46.9 s</td>
<td><strong>45.49 s</strong></td>
<td><strong>0.97×（快）</strong></td>
<td>472 s</td>
<td><strong>462.5 s</strong></td>
<td><strong>0.98×</strong></td>
</tr>
<tr>
<td>1920×1088</td>
<td>124</td>
<td>86.7 s</td>
<td>显存不足</td>
<td>—</td>
<td>835 s</td>
<td>—</td>
<td>—</td>
</tr>
<tr>
<td>1920×1088</td>
<td>362</td>
<td>534.9 s</td>
<td>显存不足</td>
<td>—</td>
<td>76 min</td>
<td>—</td>
<td>—</td>
</tr>
</tbody>
</table>
<p dir="auto">单卡 832×480×124 作为参考：我们 CK 版 <strong>14.31 s/步</strong>，原帖 CK 单卡 <strong>12.8 s/步</strong>（1.12×）。原帖 SDPA 单卡是 18.6 s/步。</p>
<h3>6.3 怎么读这张表</h3>
<ol>
<li><strong>差距随画面变大而消失，甚至在 1600×896 反超。</strong> 小尺寸慢 7%，中大尺寸打平到略快。原因很直接：两边现在跑的是同一套内核家族（CK INT8 注意力 + 融合 INT8 线性），token 量大时每步被"两边做同样的活"主导，剩下的差别只是固定开销。</li>
<li><strong>端到端反而更占优</strong>，因为我们的文本编码器是 nvfp4/AWQ 量化版、VAE 是 fp16，加载和编解码开销更小。832×480 那一档端到端快 15%。</li>
<li><strong>原帖"采样总计"那一列和"稳态每步"对不上</strong>（例如 1344×768：170 s ÷ 8 = 21.25 s，而每步标 28.3 s）。所以上面只比"每步"和"单镜耗时"这两个自洽的量，没有用采样总计。</li>
<li><strong>我们的"单镜耗时"包含音频解码 + 编码</strong>，原帖那批数据没说明是否含音频，所以这栏如果严格对齐我们略微吃亏。</li>
</ol>
<hr />
<h2>七、局限与没做的事</h2>
<ul>
<li><strong>只有 2 卡、只支持 world=2</strong>，代码里写死了；H3 的形状也写死了（hidden 5376、56 头 ×128、ffn 14336）。</li>
<li><strong>不支持 LoRA、不支持 bias</strong>，遇到会直接抛异常而不是静默降级。</li>
<li><strong>两个实例必须同时提交同一份工作流</strong>，否则会阻塞；不要暴露到公网。</li>
<li><strong>VRAM 是硬墙</strong>：22G 卡到 1600×896 为止。这一档和论坛里"24G 卡上限在 1600×896"的说法一致。</li>
<li>1920×1088 及以上没测（显存不足），1344×768×175 没测（时间关系）。</li>
<li>两卡都是改装 22G，<strong>这一条和原帖的官方 48G 卡不可比</strong>，只能说在同样 8 步、同样分辨率、同样 checkpoint 下达到了同一量级。</li>
</ul>
<hr />
<h2>八、踩过的坑（供同好省时间）</h2>
<ol>
<li><code>Using pytorch attention</code> 这一行值得每天看一遍——我们用错了很久才发现。</li>
<li><code>comfy_kitchen.int8_attention_is_available()</code> 会撒谎，registry 也会撒谎，以实际跑通为准。</li>
<li>ComfyUI 用<strong>绝对路径当模块名</strong>注册 custom node（<code>module_path.replace(".", "_x_")</code>），所以 <code>importlib.import_module("ComfyUI-INT8-Fast.int8_quant")</code> 拿到的是<strong>另一个模块对象</strong>，补丁打上去无效。要扫 <code>sys.modules</code> 找真正被加载的那份。</li>
<li><code>use_triton</code> 会被加载器每次 load 时重新置 True，运行时改类属性没用，得关模块级的 <code>_TRITON_AVAILABLE</code>。</li>
<li>想知道时间花在哪，别推算，上 profiler。我们靠 <code>torch.profiler</code> 否掉了自己三个"看起来很美"的估算（其中一个是把序列长度估小了 18%，而 attention 是 O(S²)，直接把 39% 的误差算成了"可优化空间"）。</li>
<li>这套管线<strong>完全确定</strong>：同内核同 seed 跑两次逐位相同。这很有用——任何画面差异都可以放心归因到改动本身，不必怀疑噪声。</li>
</ol>
<hr />
<h2>九、结语</h2>
<p dir="auto">再次感谢原帖。这条链路从接手时的 <strong>22.15 s/步</strong>（832×480，TP2）走到 <strong>8.21 s/步</strong>，2.7 倍，但归因很清楚：</p>
<ul>
<li><strong>CK INT8 注意力</strong>：3.47× 的 attention，整轮最大</li>
<li><strong>行并行融合内核</strong>：再 10.7%</li>
<li>音频：一个从未被解码的分支接线问题，不算优化</li>
<li>我自己拍脑袋估的四个"优化"（异步重叠气泡、convrot 折进内核、残差流融合、H2D 缓存）<strong>实测全部归零</strong></li>
</ul>
<p dir="auto">写这篇的目的不是证明老卡多能打，而是想说：<strong>很多时候瓶颈不在"你能不能写出更好的内核"，而在"你有没有发现环境里那个更好的内核压根没被调用"</strong>。希望这个记录能给同在老硬件上折腾的朋友省几个晚上。</p>
<p dir="auto">================11-01 13:00更新==================<br />
更新了一版代码，之前只对采样阶段分割并行，现在在解码阶段同样进行分割，提升解码阶段的处理速度。<a href="https://upload.lcz.me/uploads/a4ed2e8e-3a48-4d75-8bc4-024eb40402f9.gz" rel="nofollow ugc">minimax-h3-tp2-lab-code-20261101-1778fd5.tar.gz</a></p>
<p dir="auto">并做了与此帖子（<a href="https://lcz.me/topic/2707%EF%BC%89%E4%B8%AD%E6%B5%8B%E8%AF%95%E6%A1%88%E4%BE%8B%E7%BB%93%E6%9E%9C%E7%9A%84%E5%AF%B9%E6%AF%94%EF%BC%9A">https://lcz.me/topic/2707）中测试案例结果的对比：</a><br />
<img src="https://upload.lcz.me/uploads/e64ae480-1a59-418d-9a9e-0514eeb1b194.jpeg" alt="image.jpeg" class="img-markdown  img-fluid" /></p>
<p dir="auto">================11-03 01:00更新==================<br />
加入lora支持。<a href="https://upload.lcz.me/uploads/311e43fe-daf5-423b-8010-a15d7b6d3277.gz" rel="nofollow ugc">minimax-h3-tp2-lab-code-20261102-072529-d8d466c.tar.gz</a> minimax-h3-tp2-lab-code-20261102-072529-d8d466c.tar.gz</p>
]]></description><link>https://lcz.me/topic/2750</link><generator>RSS for Node</generator><lastBuildDate>Mon, 09 Nov 2026 08:22:19 GMT</lastBuildDate><atom:link href="https://lcz.me/topic/2750.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 31 Oct 2026 17:39:44 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to 双 2080 Ti（22G）跑 MiniMax-H3 张量并行 TP2 方案分享 on Sun, 01 Nov 2026 09:08:34 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> 怎么，这个ID很张狂吗？这点小性趣，大家不都是表面上柳下惠，事实上一触即溃吗？</p>
]]></description><link>https://lcz.me/post/30220</link><guid isPermaLink="true">https://lcz.me/post/30220</guid><dc:creator><![CDATA[terry]]></dc:creator><pubDate>Sun, 01 Nov 2026 09:08:34 GMT</pubDate></item><item><title><![CDATA[Reply to 双 2080 Ti（22G）跑 MiniMax-H3 张量并行 TP2 方案分享 on Sun, 01 Nov 2026 09:02:59 GMT]]></title><description><![CDATA[<p dir="auto">逛论坛我很少看ID，直到今天老特上节目，介绍作者@用包子丢狗 发现ID都这么有才华。直到我看到了你。。。<br />
＠JumpEggKiller<br />
兄弟大才，下次上老特节目让他怎么介绍你？<img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/1f913.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--nerd_face" style="height:1.4em;width:auto;vertical-align:middle" title=":nerd_face:" alt="🤓" /></p>
]]></description><link>https://lcz.me/post/30216</link><guid isPermaLink="true">https://lcz.me/post/30216</guid><dc:creator><![CDATA[xiongjie gao]]></dc:creator><pubDate>Sun, 01 Nov 2026 09:02:59 GMT</pubDate></item><item><title><![CDATA[Reply to 双 2080 Ti（22G）跑 MiniMax-H3 张量并行 TP2 方案分享 on Sun, 01 Nov 2026 08:56:37 GMT]]></title><description><![CDATA[<p dir="auto">2080TI魔改卡去年便宜的时候买过，才2天就花屏，退了以后就没有再敢碰</p>
]]></description><link>https://lcz.me/post/30215</link><guid isPermaLink="true">https://lcz.me/post/30215</guid><dc:creator><![CDATA[JumpEggKiller]]></dc:creator><pubDate>Sun, 01 Nov 2026 08:56:37 GMT</pubDate></item><item><title><![CDATA[Reply to 双 2080 Ti（22G）跑 MiniMax-H3 张量并行 TP2 方案分享 on Sun, 01 Nov 2026 04:43:30 GMT]]></title><description><![CDATA[<blockquote>
<p dir="auto"><a href="/user/%E7%94%A8%E5%8C%85%E5%AD%90%E4%B8%A2%E7%8B%97">@用包子丢狗</a> <a href="/post/30137">说</a>:</p>
<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/terry" aria-label="Profile: terry">@<bdi>terry</bdi></a> 代码已上传在#11楼，agent可以照着部署。</p>
</blockquote>
<p dir="auto">感謝有你</p>
]]></description><link>https://lcz.me/post/30159</link><guid isPermaLink="true">https://lcz.me/post/30159</guid><dc:creator><![CDATA[pofu lin 0]]></dc:creator><pubDate>Sun, 01 Nov 2026 04:43:30 GMT</pubDate></item><item><title><![CDATA[Reply to 双 2080 Ti（22G）跑 MiniMax-H3 张量并行 TP2 方案分享 on Sun, 01 Nov 2026 04:32:50 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/%E7%94%A8%E5%8C%85%E5%AD%90%E4%B8%A2%E7%8B%97" aria-label="Profile: 用包子丢狗">@<bdi>用包子丢狗</bdi></a> 兄弟们还是很给力，说实话给教程不是义务，但是能分享的，都是有格局的。</p>
]]></description><link>https://lcz.me/post/30153</link><guid isPermaLink="true">https://lcz.me/post/30153</guid><dc:creator><![CDATA[terry]]></dc:creator><pubDate>Sun, 01 Nov 2026 04:32:50 GMT</pubDate></item><item><title><![CDATA[Reply to 双 2080 Ti（22G）跑 MiniMax-H3 张量并行 TP2 方案分享 on Sun, 01 Nov 2026 04:00:16 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/terry" aria-label="Profile: terry">@<bdi>terry</bdi></a> 代码已上传在#11楼，agent可以照着部署。</p>
]]></description><link>https://lcz.me/post/30137</link><guid isPermaLink="true">https://lcz.me/post/30137</guid><dc:creator><![CDATA[用包子丢狗]]></dc:creator><pubDate>Sun, 01 Nov 2026 04:00:16 GMT</pubDate></item><item><title><![CDATA[Reply to 双 2080 Ti（22G）跑 MiniMax-H3 张量并行 TP2 方案分享 on Sun, 01 Nov 2026 03:49:49 GMT]]></title><description><![CDATA[<p dir="auto"><a href="https://upload.lcz.me/uploads/6e16e36c-2f22-4497-8e32-564fb0c6b9d2.gz" rel="nofollow ugc">minimax-h3-tp2-lab-code-20261101-3fef547.tar.gz</a> 项目代码已上传，可以据此让agent部署。代码是pi agent使用 deepseek v4.1 flash 1017开发。</p>
]]></description><link>https://lcz.me/post/30129</link><guid isPermaLink="true">https://lcz.me/post/30129</guid><dc:creator><![CDATA[用包子丢狗]]></dc:creator><pubDate>Sun, 01 Nov 2026 03:49:49 GMT</pubDate></item><item><title><![CDATA[Reply to 双 2080 Ti（22G）跑 MiniMax-H3 张量并行 TP2 方案分享 on Sun, 01 Nov 2026 03:42:16 GMT]]></title><description><![CDATA[<p dir="auto">我是看了下详细内容，哥们还是很懂，有空我根据这个帖子水一个视频，说实话，图灵架构能跑到这个水平，没有BF16的硬伤下速度依然这么好，出乎预料。详细配置出个可以抄作业的教程呢？你说的这些细节，其实大多数人看不懂。能跑就是真实，不能跑，毫无意义。让大家自己配，不现实。AI抄作业，也要足够的信息。</p>
]]></description><link>https://lcz.me/post/30117</link><guid isPermaLink="true">https://lcz.me/post/30117</guid><dc:creator><![CDATA[terry]]></dc:creator><pubDate>Sun, 01 Nov 2026 03:42:16 GMT</pubDate></item><item><title><![CDATA[Reply to 双 2080 Ti（22G）跑 MiniMax-H3 张量并行 TP2 方案分享 on Sun, 01 Nov 2026 03:39:48 GMT]]></title><description><![CDATA[<p dir="auto"><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>优秀</strong>升级为<strong>精华</strong>（两者互斥，只补差价），作者 <strong>+3 积分</strong>，累计 6 分。</p>
<blockquote>
<p dir="auto">补差凭证：优秀升精华 +3 分 · 编号 ef2750-4950-1</p>
</blockquote>
]]></description><link>https://lcz.me/post/30115</link><guid isPermaLink="true">https://lcz.me/post/30115</guid><dc:creator><![CDATA[Xiaote]]></dc:creator><pubDate>Sun, 01 Nov 2026 03:39:48 GMT</pubDate></item><item><title><![CDATA[Reply to 双 2080 Ti（22G）跑 MiniMax-H3 张量并行 TP2 方案分享 on Sun, 01 Nov 2026 03:38:28 GMT]]></title><description><![CDATA[<p dir="auto"><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>，作者 <strong>+3 积分</strong>奖励，继续加油！</p>
<blockquote>
<p dir="auto">奖励凭证：优秀 +3 分 · 编号 e2750-4950-1</p>
</blockquote>
]]></description><link>https://lcz.me/post/30110</link><guid isPermaLink="true">https://lcz.me/post/30110</guid><dc:creator><![CDATA[Xiaote]]></dc:creator><pubDate>Sun, 01 Nov 2026 03:38:28 GMT</pubDate></item><item><title><![CDATA[Reply to 双 2080 Ti（22G）跑 MiniMax-H3 张量并行 TP2 方案分享 on Sun, 01 Nov 2026 03:19:04 GMT]]></title><description><![CDATA[<p dir="auto">帖子正文是我按照跑llm时的卡功耗和频率设置跑的结果。现在补一个神力全开，功耗上限250w，核心频率取消限制的对比数据。（768p，24fps，124帧，step8）</p>
<p dir="auto"><img src="https://upload.lcz.me/uploads/4b5b99fa-7fac-4d29-86f1-6d597f773120.jpeg" alt="image.jpeg" class="img-markdown  img-fluid" /></p>
]]></description><link>https://lcz.me/post/30082</link><guid isPermaLink="true">https://lcz.me/post/30082</guid><dc:creator><![CDATA[用包子丢狗]]></dc:creator><pubDate>Sun, 01 Nov 2026 03:19:04 GMT</pubDate></item><item><title><![CDATA[Reply to 双 2080 Ti（22G）跑 MiniMax-H3 张量并行 TP2 方案分享 on Sun, 01 Nov 2026 01:53:23 GMT]]></title><description><![CDATA[<p dir="auto">2080ti看来还能在战3年</p>
]]></description><link>https://lcz.me/post/30037</link><guid isPermaLink="true">https://lcz.me/post/30037</guid><dc:creator><![CDATA[懒人烘培]]></dc:creator><pubDate>Sun, 01 Nov 2026 01:53:23 GMT</pubDate></item><item><title><![CDATA[Reply to 双 2080 Ti（22G）跑 MiniMax-H3 张量并行 TP2 方案分享 on Sun, 01 Nov 2026 00:04:33 GMT]]></title><description><![CDATA[<p dir="auto">不愧是N卡，老将军还是这么能打</p>
]]></description><link>https://lcz.me/post/30000</link><guid isPermaLink="true">https://lcz.me/post/30000</guid><dc:creator><![CDATA[xiongjie gao]]></dc:creator><pubDate>Sun, 01 Nov 2026 00:04:33 GMT</pubDate></item><item><title><![CDATA[Reply to 双 2080 Ti（22G）跑 MiniMax-H3 张量并行 TP2 方案分享 on Sat, 31 Oct 2026 18:08:44 GMT]]></title><description><![CDATA[<p dir="auto">赞！可惜，只是可惜稍微硬件有点老。</p>
]]></description><link>https://lcz.me/post/29965</link><guid isPermaLink="true">https://lcz.me/post/29965</guid><dc:creator><![CDATA[Bunsei]]></dc:creator><pubDate>Sat, 31 Oct 2026 18:08:44 GMT</pubDate></item><item><title><![CDATA[Reply to 双 2080 Ti（22G）跑 MiniMax-H3 张量并行 TP2 方案分享 on Sat, 31 Oct 2026 18:08:11 GMT]]></title><description><![CDATA[<p dir="auto">叹为观止，恐怖如斯</p>
]]></description><link>https://lcz.me/post/29964</link><guid isPermaLink="true">https://lcz.me/post/29964</guid><dc:creator><![CDATA[ikum]]></dc:creator><pubDate>Sat, 31 Oct 2026 18:08:11 GMT</pubDate></item><item><title><![CDATA[Reply to 双 2080 Ti（22G）跑 MiniMax-H3 张量并行 TP2 方案分享 on Sat, 31 Oct 2026 17:48:34 GMT]]></title><description><![CDATA[<p dir="auto">补充一下，我的卡钉死了功耗墙为180w，没有测试卡的极限250w的情况。</p>
]]></description><link>https://lcz.me/post/29960</link><guid isPermaLink="true">https://lcz.me/post/29960</guid><dc:creator><![CDATA[用包子丢狗]]></dc:creator><pubDate>Sat, 31 Oct 2026 17:48:34 GMT</pubDate></item></channel></rss>