<?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[【纯闲着】2700 块的洋垃圾跑 QFN：MI50 16G×2 + 128G DDR3，从装系统到 54 tok/s，这可能是目前价格最低的洋垃圾方案。]]></title><description><![CDATA[<h3>第二次调优结果放在#16</h3>
<p dir="auto">先说结论，再讲过程。</p>
<p dir="auto"><strong>这台机器现在稳定跑 54.0 tok/s（decode）、571 tok/s（prefill），支持 128K 上下文，使用 IQ3_S 量化，OpenAI + Anthropic 兼容接口常驻 8080。</strong></p>
<p dir="auto"><strong>显卡、内存、主板三件合计 2700 元</strong>：MI50 16G 每块 750 元，32G DDR3 REG ECC 4 条共 900 元，华南金牌 X99-TF 二手 300 元。</p>
<p dir="auto">折算下来：<strong>32GB HBM2 显存折合 46.9 元/GB，128GB DDR3 内存折合 7.0 元/GB</strong>。同样运行这个模型，一张 4080 SUPER 16G 大约能给到 58 tok/s，但仅那张卡的价格就足够配三台这样的机器。</p>
<hr />
<h2>一、硬件与成本</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>项目</th>
<th>型号 / 规格</th>
<th style="text-align:right">价格</th>
</tr>
</thead>
<tbody>
<tr>
<td>显卡</td>
<td>AMD Instinct MI50 16GB ×2（已改主动散热）</td>
<td style="text-align:right">750 × 2 = <strong>1500</strong></td>
</tr>
<tr>
<td>内存</td>
<td>DDR3 1333 RDIMM 32GB ×4（共 128GB）</td>
<td style="text-align:right"><strong>900</strong></td>
</tr>
<tr>
<td>主板</td>
<td>华南金牌 X99-TF（二手）</td>
<td style="text-align:right"><strong>300</strong></td>
</tr>
<tr>
<td>CPU</td>
<td>Intel Xeon E5-2696 v3（18 核 36 线程）</td>
<td style="text-align:right">未计入</td>
</tr>
<tr>
<td>硬盘</td>
<td>1TB NVMe（系统 + 模型）</td>
<td style="text-align:right">未计入</td>
</tr>
<tr>
<td>电源</td>
<td>长城 1250W 金牌</td>
<td style="text-align:right">未计入</td>
</tr>
<tr>
<td><strong>已计合计</strong></td>
<td>显存 32GB + 内存 128GB</td>
<td style="text-align:right"><strong>2700</strong></td>
</tr>
</tbody>
</table>
<p dir="auto">有几点值得单独说明：</p>
<ul>
<li><strong>MI50 是 HBM2，单卡 1024 GB/s</strong>。这不仅是“便宜的显存”，它的显存速度还超过很多家用卡。双卡合计 2TB/s 的名义带宽，是整个方案里最不合常理的性价比来源。</li>
<li><strong>DDR3 1333 四通道实测约 30 GB/s</strong>。这是这台机器真正的短板，后面所有调优都围绕它展开。</li>
<li>双卡各需 2×8pin，共 4 根；1250W 金牌电源完全过剩（没有做整机功耗实测，这里不编造数字）。</li>
<li><strong>BIOS 必须开启 <code>Above 4G Decoding</code></strong>，否则卡无法启动。</li>
<li>MI50 是涡轮或被动散热的服务器卡，<strong>必须改散热</strong>（我这套已改主动散热）。</li>
</ul>
<p dir="auto">硬件验收的原始数据（<code>lspci</code> / <code>sysfs</code> 实测）：</p>
<ul>
<li>两卡均为 <code>Vega 20 [1002:66a1]</code>，<strong><code>mem_info_vram_total</code> 各 16.0 GiB</strong>（确认是 16G 版，不是 32G 版）；</li>
<li><strong><code>LnkCap/LnkSta</code> 两卡都是 <code>Speed 16GT/s, Width x16</code></strong>，Gen3 x16 满血，无需争抢槽位；</li>
<li><code>/dev/kfd</code>、<code>/dev/dri/card1</code>、<code>card2</code>、<code>renderD128</code>、<code>renderD129</code> 齐全。</li>
</ul>
<hr />
<h2>二、这套卡为什么需要“自己编译”</h2>
<p dir="auto">gfx906 在 Strata 里是<strong>社区验证路径</strong>，官方的“支持的硬件”表里根本没有 MI50。这里有三条硬性约束：</p>
<ol>
<li><strong>官方 Setup 不会自动构建 gfx906</strong>，必须从源码自行构建，编译参数中带上 <code>-DSTRATA_HIP_GFX906=ON</code>（注意不是 <code>STRATA_ENABLE_HIP</code>，两者互斥，同时给出会直接触发 FATAL_ERROR）。</li>
<li><strong>ROCm 官方版已经不再包含 gfx906 的库</strong>，必须使用社区镜像 <code>mixa3607/rocm-gfx906:7.14-complete</code>，并走内核自带的 amdgpu 驱动，不使用 hipBLASLt。</li>
<li>宿主机<strong>不需要安装 ROCm</strong>，只需要内核 amdgpu、<code>/dev/kfd</code> 和 Docker，所有工具链都在容器里。</li>
</ol>
<p dir="auto">编译命令（在容器内执行，源码位于 <code>/src/Strata</code>）：</p>
<pre><code class="language-bash">cmake -S . -B build-906 -G Ninja \
  -DSTRATA_HIP_GFX906=ON \
  -DCMAKE_HIP_ARCHITECTURES=gfx906 \
  -DSTRATA_GGML_DIR=/src/llama.cpp \
  -DCMAKE_C_COMPILER=/opt/rocm/llvm/bin/clang \
  -DCMAKE_CXX_COMPILER=/opt/rocm/llvm/bin/clang++ \
  -DCMAKE_BUILD_TYPE=Release
ninja -C build-906 strata
</code></pre>
<p dir="auto"><strong>165/165 全部通过，36 线程约 3 分钟。</strong> 产出的二进制文件为 40MB；若在宿主机上直接运行，会报 <code>libhipblas.so.3: cannot open shared object file</code>，所以所有命令都必须在容器内通过 <code>docker exec</code> 执行，以免踩到这个坑。</p>
<p dir="auto">编译期唯一的坑是：<strong><code>include/strata/platform/hip_compat/strata_hip.h</code> 缺少两个映射宏</strong>。原因是 gfx906 构建不定义 <code>STRATA_USE_HIP</code>，<code>dflash2.cpp</code> 会走 CUDA 兼容分支，从而报 <code>use of undeclared identifier</code>。补上两行即可（上游有 PR #3986，但当时还没合入 0.2.11）：</p>
<pre><code class="language-c">#define cudaStreamCreateWithPriority hipStreamCreateWithPriority
#define cudaDeviceGetStreamPriorityRange hipDeviceGetStreamPriorityRange
</code></pre>
<hr />
<h2>三、模型：从 IQ3_XXS 换到 IQ3_S，体现了反直觉的正确决定</h2>
<p dir="auto">模型是 <code>ISTA-DASLab/Qwen3.8-Flash-Next-GSQ-RCO-GGUF</code>。它的体积口径很容易被误读：<strong>47.0GB 只是权重</strong>，实际下载量为 <code>47.04 + 28.80 = 75.84GB</code>——第二个分片是 28.8GB 的 per-token 表。</p>
<p dir="auto">下载走 <code>hf-mirror.com</code>，峰值 <strong>48.8 MB/s</strong>，75.84GB 用时 19 分 08 秒，下载完成后按精确字节数校验（这类数字必须一个字节不差）。</p>
<p dir="auto">构建 pack（使用 <code>tools/iq_pack.py</code>，注意<strong>必须加 <code>--experts-bin</code></strong>，否则 mmap 模式无法启动）：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>量化</th>
<th style="text-align:right">experts.bin</th>
<th style="text-align:right">dense.bin</th>
<th style="text-align:right">top-1 一致率</th>
<th style="text-align:right">专家槽位</th>
<th style="text-align:right">decode</th>
</tr>
</thead>
<tbody>
<tr>
<td>IQ3_XXS</td>
<td style="text-align:right">42.9 GB</td>
<td style="text-align:right">1.43 GiB</td>
<td style="text-align:right">84.46%</td>
<td style="text-align:right">15,123</td>
<td style="text-align:right">37.5</td>
</tr>
<tr>
<td><strong>IQ3_S</strong></td>
<td style="text-align:right"><strong>50.3 GB</strong></td>
<td style="text-align:right">1.54 GiB</td>
<td style="text-align:right"><strong>87.69%</strong></td>
<td style="text-align:right">12,741</td>
<td style="text-align:right"><strong>37.7</strong></td>
</tr>
</tbody>
</table>
<p dir="auto">我原本的判断是“专家块大 16.6%，显存槽位少 16%，decode 肯定会掉 8%”——<strong>实测没有下降，几乎持平</strong>。原因大概是命中率对槽位数并不敏感。因此在这台机器上换成更高精度档<strong>相当于免费获得质量提升</strong>，我把生产线直接换成了 IQ3_S。</p>
<p dir="auto">另外，IQ3_S 和 IQ3_XXS 的第二个分片（那 28.8GB 的表）<strong>逐字节相同</strong>，用软链接复用即可，省下 29GB 下载量。</p>
<hr />
<h2>四、调优全过程：六个台阶，从 28.3 到 54.0</h2>
<p dir="auto">每个数字都是先重启服务、空转 90 秒、用 6 条短请求预热之后才测得的（这点非常重要，见第五节）。全程使用同一台机器、同一份模型文件。</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>阶段</th>
<th>改动</th>
<th style="text-align:right">decode</th>
</tr>
</thead>
<tbody>
<tr>
<td>首跑</td>
<td>IQ3_XXS，出厂参数</td>
<td style="text-align:right">28.3</td>
</tr>
<tr>
<td>①</td>
<td><code>--spec 2</code> + <code>--pool-workers 32</code></td>
<td style="text-align:right">31.0</td>
</tr>
<tr>
<td>②</td>
<td><strong>解除 <code>--adapt-every 0</code></strong></td>
<td style="text-align:right"><strong>37.6</strong></td>
</tr>
<tr>
<td>③</td>
<td>换 IQ3_S</td>
<td style="text-align:right">37.7</td>
</tr>
<tr>
<td>④</td>
<td>升级 0.2.11 + <strong>DFlash2 草稿模型</strong></td>
<td style="text-align:right">49.3</td>
</tr>
<tr>
<td>⑤</td>
<td><strong>MTP 草稿 + <code>--pipeline-windows 2</code> + <code>--trim-stage-weights</code></strong></td>
<td style="text-align:right"><strong>54.0</strong></td>
</tr>
</tbody>
</table>
<p dir="auto">最后一轮使用官方口径（1.6K prompt / 128 token / temp 0）复核过的五组对照：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>组合</th>
<th style="text-align:right">decode</th>
<th style="text-align:right">prefill</th>
</tr>
</thead>
<tbody>
<tr>
<td>官方原参数（无草稿层）</td>
<td style="text-align:right">34.8</td>
<td style="text-align:right">—</td>
</tr>
<tr>
<td>+ <code>--pipeline-windows 2</code>（该组合下开关被静默关闭，见第五节）</td>
<td style="text-align:right">35.9</td>
<td style="text-align:right">—</td>
</tr>
<tr>
<td>+ MTP 草稿</td>
<td style="text-align:right">47.1</td>
<td style="text-align:right">—</td>
</tr>
<tr>
<td>+ MTP + 流水线 + trim（IQ3_XXS）</td>
<td style="text-align:right">51.8</td>
<td style="text-align:right">—</td>
</tr>
<tr>
<td><strong>+ MTP + 流水线 + trim（IQ3_S）</strong></td>
<td style="text-align:right"><strong>54.0</strong></td>
<td style="text-align:right"><strong>571</strong></td>
</tr>
<tr>
<td>同机 IQ3_S + DFlash2</td>
<td style="text-align:right">48.3</td>
<td style="text-align:right">571</td>
</tr>
<tr>
<td>官方参考机（2×MI50 16G，0.1.43.1，IQ3_XXS）</td>
<td style="text-align:right">49.2</td>
<td style="text-align:right">353</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>比官方参考机快 10%，prefill 高 62%，而且量化档更高。</strong></p>
<p dir="auto">关键参数（生产配置）：</p>
<pre><code class="language-json">{
  "exe": "/src/Strata/build-906/strata",
  "args": [
    "--pack", "/src/models/packs/iq3s",
    "--native", ".../IQ3_S-00001-of-00002.gguf",
    "--ple-gguf", ".../IQ3_S-00002-of-00002.gguf",
    "--expert-profile", "/src/models/learned-iq3s.bin",
    "--expert-profile-save", "/src/models/learned-iq3s-mtp.bin",
    "--expert-profile-save-every", "3",
    "--expert-cache", "auto",
    "--prefill", "auto",
    "--spec", "3",
    "--max-context", "131072",
    "--kv", "int8", "--kv-resident", "32768",
    "--layer-split", "27", "--trim-stage-weights",
    "--mtp", "/src/models/mtp/rt",
    "--pipeline-windows", "2",
    "--pool-workers", "32",
    "--pcie-frac", "0", "--vram-reserve-mib", "1024"
  ],
  "env": { "STRATA_RESIDENT_HEADROOM_GIB": "6" }
}
</code></pre>
<hr />
<h2>五、三个“静默失效”的坑，比参数本身更重要</h2>
<p dir="auto">这三个坑的共同点是：<strong>服务仍然让 <code>/health</code> 返回 ok，也仍然正常输出文字，但你调的东西根本没有生效。</strong></p>
<h3>1. <code>--adapt-every 0</code> 会静默关闭自适应专家缓存层</h3>
<p dir="auto">官方冒烟命令里带着 <code>--adapt-every 0</code>，我早期配置直接继承了它。后果是：</p>
<ul>
<li>专家缓存退化成出厂 profile 的静态 15,123 个槽位，<strong>永远不会学习</strong>——同一批请求连续测三遍，命中率分别为 0.709 / 0.711 / 0.711，一个数都没变；</li>
<li><code>--expert-profile-save</code> 根本不会落盘。</li>
</ul>
<p dir="auto">引擎原话：</p>
<pre><code>strata serve: --expert-profile-save needs the adaptive tier
  (--adapt-every and --adapt-swaps above 0) and --expert-profile: nothing will be saved
</code></pre>
<p dir="auto">去掉这个参数后，命中率直接从 0.71 跳到 0.98，<strong>decode 提升 27%</strong>（从 29.7 到 37.6）。这是整台机器上成本最低的一次提速，代价只是删掉四个字符。</p>
<h3>2. <code>--pipeline-windows 2</code> 必须配合 MTP，否则会被静默禁用</h3>
<p dir="auto">我第一次测试流水线时，前后两轮都“没有收益”，于是得出了“流水线无用”的结论。后来补加 <code>--mtp</code> 才发现日志里一直写着：</p>
<pre><code>strata generate: --pipeline-windows 2 is off: it needs the MTP drafter (--mtp, --spec)
</code></pre>
<p dir="auto"><strong>这个开关只作用于 MTP 草稿路径。</strong> 它生效时的自检行是下面这三条：</p>
<pre><code>strata mtp: draft layer loaded, 837 MiB of VRAM (experts 675, dense 111)
--pipeline-windows 2: 290 MiB of CUDA0 kept out of the expert cache
--pipeline-windows 2: two verifiers per stage, 2 stages overlap across windows (decode too)
</code></pre>
<h3>3. DFlash2 和流水线<strong>不能共存</strong>，这是源码里写死的</h3>
<p dir="auto">DFlash2 从“已经跑完的那个窗口的 hidden taps”里起草，而流水线的本质是让两个窗口在时间上重叠，两者的数据依赖直接冲突。源码 <code>generate.cpp:7103</code> 的拒绝理由如下：</p>
<pre><code>it does not run beside --pipeline-windows (the MTP's speculative next
window has no DFlash2 counterpart); --pipeline-windows 0
</code></pre>
<p dir="auto">所以只能二选一：DFlash2（48.3）或 MTP + 流水线（<strong>54.0</strong>）。顺带说，<code>--draft auto</code>（两个草稿按请求二选一）也不适用于双卡 layer split，源码写明它是给“单卡、单请求”使用的。</p>
<hr />
<h2>六、测速方法学：否则测出来的结果并不可靠</h2>
<p dir="auto">这点我和公开的 fieldnotes 结论完全一致，值得单独说明：</p>
<ol>
<li><strong>重启后必须空转 ≥90 秒，再发 6 条预热请求，然后才能开始计分。</strong> 冷启动后首次测量的数字会偏低 30–40%，而且不同配置的冷启动偏差不同——如果拿第 1 个样本做 A/B 对比，结论会非常自信却完全错误。</li>
<li><strong>重启必须同时杀掉 <code>serve.server</code> 和引擎子进程，并且要在容器内执行 pkill。</strong> 如果只杀引擎，<code>serve.server</code> 会立刻把它重新拉起来并继续占用 8080，新实例会静默失败，<code>/health</code> 会立刻返回旧服务的响应——我第一轮就是这样把上一版的数字当成了这一版的。</li>
<li><strong>启动后核对 <code>/v1/models</code> 的模型名是否等于本配置的 <code>model_name</code></strong>，如果不一致，直接中止测量。</li>
<li>权威数字取 <code>/metrics</code> 中服务端自报的行，不要用客户端 wall time 估算。</li>
<li>修改配置时删除参数，要<strong>连它的值一起删除</strong>，否则残留值会变成位置参数，报 <code>unknown argument: 2</code>，而 serve 只会说“引擎启动前退出”。</li>
</ol>
<hr />
<h2>七、128K 上下文和内存的实际分配方式</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>位置</th>
<th>内容</th>
<th>实测</th>
</tr>
</thead>
<tbody>
<tr>
<td>显存（两卡）</td>
<td>专家缓存 + dense 权重 + 草稿层 + KV 窗口</td>
<td>每卡约 15.9 / 16.0 GiB，余量 1.1 GiB</td>
</tr>
<tr>
<td>系统内存</td>
<td>PLE 表 26.8 GiB（锁页）</td>
<td><code>--ple-io ram</code> 自动选中</td>
</tr>
<tr>
<td>系统内存</td>
<td>专家常驻 arena / 文件页缓存</td>
<td>50.3 GB 的 experts.bin</td>
</tr>
<tr>
<td>系统内存</td>
<td>KV 后备</td>
<td><code>--kv-resident 32768</code>：每 QSA 层 32768/131072 个 cell 在显存，其余 K/V 落在锁页内存（早期设 20480 时实测锁页 K/V 为 0.77 GiB）</td>
</tr>
</tbody>
</table>
<p dir="auto">要点是：<strong>128K 上下文不等于把 128K KV 全部塞进显存。</strong> 这个模型 48 层里只有 12 层 QSA 需要 KV，其余 36 层是 GDN 线性注意力，KV 成本天然就小；再配合 <code>--kv int8</code> 和 <code>--kv-resident 32768</code> 的流式方案，就能实现。</p>
<p dir="auto">实测长 prompt 表现：</p>
<ul>
<li>61,859 token 冷预填耗时 <strong>92.8 秒 ≈ 666 tok/s</strong>；</li>
<li>15.6K token 预填约 29 秒；</li>
<li>64–69K token 的长会话因为复用了 conversation cache，decode 达到 <strong>33.5–54.8 tok/s、命中率 0.78–0.93</strong>。</li>
</ul>
<p dir="auto">冷启动到 <code>/health</code> ok：<strong>84 秒</strong>（首次锁页的那几分钟会很安静，别以为程序挂了）。</p>
<hr />
<h2>八、横向对比</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>平台</th>
<th>卡</th>
<th style="text-align:right">decode</th>
<th>备注</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>本机</strong></td>
<td><strong>2×MI50 16G</strong></td>
<td style="text-align:right"><strong>54.0</strong></td>
<td>IQ3_S + MTP + 流水线</td>
</tr>
<tr>
<td>官方参考机</td>
<td>2×MI50 16G</td>
<td style="text-align:right">49.2</td>
<td>IQ3_XXS，Ryzen 7 5700X + DDR4-3600</td>
</tr>
<tr>
<td>社区同卡</td>
<td>2×Radeon Pro VII 16G</td>
<td style="text-align:right">47.8</td>
<td>IQ3_S，Ryzen 5 2600 + DDR4-2133</td>
</tr>
<tr>
<td>单卡 4080 SUPER</td>
<td>1×16G</td>
<td style="text-align:right">58.8</td>
<td>IQ3_XXS，i7-12700 + DDR4-3200</td>
</tr>
<tr>
<td>同机 llama.cpp</td>
<td>2×MI50 16G</td>
<td style="text-align:right">26.3–26.6</td>
<td>Qwen3.8-<strong>27B</strong> UD-Q4_K_M，pp 228.5</td>
</tr>
</tbody>
</table>
<p dir="auto">两点说明：一是<strong>同一张卡搭配不同 CPU，差距非常明显</strong>，我测得 54.0，而公开数据是 47.8，差异主要来自 MTP + 流水线这套组合，并不完全由硬件决定；二是 27B dense 在这套卡上只有 26 tok/s 量级，而 125B 总参 / 6B 激活的 MoE 反而更快——<strong>这台机器注定应该跑 MoE</strong>。</p>
<hr />
<h2>九、性价比换算</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>口径</th>
<th style="text-align:right">数字</th>
</tr>
</thead>
<tbody>
<tr>
<td>显卡/内存/主板合计</td>
<td style="text-align:right">2700 元</td>
</tr>
<tr>
<td>显存成本</td>
<td style="text-align:right">46.9 元 / GB（HBM2）</td>
</tr>
<tr>
<td>内存成本</td>
<td style="text-align:right">7.0 元 / GB</td>
</tr>
<tr>
<td>每 1000 元买到的 decode</td>
<td style="text-align:right"><strong>20 tok/s</strong></td>
</tr>
<tr>
<td>对比：4080 SUPER 16G</td>
<td style="text-align:right">单卡价格约 3–4 倍，decode 只高 9%</td>
</tr>
</tbody>
</table>
<p dir="auto">再补充两点：<strong>MI50 单卡标称 300W TDP，但轻载推理时的实际功耗并不高</strong>，1250W 电源纯属过剩；这台机器<strong>同时还能当 128GB 内存的普通服务器使用</strong>（我平时在上面跑 Docker 做杂活）。</p>
<p dir="auto">一句话概括：<strong>用显存买速度，用内存买容量，用老 CPU 硬扛剩下的部分——这条路能走通，前提是你愿意花一晚上编译。</strong></p>
<hr />
<h2>十、未验证 / 待办事项</h2>
<p dir="auto">这里如实标注，避免误导：</p>
<ol>
<li><strong>质量还没有做正式评测。</strong> 目前只跑了冒烟测试和讲义风格的中文长文样本（情境、公式、易错点齐全，没有套话）。3bit 在中文长文上的典型失效是重复、断段、术语漂移，<strong>这需要真材料 A/B 对比才算数</strong>。</li>
<li><strong>没有测试满 128K 的检索质量</strong>，最长实测输入为 61.9K。</li>
<li><strong>没有测试并发</strong>。官方和社区都说这条路径并发不行，我也没有尝试。</li>
<li><strong>没有做整机功耗和温度实测</strong>，散热是改过的，长期稳定性只观察了一天。</li>
<li>0.1.57 的 <code>--draft mtp</code> 能否也配合流水线，还没有验证——我现在使用 0.1.55 是为了稳妥；DFlash2 那条线保留在 <code>/src/Strata-0211</code>，随时可以切换。</li>
<li>层切分只试了 27/21（按官方给出的值），没有穷举，不要当成全局最优。</li>
</ol>
<hr />
<h2>十一、一句话总结</h2>
<p dir="auto"><strong>750 元一块的 16G HBM2 卡两张、900 元的 128G DDR3、300 元的二手主板，总计 2700 元，达到 54 tok/s，支持 128K 上下文，兼容 OpenAI/Anthropic 双接口。</strong></p>
<p dir="auto">真正花时间的不是攒机，而是搞清楚<strong>哪些开关是真正生效的</strong>：<code>--adapt-every 0</code> 会让性能损失 27%，<code>--pipeline-windows 2</code> 在没有 MTP 时不会生效，DFlash2 和流水线在源码级就是互斥的。这三个坑的信息量，比任何一个调参数字都大。</p>
]]></description><link>https://lcz.me/topic/2896</link><generator>RSS for Node</generator><lastBuildDate>Mon, 09 Nov 2026 10:07:47 GMT</lastBuildDate><atom:link href="https://lcz.me/topic/2896.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 07 Nov 2026 06:20:39 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to 【纯闲着】2700 块的洋垃圾跑 QFN：MI50 16G×2 + 128G DDR3，从装系统到 54 tok/s，这可能是目前价格最低的洋垃圾方案。 on Mon, 09 Nov 2026 08:41:04 GMT]]></title><description><![CDATA[<h1>暂时最后一弹：Q3.8 FN参数到顶之后，我换了3.6 35B A3B对比了一下</h1>
<p dir="auto">（2×MI50 16GB + DDR3-1333 的第三轮）</p>
<p dir="auto">QFN参数扫完，这台机器停在 decode 67.83 tok/s、窗口 160K、专家命中 97–99%。</p>
<p dir="auto">结论：</p>
<ul>
<li>现役定版跑出 decode 67.83（三个样本 64.94 / 67.83 / 70.27）、长 prefill 716–727 tok/s、18K 冷预填 736.6 tok/s，窗口 160K</li>
<li>q36 最好成绩是短上下文 98.8 tok/s、18K 冷预填 962 tok/s、18K 复用后 38.2 tok/s，窗口 32K</li>
<li>继续用 Flash-Next。q36 赢的那一格现役已经够用，其余都在输</li>
</ul>
<h2>数字是怎么量的</h2>
<p dir="auto">decode 走流式请求，取 <code>usage</code> 自报的计数，同一配置连发三次取中位。长预填用同一份 11,018 token 的 prompt。短 prompt 一组 185 token、一组 515 token，只看首字节。18K 一组是 87 KB 中文材料，先冷跑一轮，再在同一会话里追问一轮，两轮分开记。空转 180 秒，前面带六条预热。</p>
<p dir="auto">改完配置要核对自检行。<code>/health</code> 在加载期就返回 ok，看不出开关有没有生效。MTP 要看到 <code>draft layer loaded</code>，流水线要看到 <code>two verifiers per stage</code>，env 类只能读进程环境：</p>
<pre><code class="language-bash">docker exec strata-build bash -c 'tr "\0" "\n" &lt; /proc/&lt;引擎pid&gt;/environ | grep CPU_SHARE'
</code></pre>
<h2>生产上还能动的地方</h2>
<h3>第 22 个 env 买的是首字节</h3>
<p dir="auto"><code>STRATA_PREFILL_CPU_SHARE=auto</code> 把预填阶段的一部分专家行分给 CPU 线程池，跟 GPU 并行推进。短 prompt 本来就在等 CPU 算专家，收益应该落在这里。</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>指标</th>
<th style="text-align:right">21 个 env</th>
<th style="text-align:right">22 个 env（现役）</th>
<th style="text-align:right">变化</th>
</tr>
</thead>
<tbody>
<tr>
<td>decode 中位（3×512）</td>
<td style="text-align:right">70.49</td>
<td style="text-align:right">67.83</td>
<td style="text-align:right">−3.8%</td>
</tr>
<tr>
<td>长预填 11,018 token</td>
<td style="text-align:right">710.3 / 746.6</td>
<td style="text-align:right">726.8 / 716.3</td>
<td style="text-align:right">持平</td>
</tr>
<tr>
<td>18K 冷预填</td>
<td style="text-align:right">774.2 tok/s</td>
<td style="text-align:right">736.6 tok/s</td>
<td style="text-align:right">−4.9%</td>
</tr>
<tr>
<td>短 prompt 185 token</td>
<td style="text-align:right">1.527 s</td>
<td style="text-align:right">1.326 s</td>
<td style="text-align:right">−13.2%</td>
</tr>
<tr>
<td>短 prompt 515 token</td>
<td style="text-align:right">2.226 s</td>
<td style="text-align:right">1.861 s</td>
<td style="text-align:right">−16.4%</td>
</tr>
</tbody>
</table>
<p dir="auto">decode 和长预填的差都在噪声带里，同一个臂连发三次就能从 62.32 摆到 71.38。稳的只有首字节，三个样本 1.516 / 1.326 / 1.314，摘掉这个 env 是 1.687 / 1.517 / 1.527。</p>
<p dir="auto">所以它留在生产里，理由是交互的时候人等的是第一个字。它不提吞吐，这一条不该写成提速。</p>
<p dir="auto">env 从 21 项变 22 项，备份在 <code>strata-iq3s-prod-pre-cpushare.json</code>，<code>restart-prod.sh</code> 一条命令上去，<code>WARM_DONE 17.8s</code>，冒烟正常。</p>
<h3>窗口定在 160K</h3>
<p dir="auto">模型原生 262K。192K 也能跑，同批对比摆在下面。</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>配置</th>
<th>max-context / kv-resident</th>
<th style="text-align:right">启动</th>
<th style="text-align:right">短上下文 decode</th>
<th style="text-align:right">长预填</th>
</tr>
</thead>
<tbody>
<tr>
<td>192K</td>
<td>196608 / 65536</td>
<td style="text-align:right">66.1 s</td>
<td style="text-align:right">59.3</td>
<td style="text-align:right">803.2 @19K、901.4 @53K</td>
</tr>
<tr>
<td>160K（定版）</td>
<td>163840 / 54624</td>
<td style="text-align:right">60.3 s</td>
<td style="text-align:right">60.6</td>
<td style="text-align:right">744.1 @11K</td>
</tr>
</tbody>
</table>
<p dir="auto">这一组是同一批测的，只读相对差，绝对值看开头那行。</p>
<p dir="auto">192K 那版还跑过一组长上下文。</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>prompt</th>
<th style="text-align:right">decode</th>
<th style="text-align:right">prefill</th>
</tr>
</thead>
<tbody>
<tr>
<td>29 token</td>
<td style="text-align:right">59.3</td>
<td style="text-align:right">—</td>
</tr>
<tr>
<td>19,026 token</td>
<td style="text-align:right">42.0</td>
<td style="text-align:right">803.2</td>
</tr>
<tr>
<td>53,125 token</td>
<td style="text-align:right">52.7</td>
<td style="text-align:right">901.4</td>
</tr>
</tbody>
</table>
<p dir="auto">上下文从 29 token 涨到 5.3 万，decode 掉 11%。这笔开销跟 KV 放不放得下无关，是 attention 本身随长度线性涨价。160K 比 192K 短上下文快 1.3 tok/s，启动快 6 秒，多出来的 32K 用不上，生产里最长的一次真实会话 145,985 token，占 160K 的 89%。</p>
<p dir="auto">那条会话的日志比合成测试更有说服力。</p>
<pre><code>prompt 145,985 tokens = 144,739 reused + 1,246 read in 4.7 s
1,982 generated in 36.8 s (53.9 tok/s)
decode expert cache hit rate: 97.4%
</code></pre>
<p dir="auto">接近满窗还有 54 tok/s。</p>
<h3>会话缓存，低的是前缀复用率</h3>
<p dir="auto">「命中率只有七成」这个印象一直挂在专家缓存上，挂错了。专家缓存常年在 0.96–0.98，低的是 <code>--conversation-cache-*</code> 管的前缀复用。</p>
<p dir="auto">根因很朴素。默认四个停放槽，<code>--conversation-cache-min-tokens</code> 默认 0，任何请求都能占一个。几条二十来 token 的请求就把槽占满，长会话挤不进去。</p>
<pre><code>--conversation-cache-mib 16384
--conversation-cache-slots 8
--conversation-cache-min-tokens 8192
--conversation-cache-park-gain 512
</code></pre>
<p dir="auto">生效后日志里能看到短请求被挡在门外。</p>
<pre><code>strata serve: conversation cache: skip parking (43 tokens, below the 8192 minimum; parked=0)
</code></pre>
<p dir="auto">长会话的复用率跟着上到 99.2%。</p>
<p dir="auto">代价在冷启动。缓存槽刚改完、引擎还在爬坡的时候，8,592 token 的冷预填跑过 373 秒；稳定之后 18K 冷预填 23.6 秒。重启后必须有预热，否则第一个真实请求可能卡几分钟。<code>warm.py</code> 已经内置进 <code>restart-prod.sh</code>，一次 <code>WARM_DONE 17.7s</code>，首请求 TTFT 从 11.9 秒降到 0.59 秒。</p>
<h2>十六个开关臂全落在噪声里</h2>
<p dir="auto">后面又扫了十六个开关，分三批，同一口径。扫描结果折算成相对基线的差。</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>批次</th>
<th>臂</th>
<th style="text-align:right">相对基线（tok/s）</th>
</tr>
</thead>
<tbody>
<tr>
<td>草稿与管道</td>
<td><code>--spec 4</code></td>
<td style="text-align:right">−4.1</td>
</tr>
<tr>
<td></td>
<td><code>--spec 5</code></td>
<td style="text-align:right">−13.8</td>
</tr>
<tr>
<td></td>
<td><code>--spec-min-p 0.5</code></td>
<td style="text-align:right">−0.8</td>
</tr>
<tr>
<td></td>
<td><code>--prefill-pipe 300</code></td>
<td style="text-align:right">−2.0</td>
</tr>
<tr>
<td></td>
<td><code>--prefill-pipe 450</code></td>
<td style="text-align:right">−2.3</td>
</tr>
<tr>
<td>GDN 五臂</td>
<td><code>GDN_PIPELINE</code> / <code>GDN_SPLIT</code> / <code>GDN_CHUNKED</code> / <code>GDN_COMMIT_SPLIT</code> / <code>GDN_PP=2</code></td>
<td style="text-align:right">−1.3 / −0.8 / −3.4 / −1.5 / +0.3</td>
</tr>
<tr>
<td>KV 与 MTP 五臂</td>
<td><code>KV_PREFETCH</code> / <code>KV_GROW</code> / <code>MTP_TOP2</code> / <code>MTP_FULL_HEAD</code> / <code>LOOKAHEAD</code></td>
<td style="text-align:right">−2.1 / −3.4 / −3.4 / −2.3 / −1.7</td>
</tr>
</tbody>
</table>
<p dir="auto">掉出噪声带的只有 <code>--spec 4</code> 和 <code>--spec 5</code>。<code>--spec 3</code> 是唯一最优点，而且非单调，4 慢，5 更慢，6 也不快，不是越大越好。</p>
<p dir="auto">结论很干脆：靠调参数榨不出东西了。想再快只剩两条路，改内核或者换模型。</p>
<h2>外部路线都试过一轮</h2>
<h3>replicas 单流掉两成</h3>
<p dir="auto">同平台（E5 + X99 + 128G DDR3 + 双卡）用 replicas 拓扑的报告里，单流明显更高，就想验证一卡一副本能不能绕开跨卡握手。</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>拓扑</th>
<th style="text-align:right">单流 decode</th>
<th style="text-align:right">双流聚合</th>
<th style="text-align:right">专家命中</th>
<th style="text-align:right">启动</th>
</tr>
</thead>
<tbody>
<tr>
<td>层切分（现役）</td>
<td style="text-align:right">基准</td>
<td style="text-align:right">57.4–61.7</td>
<td style="text-align:right">0.952</td>
<td style="text-align:right">87 s</td>
</tr>
<tr>
<td>replicas（一卡一副本）</td>
<td style="text-align:right">−22%</td>
<td style="text-align:right">66.1</td>
<td style="text-align:right">0.682</td>
<td style="text-align:right">120 s</td>
</tr>
</tbody>
</table>
<p dir="auto">replicas 输在显存。每个副本只看得见自己那张 16GB 卡，专家槽位从约 12,200 掉到 5,500 上下，命中率 0.952 → 0.682，缺口全落到 DDR3 上。同平台那台能赢，推测是同样的机制反过来，副本看得见的显存够放槽位，命中率不掉。</p>
<p dir="auto">判定是保持层切分。我们的负载是单 agent 长会话顺序推进，单流速度决定一切；replicas 只在多人同用、每人能接受 40 tok/s 的时候有意义。</p>
<h3>rocBLAS 解表派发不通</h3>
<p dir="auto"><code>xxDoman/strata-gfx906</code> 那条线里唯一带速度的是 rocBLAS solution table。库版本对不上（我们是 5.5.0，它的表是 5.2.0），只能现场调一份。</p>
<ul>
<li>42 个 shape，32 个有更优解，最大 <code>T=8192 N=1 K=2560</code> 增益 6.36 倍；</li>
<li>表落在 <code>/src/models/gfx906-rocblas.txt</code>。</li>
</ul>
<p dir="auto">reader 一编进引擎，生产直接不可用。</p>
<pre><code>reading the prompt: 13 of 20 tokens, 143 s
no progress for 60 s ... stopping the engine
</code></pre>
<p dir="auto">带与不带 <code>STRATA_ROCBLAS_TUNING</code> 结果一样，表的问题是次要的。走不通的是 rocBLAS 在这个 shape 上的派发，缺 Tensile 内核或者首次 JIT 极慢，没证实。已回滚，重编后二进制字节数与补丁前完全一致。</p>
<p dir="auto">单测证明「这档算得快」和「引擎能用这档」是两件事。</p>
<h3>Avalon 能加载算不对</h3>
<p dir="auto"><code>fraiadoc/Avalon</code> 是 llama.cpp 的 fork。移植时改了逻辑 warp32、MMQ GCN 的 <code>nthreads/2</code>、host <code>warp_size</code>，编得过；官方 89.72 GiB 的包也能加载，25 个专家 pool 全部 register=1。</p>
<p dir="auto">坏在 MMQ 批量路径在 gfx906 上 <code>unspecified launch failure</code>：<code>ub≥16</code> 必崩，<code>ub≤4</code> 才正常，加 <code>GGML_CUDA_NO_MMQ</code> 短路也换不来可用吞吐。90 GB 模型已删。</p>
<p dir="auto">这条留下的教训比速度重要。随机 token 的 bench 只证明跑得动，证明不了算得对。</p>
<h3>其余几条判负</h3>
<ul>
<li><code>--kv k8v4</code>：−7%</li>
<li><code>--ple-io direct</code> 和 <code>mmap</code>：与 <code>ram</code> 无差别，PLE 26.8 GiB 已经整表锁内存，每 token 只取 90 字节每行</li>
<li>中文 MTP 草稿词表：默认 106,299 token 的集合里只有 27 个汉字（共 55,328 个），但中文 decode 61.0 tok/s、英文 63.9 tok/s，只差 4%，prompt-lookup 草稿仍能命中；<code>--add cjk</code> 是 +3–5% 的小杠杆</li>
<li>vLLM 的 gfx906 两个实现（MobyDick #53 / #34）：收益场景是 page-cache 随机 gather，我们的 PLE 已经整表锁内存，没空间</li>
<li>Basalt：只支持 NVIDIA Blackwell，源码里没有 HIP 后端</li>
</ul>
<h2>转去 Qwen3.6-35B-A3B</h2>
<p dir="auto">参数到顶、窗口定死、内核路径能试的都试过之后，剩下的变量只有模型本身。Qwen3.6-35B-A3B 是官方仓库里的一等模型，22.9 GB 的 UD-Q4_K_XL 塞得进显存，总参 35B、激活 3B，理论上比 125B 总参 / 6B 激活的 Flash-Next 轻。</p>
<h3>它按单卡写死</h3>
<p dir="auto">只读调研的证据链很硬：<code>src/qwen35/</code> 里 <code>ggml_</code> 零引用，没有 <code>cudaSetDevice</code> 和 <code>cudaGetDeviceCount</code>，所有权重裸 <code>cudaMalloc</code>，<code>--gpu</code> 只由父进程的 <code>HIP_VISIBLE_DEVICES</code> 生效。而且整个目录被 <code>CMakeLists.txt:860</code> 的 <code>if(NOT STRATA_HIP_GFX906)</code> 排除，理由写在同处注释里：它调用 wave64 兼容层没映射的 cuBLAS 入口，kernel 也假设 32-lane warp。</p>
<p dir="auto">所以这条路得做移植，改配置没有用。按五个阶段推进：能编、单卡跑通、层切分、和 serve 共存、接 MTP。</p>
<h3>让它能编译</h3>
<p dir="auto">最小改动两处。</p>
<ol>
<li><code>include/strata/platform/hip_compat/cublas_v2.h</code> 补 <code>cublasSgemm</code> 和 <code>cublasGemmStridedBatchedEx</code> 两个映射（指向 hipblas）；</li>
<li><code>CMakeLists.txt</code> 加 <code>option(STRATA_BUILD_QWEN35_GFX906 ... OFF)</code>，条件改成 <code>if(NOT STRATA_HIP_GFX906 OR STRATA_BUILD_QWEN35_GFX906)</code>。</li>
</ol>
<p dir="auto">默认 OFF 是关键。实验用独立的 <code>build-906-q36</code>，生产构建完全不受影响。结果 167/167 编译通过，<code>--families</code> 从 <code>qwen4exp</code> 变成 <code>qwen4exp qwen35moe</code>。</p>
<h3>单卡上撞三道门</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>门</th>
<th>报错</th>
<th>结局</th>
</tr>
</thead>
<tbody>
<tr>
<td>专家类型白名单</td>
<td><code>blk.0.experts are IQ2_S/IQ3_S, which the native expert kernels do not take</code></td>
<td>UD-IQ3_XXS 是逐层混合量化，补表补不完，换档</td>
</tr>
<tr>
<td>32-lane warp 假设</td>
<td><code>MUL_MAT failed</code> 加 <code>unspecified launch failure</code></td>
<td>逻辑 warp32 改造，四处</td>
</tr>
<tr>
<td>MMQ 批量路径</td>
<td><code>ub=16/64/256</code> 必崩，<code>ub≤8</code> 正常</td>
<td>GCN 配置表按 64 lane 波设计，改 <code>nthreads/2</code></td>
</tr>
</tbody>
</table>
<p dir="auto">换成 UD-Q4_K_XL（22,853,663,008 B）后加载成功，25 个专家 pool 全部注册，<code>-ub 1</code> 下中文跑通。</p>
<h3>层切分暴露四个跨设备 bug</h3>
<p dir="auto">单卡跑通只是及格线。两卡实现选了两个 <code>Engine</code> 对象各自 <code>init()</code>，没有去手抄七十多个指针的 scratch 快照。这一层暴露的四个 bug，单卡上永远看不到。</p>
<ol>
<li><code>iq_embed_rows: invalid resource handle</code>，所有入口前置 <code>use_dev()</code>（<code>cudaSetDevice</code>）；</li>
<li><code>k_moe_out</code> 在 GPU0 上 Memory Fault，边界层的 <code>wn</code> 指向了 dev1 的 <code>next-&gt;attn_norm</code>，改成 load 末尾复制到 dev0；</li>
<li>残差流没跨设备，<code>k_moe_out</code> 同时写 <code>h</code> 和残差 <code>x</code>，原实现只搬了 <code>h</code>，从边界层起全错；</li>
<li><code>xq_ready</code> 跨 forward 泄漏，边界层让 <code>mkq</code> 保持为真，标志留在 A 上，下一个 token 复用了上一个 token 的 q8 镜像。</li>
</ol>
<p dir="auto">修完速度：pp 约 345 → 935（2.7 倍），tg 约 64 → 77（+20%）。</p>
<p dir="auto">这一层比速度更值钱的收获，是那个不变量闸门。</p>
<pre><code>同一条 prompt、--n 1，只改 --layer-split
  split 20 → gen: 2972   ← 三个切点给出三个答案
  split 22 → gen: 271
  split 23 → gen: 248044 (EOS)
  单卡     → gen: 1
</code></pre>
<p dir="auto">修好后四者全是 token <code>1</code>；<code>--n 16</code> 四份逐 token 相同；<code>--dump-full-logits</code> 显示 split 20、22 与 split 23 的 <code>max|Δlogit| = 0</code>。</p>
<p dir="auto">切分类改造必须配这个测试。没有它，速度数字再漂亮也是错的。</p>
<h3>和 serve 共存，卡住四个 token</h3>
<p dir="auto">删掉 <code>q36_engine.cu:3980</code> 那个 <code>if (layer_split &gt; 0 &amp;&amp; serve_mode) return 2;</code>，补上 <code>select_all</code>、<code>copy_session_all</code>、<code>reserve_bnd</code>，8082 上中文正确，API 与 CLI 逐 token 相同（25/25）。</p>
<p dir="auto">会话前缀复用恒为 0。根因在模板。生成提示末尾会追加一个空思考块 <code>&lt;think&gt;\n\n&lt;/think&gt;\n\n</code>，四个 token，而历史轮渲染默认不回放 think 块，第二轮的 prompt 与第一轮的前缀差这四个 token。<code>match_len()</code> 要求整段 live 是新 prompt 的前缀，引擎又没有 KV 回退，于是恒 0。</p>
<p dir="auto">把 <code>chat_template.jinja</code> 里那个 <code>preserve_thinking</code> 条件改成 <code>{%- if true %}</code>，历史 assistant 轮永远回放 think 块，立刻变成 <code>REUSE 42 of 62</code>。</p>
<p dir="auto">顺带一个运维坑：tokenizer 目录是容器 root 建的，宿主机改不动，只能 <code>scp</code> 脚本进 <code>/src/bench/</code> 再用 <code>docker exec</code> 跑。</p>
<h3>接 MTP 改了七处</h3>
<p dir="auto">矛盾在权重的位置上。MTP 权重在 head 引擎（dev1），验证窗口必须从拥有 layer 0 的引擎（dev0）进入。</p>
<ol>
<li><code>commit()</code> 循环加 <code>if (!owns_layer(l)) continue;</code>，每卡只推进自己那半层的 GDN 状态；</li>
<li><code>spec_step()</code> 的验证窗口改由 <code>peer ? *peer : *this</code> 跑，之后双侧 commit 加双侧 pos 同步，只让一边 commit 会让两卡状态分叉；</li>
<li>新增 <code>spec()</code> 委托到 <code>head_e</code>，覆盖 warmup、serve、CLI 三个调用点；</li>
<li>新增 <code>mtp_prompt()</code>，prompt 的 MTP K/V 预填写到 head 引擎，拷贝全用它的 stream；</li>
<li><code>main()</code> 删掉 split 下的 <code>mtp_d = 0</code>；</li>
<li><code>spec_step</code> 入口补 <code>use_dev()</code>；</li>
<li><code>Model::embd1</code> 给 dev1 一份嵌入副本，否则 MTP 种子行在 dev1 读 dev0 的嵌入会越界（rc=141），代价 0.50 GiB。</li>
</ol>
<p dir="auto">验证跑了 split 20 / 22 / 23 乘 mtp 0 / 3 四种配置，两套 prompt 各 16 token 全部 IDENTICAL。</p>
<h2>两个模型的成绩</h2>
<p dir="auto">同一份材料、同一条会话、同一台机器。材料被两个 tokenizer 数成 17,408 和 18,376 个 token，不是两份材料。</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>指标</th>
<th style="text-align:right">q36（split 22 + mtp 3）</th>
<th style="text-align:right">现役 Flash-Next</th>
<th>谁赢</th>
</tr>
</thead>
<tbody>
<tr>
<td>冷预填 18K</td>
<td style="text-align:right">19.1 s（962 tok/s）</td>
<td style="text-align:right">23.6 s（736.6 tok/s）</td>
<td>q36，1.31 倍</td>
</tr>
<tr>
<td>复用读入</td>
<td style="text-align:right">0.125 s</td>
<td style="text-align:right">0.381 s</td>
<td>q36</td>
</tr>
<tr>
<td>18K 冷 decode（28 token）</td>
<td style="text-align:right">50.0（drafts 19/24）</td>
<td style="text-align:right">53.9</td>
<td>现役</td>
</tr>
<tr>
<td>18K 复用后 decode（128 token）</td>
<td style="text-align:right">38.2（drafts 80/144）</td>
<td style="text-align:right">58.3</td>
<td>现役，1.53 倍</td>
</tr>
<tr>
<td>上下文窗口</td>
<td style="text-align:right">32,768</td>
<td style="text-align:right">163,840</td>
<td>现役</td>
</tr>
</tbody>
</table>
<p dir="auto">那 28 个 token 的样本太小，又是在冷启动的爬坡段里取的，波动比差距还大，这一格别太当真。</p>
<p dir="auto">MTP 在 q36 身上是双刃剑。</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>场景</th>
<th style="text-align:right">无 MTP</th>
<th style="text-align:right"><code>--mtp 3</code></th>
<th style="text-align:right">变化</th>
</tr>
</thead>
<tbody>
<tr>
<td>1,242 token 短上下文</td>
<td style="text-align:right">77.9</td>
<td style="text-align:right">98.8</td>
<td style="text-align:right">+26.8%</td>
</tr>
<tr>
<td>18,376 token 冷预填</td>
<td style="text-align:right">960.9</td>
<td style="text-align:right">919.9</td>
<td style="text-align:right">−4.3%</td>
</tr>
<tr>
<td>18K 冷 decode</td>
<td style="text-align:right">44.2</td>
<td style="text-align:right">50.0</td>
<td style="text-align:right">+13%</td>
</tr>
<tr>
<td>18K 复用后 decode</td>
<td style="text-align:right">43.7</td>
<td style="text-align:right">38.2</td>
<td style="text-align:right">−12.6%</td>
</tr>
</tbody>
</table>
<p dir="auto"><code>--mtp 5</code> 掉到 37.0，<code>--mtp 6</code> 掉到 33.9，草稿越激进越糟。</p>
<p dir="auto">机制说得清。q36 的 decode attention 按 query 行展开，窗口越大越亏；投机解码每轮要验证多个 token，等于在长上下文里把这份成本乘若干倍。现役 Flash-Next 的 QSA 层本来就是为长窗口设计的，48 层里只有 12 层需要 KV，MTP 验证才吃得下。</p>
<h2>两个模型最好成绩并排</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>维度</th>
<th>Qwen3.8-Flash-Next（现役）</th>
<th>Qwen3.6-35B-A3B（q36）</th>
</tr>
</thead>
<tbody>
<tr>
<td>量化与体积</td>
<td>IQ3_S，两分片 54.8 + 28.8 GB，PLE 嵌入表走内存 mmap</td>
<td>UD-Q4_K_XL，22.85 GB</td>
</tr>
<tr>
<td>架构</td>
<td>125B 总参 / 6B 激活 MoE</td>
<td>35B 总参 / 3B 激活 MoE</td>
</tr>
<tr>
<td>短上下文 decode</td>
<td>70.27 峰值、67.83 中位</td>
<td>98.8（1.2K 上下文，mtp 3）</td>
</tr>
<tr>
<td>中长上下文 decode</td>
<td>58.3（18K，复用后）</td>
<td>38.2（18K，复用后）</td>
</tr>
<tr>
<td>冷预填</td>
<td>736.6 tok/s（18K）</td>
<td>962 tok/s（18K）</td>
</tr>
<tr>
<td>长 prefill（11K）</td>
<td>716–727 tok/s</td>
<td>962 tok/s（18K 口径）</td>
</tr>
<tr>
<td>上下文窗口</td>
<td>163,840</td>
<td>32,768</td>
</tr>
<tr>
<td>显存余量</td>
<td>两卡各约 1 GiB</td>
<td>dev0 1.16、dev1 1.51 GiB</td>
</tr>
<tr>
<td>代码状态</td>
<td>上游分支加一份配置，没改业务代码</td>
<td>改 5 个文件，其中 <code>q36_engine.cu</code> 803 行 patch，移植两天</td>
</tr>
<tr>
<td>生产运行</td>
<td>连跑 30 天</td>
<td>从未上生产</td>
</tr>
</tbody>
</table>
<p dir="auto">q36 领先的只有短上下文那一格，冷预填领先 31%；长上下文和反复追问都归现役，窗口大五倍。</p>
<h2>没换的原因</h2>
<p dir="auto">我们的负载形状长在 Flash-Next 的优势区。</p>
<ol>
<li>主流程是同一份材料反复追问，是讲一讲、改一改、再问细节，同一份一万到两万 token 的材料在同一条会话里来回推进。这条路吃的是复用后 decode，58.3 对 38.2，现役快 53%。q36 赢的那条是冷预填快 4.5 秒，每份材料只发生一次。</li>
<li>窗口是硬约束。32K 装不下一讲完整材料加多轮对话，我们真实会话已经到 14.6 万 token。q36 的可行带在 40 层里是 <code>split 17..23</code>，往上要么放不下要么爆显存。</li>
<li>稳定性差着数量级。现役是上游分支加一份配置，连跑 3天；q36 是改 5 个文件移植出来的，上游一次更新就可能要重来。</li>
<li>它的收益场景现役能覆盖。超长材料只问一轮，现役多付 4.5 秒预填就能做，窗口还是五倍。为这 4.5 秒去背一个自己维护的移植分支，不划算。</li>
<li>想让它真赢，得改 kernel。唯一能把 q36 的 18K decode 推到现役之上的路，是改 <code>k_attn_part</code> 和 <code>k_attn_prep</code>，让窗口内 T 行共享一次 KV 读取。那是一两天的 kernel 工作，且不保证成功。</li>
</ol>
<h2>教训</h2>
<h3>切分类改造要配切点不变性测试</h3>
<p dir="auto">同一条 prompt、<code>--n 1</code>、只改切分点，比 argmax。q36 靠它抓出四个 bug。Avalon 那次是反例，<code>ub</code> 调小跑得动、一放大就崩，随机 token 的 bench 把「算不对」伪装成了「调参问题」。</p>
<h3>基线必须同批</h3>
<p dir="auto">同一台机器、同一个二进制、同一份 args，隔一天测出来的数能差 16%。所以 A/B 要在同一批里跑，跨天、跨口径的数字不能直接减，否则会得出「越调越慢」这种结论。</p>
<h3>默认值是给能跑起来准备的</h3>
<p dir="auto"><code>--adapt-every 0</code> 关掉自适应缓存层，21 个 env 默认全关，<code>--conversation-cache-min-tokens</code> 默认 0 让短请求占满长会话的槽。这几处默认值只管能跑起来，不管跑得好。</p>
<h3>别人的增益不能照搬</h3>
<p dir="auto">rocBLAS 那张表在我们机器上确实成立，32/42 个 shape 有更优解，最大 6.36 倍，但派发走不通就是走不通。先核对是不是同一条代码路径、同一个瓶颈，再决定复刻。</p>
<h2>还没做的</h2>
<ol>
<li>质量评测没做，速度已经够了。</li>
<li>长跑稳定性。int6 分支版连跑满 24 小时不掉速才算数，目前断续跑了几天，没见异常。</li>
<li>并发没测，官方和社区都说这条路径并发不行。</li>
<li>识图没启用。模型本身是多模态，repo 另发 907 MB 的 mmproj，引擎 0.1.52 也有 <code>--vision</code>，但官方把 gfx906 的图片功能列为未做，<code>/health</code> 仍是 <code>images: false</code>。没启用的能力不写进成绩。</li>
<li>层切分只有 27 和 21 两个值，没穷举。</li>
</ol>
<h2>收尾</h2>
<p dir="auto">第一轮把机器装起来，54 tok/s。第二轮发现开关默认是关的，65。第三轮把剩下的试完，参数到顶、窗口定死、三条外部路线全部判负，于是换了个模型，跑通、跑对、跑快，然后决定不换。</p>
<p dir="auto">最后那个决定不靠速度。q36 的 98.8 是我这台机器上出现过的最快数字，它只在 32K 窗口里成立。这台机器真正的瓶颈在窗口乘复用，不在算力。</p>
<p dir="auto">项目地址：<a href="https://github.com/Niko1221/Strata" rel="nofollow ugc">Niko1221/Strata</a><br />
分支：<a href="https://github.com/Niko1221/Strata/pull/5361" rel="nofollow ugc">rpcribari: int6</a><br />
q36 实验归档：<code>strata-research/q36-experiment/</code>（803 行移植 patch 加全部日志）</p>
]]></description><link>https://lcz.me/post/32150</link><guid isPermaLink="true">https://lcz.me/post/32150</guid><dc:creator><![CDATA[Sun Lyu]]></dc:creator><pubDate>Mon, 09 Nov 2026 08:41:04 GMT</pubDate></item><item><title><![CDATA[Reply to 【纯闲着】2700 块的洋垃圾跑 QFN：MI50 16G×2 + 128G DDR3，从装系统到 54 tok/s，这可能是目前价格最低的洋垃圾方案。 on Mon, 09 Nov 2026 07:19:30 GMT]]></title><description><![CDATA[<p dir="auto">最早32G版本的價格可是跟標題現在的16G差不多，前一陣子突然快跟V100 32G看齊了，有Strata 和 LLM搞定後台，真的變成有VRAM便是娘了</p>
]]></description><link>https://lcz.me/post/32117</link><guid isPermaLink="true">https://lcz.me/post/32117</guid><dc:creator><![CDATA[Tzung-Ru Tsai]]></dc:creator><pubDate>Mon, 09 Nov 2026 07:19:30 GMT</pubDate></item><item><title><![CDATA[Reply to 【纯闲着】2700 块的洋垃圾跑 QFN：MI50 16G×2 + 128G DDR3，从装系统到 54 tok/s，这可能是目前价格最低的洋垃圾方案。 on Mon, 09 Nov 2026 07:05:42 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/kiwi" aria-label="Profile: kiwi">@<bdi>kiwi</bdi></a> 哈哈，我现在觉得这配置这价格，真香，把Ai本地的价格打下来，哈哈哈哈</p>
]]></description><link>https://lcz.me/post/32116</link><guid isPermaLink="true">https://lcz.me/post/32116</guid><dc:creator><![CDATA[Sun Lyu]]></dc:creator><pubDate>Mon, 09 Nov 2026 07:05:42 GMT</pubDate></item><item><title><![CDATA[Reply to 【纯闲着】2700 块的洋垃圾跑 QFN：MI50 16G×2 + 128G DDR3，从装系统到 54 tok/s，这可能是目前价格最低的洋垃圾方案。 on Mon, 09 Nov 2026 00:14:02 GMT]]></title><description><![CDATA[<p dir="auto"><img src="https://upload.lcz.me/uploads/5c9a0a0a-d91d-4cae-9920-3d0720d66fae.png" alt="截圖 2026-11-09 上午8.11.14.png" class="img-markdown  img-fluid" /></p>
<p dir="auto">版大的配置來拿部署夠好用了！</p>
<p dir="auto">目前在測試長一點上下文跟併發。</p>
]]></description><link>https://lcz.me/post/32002</link><guid isPermaLink="true">https://lcz.me/post/32002</guid><dc:creator><![CDATA[kiwi]]></dc:creator><pubDate>Mon, 09 Nov 2026 00:14:02 GMT</pubDate></item><item><title><![CDATA[Reply to 【纯闲着】2700 块的洋垃圾跑 QFN：MI50 16G×2 + 128G DDR3，从装系统到 54 tok/s，这可能是目前价格最低的洋垃圾方案。 on Sun, 08 Nov 2026 04:04:12 GMT]]></title><description><![CDATA[<p dir="auto">我觉得把一些东西放在内存当查表，这个思路是最核心的</p>
]]></description><link>https://lcz.me/post/31852</link><guid isPermaLink="true">https://lcz.me/post/31852</guid><dc:creator><![CDATA[jerry deng]]></dc:creator><pubDate>Sun, 08 Nov 2026 04:04:12 GMT</pubDate></item><item><title><![CDATA[Reply to 【纯闲着】2700 块的洋垃圾跑 QFN：MI50 16G×2 + 128G DDR3，从装系统到 54 tok/s，这可能是目前价格最低的洋垃圾方案。 on Sun, 08 Nov 2026 00:54:04 GMT]]></title><description><![CDATA[<p dir="auto"><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/1f525.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--fire" style="height:1.4em;width:auto;vertical-align:middle" title="🔥" alt="🔥" /> 本帖参与讨论人数已达 <strong>10+</strong>，入选<strong>热议</strong>，作者 <strong>+3 积分</strong>奖励！</p>
<blockquote>
<p dir="auto">奖励凭证：热议 +3 分 · 编号 h2896-4934-1</p>
</blockquote>
]]></description><link>https://lcz.me/post/31832</link><guid isPermaLink="true">https://lcz.me/post/31832</guid><dc:creator><![CDATA[Xiaote]]></dc:creator><pubDate>Sun, 08 Nov 2026 00:54:04 GMT</pubDate></item><item><title><![CDATA[Reply to 【纯闲着】2700 块的洋垃圾跑 QFN：MI50 16G×2 + 128G DDR3，从装系统到 54 tok/s，这可能是目前价格最低的洋垃圾方案。 on Sun, 08 Nov 2026 00:52:06 GMT]]></title><description><![CDATA[<p dir="auto">我只能说太牛了，这套调优其实就是“把每一块硬件的脾气摸透，让它们各司其职”：</p>
<ol>
<li><strong>贵的显存跑计算，便宜的内存当仓库</strong>：把需要高频计算的核心零件死死锁在极速的显存里，把体积庞大但只需要查询的辅助数据塞进便宜的内存里，用最少的钱买到了最大的容量。</li>
<li><strong>每次只动一小部分，不搞全员大集合</strong>：利用 MoE 架构“激活小部分”的特点，每次生成只调用一小撮专家，把原本几十个人才能干的活压缩到几个人干，直接避开了内存搬运速度慢的死穴。</li>
<li><strong>干掉假把戏，开关全拉满</strong>：把软件里那些表面开着、实际在偷懒的机制通通揪出来，同时把隐藏在底层的加速开关全部手动打开，不让硬件浪费哪怕一微秒。</li>
<li><strong>耐心等机器“热身”好</strong>：就像跑马拉松前要热身一样，刚开机数据还没理顺，等它空转跑个几分钟、把缓存全部命中之后，性能就能稳稳冲到最高点。</li>
</ol>
]]></description><link>https://lcz.me/post/31831</link><guid isPermaLink="true">https://lcz.me/post/31831</guid><dc:creator><![CDATA[jerry deng]]></dc:creator><pubDate>Sun, 08 Nov 2026 00:52:06 GMT</pubDate></item><item><title><![CDATA[Reply to 【纯闲着】2700 块的洋垃圾跑 QFN：MI50 16G×2 + 128G DDR3，从装系统到 54 tok/s，这可能是目前价格最低的洋垃圾方案。 on Sat, 07 Nov 2026 15:55:33 GMT]]></title><description><![CDATA[<p dir="auto">可持续更新优化，为后来者趟路。</p>
]]></description><link>https://lcz.me/post/31794</link><guid isPermaLink="true">https://lcz.me/post/31794</guid><dc:creator><![CDATA[terry]]></dc:creator><pubDate>Sat, 07 Nov 2026 15:55:33 GMT</pubDate></item><item><title><![CDATA[Reply to 【纯闲着】2700 块的洋垃圾跑 QFN：MI50 16G×2 + 128G DDR3，从装系统到 54 tok/s，这可能是目前价格最低的洋垃圾方案。 on Sat, 07 Nov 2026 12:06:41 GMT]]></title><description><![CDATA[<h1>调优再进一步</h1>
<p dir="auto">上一篇写到 54.0 tok/s 就收尾了。</p>
<p dir="auto">吃晚饭的时候，我又去挖了挖潜力。</p>
<p dir="auto">先把结论放在前面：</p>
<p dir="auto"><strong>同一台机器、同一份模型文件、同样的量化档（IQ3_S），decode 从 54.0 提到 65.1 tok/s，峰值可以突破100tok/s，prefill 从 571 提到 752 tok/s，峰值850 tok/s。</strong></p>
<p dir="auto"><strong>均值65.1 是官方 2×MI50 参考机（49.2）的 1.32 倍，是我自己首跑（28.3）的 2.3 倍。</strong></p>
<p dir="auto">代价只有一个：引擎版本从 0.1.55 退到 0.1.52+PR。</p>
<p dir="auto"><img src="https://upload.lcz.me/uploads/e945aa13-156f-41f6-8f39-9243db9378ad.jpg" alt="微信图片_20261107193643_64_2.jpg" class="img-markdown  img-fluid" /></p>
<p dir="auto"><img src="https://upload.lcz.me/uploads/d2d7a592-ae51-45d1-b7ec-222ee0ed80d5.png" alt="微信图片_20261107193228_61_2.png" class="img-markdown  img-fluid" /></p>
<p dir="auto"><img src="https://upload.lcz.me/uploads/2500b0fd-3082-46e1-a34e-4a200306971d.png" alt="微信图片_20261107193336_63_2.png" class="img-markdown  img-fluid" /></p>
<hr />
<h2>一、线索：一个没人评审的 PR</h2>
<p dir="auto">上一篇之后我看到：</p>
<blockquote>
<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/rori" aria-label="Profile: rori">@<bdi>rori</bdi></a> <a href="/post/31697">说</a>:</p>
<p dir="auto">這卡有潛力, 已經有大神做strata優化:<br />
<a href="https://github.com/Niko1221/Strata/pull/5361" rel="nofollow ugc">https://github.com/Niko1221/Strata/pull/5361</a></p>
</blockquote>
<p dir="auto">作者是 4×MI50 32GB 的机器，报出来的数字是 <strong>decode 125 tok/s、prefill 8K 1250 / 32K 1766</strong>——差不多是我 54 的两倍多。我第一反应是"32G 版显存大，全驻，不奇怪"，但里面有些数字对不上：我判负过的 <code>--prefill-pipe</code>，在他那儿是 +73% @8K、+109% @32K。</p>
<p dir="auto">这个 PR 的状态很说明问题：22 个 commit、30 个文件、+5046/−147，<strong>整个 PR 只有两条评论，都是 bot 在提醒"标题要加 [Engine] 前缀"</strong>，没有一行人工评审。作者自己在描述里写着"基于 0.2.7，main 已经前进约 4k commits"。</p>
<p dir="auto">也就是说：这东西质量未必差，但<strong>没人验过，也不会自动合进来</strong>。想用只能自己来。</p>
<hr />
<h2>二、第一次找错了地方</h2>
<p dir="auto">我让模型去读这个 PR 的提交列表，它挑了 <code>e4f4027</code> 说："这条值得参考，IQ3 的 gate/up 走 repacked GEMM，bitwise 等价，GEMM 从 0.85ms 降到 0.63ms。"</p>
<p dir="auto">听起来很对口——我用的正是 IQ3_S。于是我把这个分支完整编译了一遍（0.1.52，165/165 目标通过），然后做了个隔离实验：<code>STRATA_PF_RP_IQ3=0</code> 把这个改动关掉，看差多少。</p>
<p dir="auto">结果：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>臂</th>
<th>配置</th>
<th style="text-align:right">decode</th>
<th style="text-align:right">prefill</th>
</tr>
</thead>
<tbody>
<tr>
<td>分支默认</td>
<td>repack 开着</td>
<td style="text-align:right">50.1</td>
<td style="text-align:right">690</td>
</tr>
<tr>
<td>同一分支</td>
<td><code>STRATA_PF_RP_IQ3=0</code> <strong>关掉它</strong></td>
<td style="text-align:right">53.4</td>
<td style="text-align:right"><strong>721</strong></td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>关掉反而更快。</strong> 也就是说这条提交在我这台机器上测不出收益，方向甚至是反的（都在噪声里）。</p>
<p dir="auto">但它不是白读的——<strong>它把我引到了 PR 自带的 <code>docs/AMD_MI50.md</code></strong>，那里面有一句被我（和模型）一路略过去的话：</p>
<pre><code>Each new switch is off by default.
When a switch is off, that kernel runs exactly as before.
</code></pre>
<hr />
<h2>三、转折：收益在"默认关着"的那一整块里</h2>
<p dir="auto"><code>docs/AMD_MI50.md</code> 的推荐配置里，<code>env</code> 有 <strong>21 个开关</strong>。默认全关，全关时"kernel 和以前完全一样"。</p>
<p dir="auto">这意味着：<strong>我前面用分支默认态跑出来的 50.1，等于只免费蹭到了 prefill 栈（默认开），decode 一个开关都没吃到。</strong></p>
<p dir="auto">把 21 个全打开之后：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>臂（同一协议，空转 90s）</th>
<th>引擎</th>
<th style="text-align:right">decode 中位</th>
<th style="text-align:right">prefill</th>
<th style="text-align:right">冷启动</th>
</tr>
</thead>
<tbody>
<tr>
<td>上一篇的生产版</td>
<td>0.1.55（0.2.9）</td>
<td style="text-align:right">47.0</td>
<td style="text-align:right">521</td>
<td style="text-align:right">75s</td>
</tr>
<tr>
<td>分支默认态</td>
<td>0.1.52+PR</td>
<td style="text-align:right">50.1</td>
<td style="text-align:right">690</td>
<td style="text-align:right">84s</td>
</tr>
<tr>
<td>分支 + 关掉那条提交</td>
<td>0.1.52+PR</td>
<td style="text-align:right">53.4</td>
<td style="text-align:right">721</td>
<td style="text-align:right">54s</td>
</tr>
<tr>
<td><strong>分支 + 21 个开关全开</strong></td>
<td><strong>0.1.52+PR</strong></td>
<td style="text-align:right"><strong>61.3</strong></td>
<td style="text-align:right"><strong>701</strong></td>
<td style="text-align:right">57s</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>decode +30%、prefill +34%。</strong></p>
<p dir="auto">顺带说清楚一件事：为什么同一台机器上一篇测 54.0，这一轮基线只有 47.0。因为<strong>口径变了</strong>——上一篇收尾时用的是官方口径（1.6K prompt / 128 token / temp 0），这一轮统一成 3×512 token + 14K token 长 prefill，两者不可直接比。下面所有数字都在这一个口径里。</p>
<hr />
<h2>四、不等作者，自己把分支拉下来编</h2>
<p dir="auto">作者只在 PR 分支上，fork 也不会被合并。但这件事<strong>根本不需要作者配合</strong>：</p>
<pre><code class="language-bash">curl -L --proxy http://192.168.2.2:7890 \
  -o int6.tar.gz \
  https://codeload.github.com/rpcribari/Strata/tar.gz/refs/heads/int6
</code></pre>
<p dir="auto">31,216,899 字节，解压到 <code>/src/Strata-int6</code>。三个意外的好消息：</p>
<ol>
<li><strong>ggml 的 pin 没变</strong>（还是 <code>3cf03257f2</code>），所以我上一轮为 0.2.9 下的 <code>/src/llama.cpp</code> 直接复用，不用重下 37MB。</li>
<li><strong>这个分支自带了我上一篇手补的那两个宏</strong>，而且在 <code>dflash2.cpp:198</code> 把 guard 改成了 <code>#if defined(STRATA_USE_HIP) || defined(STRATA_HIP_GFX906)</code>——比我"补两个 #define"的土办法干净，说明作者踩过同一个坑。</li>
<li><code>project(strata VERSION 0.1.52)</code>，编译 165/165 全过，约 3 分钟。</li>
</ol>
<p dir="auto">编译命令和上一篇完全一样，只把源码目录换掉：</p>
<pre><code class="language-bash">cmake -S . -B build-906 -G Ninja \
  -DSTRATA_HIP_GFX906=ON -DCMAKE_HIP_ARCHITECTURES=gfx906 \
  -DSTRATA_GGML_DIR=/src/llama.cpp \
  -DCMAKE_C_COMPILER=/opt/rocm/llvm/bin/clang \
  -DCMAKE_CXX_COMPILER=/opt/rocm/llvm/bin/clang++ \
  -DCMAKE_BUILD_TYPE=Release
ninja -C build-906 strata
</code></pre>
<p dir="auto"><strong>注意：这里有一个反直觉的取舍——我为了 +30% 把引擎从 0.1.55 退回了 0.1.52。</strong> 新版本里 DFlash2 的改进、<code>--draft mtp</code> 那套新键，全都用不上了。但我是走 MTP + 流水线路线的，DFlash2 本来就用不了（上一篇第五节），所以这个代价对我是零。</p>
<hr />
<h2>五、空转时间本身就是个变量</h2>
<p dir="auto">社区那份 gfx906 调优台账里有一句我当时没在意的话：</p>
<blockquote>
<p dir="auto">重启后与每次换负载后都有约 5 个请求的冷启动爬坡，且是 <strong>10 分钟量级</strong>、值得 3.7 tok/s 的进程级效应。</p>
</blockquote>
<p dir="auto">于是我把同一套配置的等待时间从 90 秒拉到 <strong>540 秒</strong>，重测：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>空转</th>
<th style="text-align:right">decode 中位</th>
<th>三次样本</th>
<th style="text-align:right">prefill</th>
</tr>
</thead>
<tbody>
<tr>
<td>90 s</td>
<td style="text-align:right">61.3</td>
<td>58.4 / 64.9 / 61.3</td>
<td style="text-align:right">701</td>
</tr>
<tr>
<td><strong>540 s</strong></td>
<td style="text-align:right"><strong>65.1</strong></td>
<td>57.6 / 66.9 / 65.1</td>
<td style="text-align:right"><strong>751.9</strong></td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>+6%，一分钱没花。</strong></p>
<p dir="auto">这条值得单独记住：<strong>冷启动不是"等一会儿就好"，而是一条 10 分钟的爬坡曲线。</strong> 空转 90 秒去比两个配置，等于在两条不同形状的爬坡曲线上各取一个点做比较——数字看着挺整齐，结论可能是错的。我前面几轮"某开关无收益"的判断里，至少有一部分要打这个折扣。</p>
<hr />
<h2>六、最后一个选项，判负</h2>
<p dir="auto">那条提交还留了个选项：<code>STRATA_PF_RP_IQ3=2</code>，让 IQ2_S 也走 repacked GEMM（作者报该算子 +12–21%，非 bitwise 但相对误差 1.7e-7）。</p>
<p dir="auto">我们的 pack 是混合量化（层 0/16 是 <code>IQ3_XXS/IQ4_NL</code>、层 8 是 <code>IQ2_S/Q2_0</code>、层 24/32 是 <code>IQ2_S/IQ4_NL</code>、层 40 是 <code>IQ3_S/IQ4_NL</code>），IQ2_S 占比不小，值得一试。同样 540 秒空转：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>臂</th>
<th style="text-align:right">decode 中位</th>
<th style="text-align:right">prefill</th>
</tr>
</thead>
<tbody>
<tr>
<td>21 个开关</td>
<td style="text-align:right"><strong>65.1</strong></td>
<td style="text-align:right">751.9</td>
</tr>
<tr>
<td>22 个（多 <code>RP_IQ3=2</code>）</td>
<td style="text-align:right">60.8</td>
<td style="text-align:right">754.4</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>decode −4.3、prefill 持平。</strong> 判负。作者那个 +12–21% 是在他那种"同类专家集中"的 pack 上测的，我这种层间混排的 pack 把 IQ2_S 从 MMQ 挪走反而更亏。</p>
<hr />
<h2>七、现在的生产配置</h2>
<pre><code class="language-json">{
  "exe": "/src/Strata-int6/build-906/strata",
  "args": [
    "--pack", "/src/models/packs/iq3s",
    "--native", ".../IQ3_S-00001-of-00002.gguf",
    "--ple-gguf", ".../IQ3_S-00002-of-00002.gguf",
    "--expert-profile", "/src/models/learned-iq3s.bin",
    "--expert-profile-save", "/src/models/learned-iq3s-mtp.bin",
    "--expert-profile-save-every", "3",
    "--expert-cache", "auto",
    "--prefill", "auto:16384",
    "--prefill-pipe", "350",
    "--spec", "3",
    "--max-context", "131072",
    "--kv", "int8", "--kv-resident", "32768",
    "--layer-split", "27", "--trim-stage-weights",
    "--mtp", "/src/models/mtp/rt",
    "--pipeline-windows", "2",
    "--pool-workers", "32",
    "--pcie-frac", "0", "--vram-reserve-mib", "1024"
  ],
  "env": {
    "STRATA_RESIDENT_HEADROOM_GIB": "6",
    "STRATA_MTP_STAGE0": "0",
    "STRATA_RESIDENT_PIN": "0",
    "STRATA_GR_NORM_FAST": "1",
    "STRATA_IQ_STAGE_GRID_MMVQ": "1",
    "STRATA_IQ_MMVQ_XLDS": "1",
    "STRATA_IQ_MMVQ_RB": "16",
    "STRATA_IQ_MMVQ_R2": "1",
    "STRATA_MMVQ_XLDS": "1",
    "STRATA_MMVQ_WPB": "8",
    "STRATA_MMVQ_Q6X4": "1",
    "STRATA_MMVQ_Q4X4": "1",
    "STRATA_EXP_X4": "1",
    "STRATA_EXP_GU_H2": "1",
    "STRATA_EXP_LDS_Q50": "1",
    "STRATA_GR_DOWN_TG": "a",
    "STRATA_GR_DOWN_PF": "1",
    "STRATA_MMVF_ROWS": "1",
    "STRATA_GFX906_ATTN_QUERY_SWIZZLE": "1",
    "STRATA_GFX906_ATTN_REDUCE12": "1",
    "STRATA_HIP_SWIGLU_FUSED": "1"
  }
}
</code></pre>
<p dir="auto">实测：<strong>decode 65.1 tok/s / prefill 752 tok/s / 128K 上下文 / 命中率 0.96–0.98 / 冷启动约 60 秒</strong>。冒烟抽查（"机械效率 + 斜面"）输出结构完整、带摩擦力的因果解释。</p>
<p dir="auto">顺便说一句：<code>STRATA_GFX906_ATTN_QUERY_SWIZZLE</code> 和 <code>STRATA_GFX906_ATTN_REDUCE12</code> 这两个开关，<strong>我上一轮单独测它们是判负的</strong>（48.1/47.8，都低于基线 49.3）。现在它们进了全开组合，整体反而更快——这大概是"单开没用、和别的 kernel 一起才有用"的典型，也说明<strong>单开关 A/B 在 kernel 层是会骗人的</strong>。</p>
<hr />
<h2>八、三条可复用的教训</h2>
<h3>1. 收益常藏在"默认关闭 + 文档里一句话"里</h3>
<p dir="auto">我两次踩同一个坑：</p>
<ul>
<li><code>--adapt-every 0</code>：官方冒烟命令就带着，我继承了，<strong>偷走 27%</strong>；</li>
<li>21 个 <code>STRATA_*</code>：默认全关，文档写得很清楚"off by default"，但我先只编了分支就跑，<strong>白跑了 20%</strong>。</li>
</ul>
<p dir="auto">判据很简单：<strong>一个功能如果"默认关"，它的作者就是在等你读文档。</strong> 拿到新分支，先 <code>grep -n "env" docs/*MI50*.md</code>，别急着 <code>ninja</code>。</p>
<h3>2. 任何"某开关无效"的结论，先去日志里确认它真的生效</h3>
<p dir="auto">我在上一篇写过这条，这次又验证了一遍：<code>--pipeline-windows 2</code> 没有 MTP 会被静默关掉，日志里那句 <code>is off: it needs the MTP drafter</code> 躺在几万行里。判据就看三类行：<code>is off</code> / <code>kept as asked</code> / 启动 banner。</p>
<h3>3. 测速的空转时间必须够长</h3>
<p dir="auto">90 秒和 540 秒能差 6%。<strong>这条对谁都成立</strong>，不是我这台老机器的特例——社区在同一份台账里写了"10 分钟量级"。</p>
<hr />
<h2>九、代价与回滚</h2>
<p dir="auto">诚实列出：</p>
<ol>
<li><strong>引擎版本倒退</strong>：0.1.52+PR &lt; 0.1.55 &lt; 0.1.57。如果哪天官方把 PR 的 kernel 合进 main，我立刻回去。</li>
<li><strong>回滚成本几乎为零</strong>：<code>/src/models/strata-iq3smtp.json</code>（0.1.55 + MTP + 流水线，54.0）和 <code>/src/Strata/build-906/strata</code> 都留着，改个 <code>exe</code> 路径重启就能退回。</li>
<li><strong>分支是 untested 的</strong>：一个人维护、没人评审、基于 0.2.7。我只能用"编译通过 + 冒烟正常 + 输出结构正确"来担保，<strong>长跑稳定性还没验证</strong>（这点和上一篇的待办一样）。</li>
</ol>
<hr />
<h2>十、第 9 个台阶后的横向对比</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>平台</th>
<th>卡</th>
<th style="text-align:right">decode</th>
<th>备注</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>本机（本轮）</strong></td>
<td><strong>2×MI50 16G</strong></td>
<td style="text-align:right"><strong>65.1</strong></td>
<td>int6 分支 + 21 开关 + IQ3_S + MTP + 流水线</td>
</tr>
<tr>
<td>本机（上一篇）</td>
<td>2×MI50 16G</td>
<td style="text-align:right">54.0</td>
<td>0.1.55 + MTP + 流水线</td>
</tr>
<tr>
<td>官方参考机</td>
<td>2×MI50 16G</td>
<td style="text-align:right">49.2</td>
<td>IQ3_XXS，Ryzen 5700X + DDR4-3600</td>
</tr>
<tr>
<td>社区同卡</td>
<td>2×Radeon Pro VII 16G</td>
<td style="text-align:right">47.8</td>
<td>IQ3_S，Ryzen 5 2600 + DDR4-2133</td>
</tr>
<tr>
<td>单卡 4080 SUPER</td>
<td>1×16G</td>
<td style="text-align:right">58.8</td>
<td>IQ3_XXS，i7-12700 + DDR4-3200</td>
</tr>
<tr>
<td>同机 llama.cpp</td>
<td>2×MI50 16G</td>
<td style="text-align:right">26.3–26.6</td>
<td>Qwen3.8-27B UD-Q4_K_M</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>我这台 2700 块的洋垃圾，现在的 decode 已经超过了单卡 4080 SUPER 的公开数据（58.8），而那张卡的价格够配三台这机器。</strong></p>
<p dir="auto">而且这是在 <strong>DDR3-1333 约 30 GB/s</strong> 的前提下跑出来的。这也侧面说明：MoE 的 decode 瓶颈主要不在显存带宽，而在<strong>专家回落到内存时的那条路有没有被榨干</strong>——这条路一旦通了，便宜的 DDR3 也能顶住。</p>
<hr />
<h2>十一、待办（更新）</h2>
<ol>
<li><strong>质量仍然只有冒烟和风格样本，没有正式评测。</strong> 3bit 在中文长文上的失效模式是重复、断段、术语漂移，<strong>必须真材料 A/B 才算数</strong>——这是我现在唯一的硬闸门。</li>
<li>长跑稳定性：分支版连续跑满 24 小时没有掉速/OOM 才算数。</li>
<li>没测并发（官方与社区都说这条路径并发不行）。</li>
<li><code>--prefill-pipe</code> 在"专家全驻"场景（换 Coder IQ1_M 那种塞得进 32GB 显存的档）还没复测——PR 里它 +73% @8K 的前提就是全驻。</li>
<li>层切分仍只用了官方给的 27/21，没穷举。</li>
</ol>
<hr />
<h2>十二、一句话总结</h2>
<p dir="auto"><strong>上一篇的 54 是"把开关打开"，这一篇的 65 是"发现开关根本没打开"。</strong></p>
<p dir="auto">真正值钱的不是那 11 tok/s，而是这两次都指向同一件事：<strong>这套引擎的默认值是给"能跑起来"准备的，不是给"跑得快"准备的</strong>。<code>--adapt-every 0</code> 是一处，21 个 env 是另一处，下一处大概率还写在某个没人读的 <code>docs/*MI50*.md</code> 里。</p>
<p dir="auto">项目地址：<a href="https://github.com/Niko1221/Strata" rel="nofollow ugc">Niko1221/Strata</a><br />
分支：<a href="https://github.com/Niko1221/Strata/pull/5361" rel="nofollow ugc">rpcribari: int6</a></p>
<hr />
]]></description><link>https://lcz.me/post/31740</link><guid isPermaLink="true">https://lcz.me/post/31740</guid><dc:creator><![CDATA[Sun Lyu]]></dc:creator><pubDate>Sat, 07 Nov 2026 12:06:41 GMT</pubDate></item><item><title><![CDATA[Reply to 【纯闲着】2700 块的洋垃圾跑 QFN：MI50 16G×2 + 128G DDR3，从装系统到 54 tok/s，这可能是目前价格最低的洋垃圾方案。 on Sat, 07 Nov 2026 10:51:29 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/kiwi" aria-label="Profile: kiwi">@<bdi>kiwi</bdi></a> 很好，又多了一期视频，最好和这个数据比较下。然后github上那个优化看看是否适用</p>
]]></description><link>https://lcz.me/post/31733</link><guid isPermaLink="true">https://lcz.me/post/31733</guid><dc:creator><![CDATA[terry]]></dc:creator><pubDate>Sat, 07 Nov 2026 10:51:29 GMT</pubDate></item><item><title><![CDATA[Reply to 【纯闲着】2700 块的洋垃圾跑 QFN：MI50 16G×2 + 128G DDR3，从装系统到 54 tok/s，这可能是目前价格最低的洋垃圾方案。 on Sat, 07 Nov 2026 10:43:33 GMT]]></title><description><![CDATA[<p dir="auto">晚點也來發我的雙雷七。跟版大的架構差不多，夠用了～</p>
]]></description><link>https://lcz.me/post/31731</link><guid isPermaLink="true">https://lcz.me/post/31731</guid><dc:creator><![CDATA[kiwi]]></dc:creator><pubDate>Sat, 07 Nov 2026 10:43:33 GMT</pubDate></item><item><title><![CDATA[Reply to 【纯闲着】2700 块的洋垃圾跑 QFN：MI50 16G×2 + 128G DDR3，从装系统到 54 tok/s，这可能是目前价格最低的洋垃圾方案。 on Sat, 07 Nov 2026 09:29:01 GMT]]></title><description><![CDATA[<p dir="auto">这个跑Minimax H3表现如何？</p>
]]></description><link>https://lcz.me/post/31722</link><guid isPermaLink="true">https://lcz.me/post/31722</guid><dc:creator><![CDATA[Miraco]]></dc:creator><pubDate>Sat, 07 Nov 2026 09:29:01 GMT</pubDate></item><item><title><![CDATA[Reply to 【纯闲着】2700 块的洋垃圾跑 QFN：MI50 16G×2 + 128G DDR3，从装系统到 54 tok/s，这可能是目前价格最低的洋垃圾方案。 on Sat, 07 Nov 2026 08:11:50 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/c-jh" aria-label="Profile: c-jh">@<bdi>c-jh</bdi></a> 就等着你的帖子发视频了。</p>
]]></description><link>https://lcz.me/post/31706</link><guid isPermaLink="true">https://lcz.me/post/31706</guid><dc:creator><![CDATA[terry]]></dc:creator><pubDate>Sat, 07 Nov 2026 08:11:50 GMT</pubDate></item><item><title><![CDATA[Reply to 【纯闲着】2700 块的洋垃圾跑 QFN：MI50 16G×2 + 128G DDR3，从装系统到 54 tok/s，这可能是目前价格最低的洋垃圾方案。 on Sat, 07 Nov 2026 08:08:02 GMT]]></title><description><![CDATA[<blockquote>
<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/terry" aria-label="Profile: terry">@<bdi>terry</bdi></a> <a href="/post/31694">说</a>:</p>
<p dir="auto">不充点实拍图呢，我弟，我先水一集视频。</p>
</blockquote>
<p dir="auto">好，晚上回去搞</p>
]]></description><link>https://lcz.me/post/31705</link><guid isPermaLink="true">https://lcz.me/post/31705</guid><dc:creator><![CDATA[Sun Lyu]]></dc:creator><pubDate>Sat, 07 Nov 2026 08:08:02 GMT</pubDate></item><item><title><![CDATA[Reply to 【纯闲着】2700 块的洋垃圾跑 QFN：MI50 16G×2 + 128G DDR3，从装系统到 54 tok/s，这可能是目前价格最低的洋垃圾方案。 on Sat, 07 Nov 2026 08:07:50 GMT]]></title><description><![CDATA[<p dir="auto">我也在 整理 一个 v100 显卡 16*2  nvlink  。最低价格  也不急着买。底板用了 600多 还没有到手 ，到手了 再考虑 v100</p>
]]></description><link>https://lcz.me/post/31704</link><guid isPermaLink="true">https://lcz.me/post/31704</guid><dc:creator><![CDATA[c jh]]></dc:creator><pubDate>Sat, 07 Nov 2026 08:07:50 GMT</pubDate></item><item><title><![CDATA[Reply to 【纯闲着】2700 块的洋垃圾跑 QFN：MI50 16G×2 + 128G DDR3，从装系统到 54 tok/s，这可能是目前价格最低的洋垃圾方案。 on Sat, 07 Nov 2026 07:54:55 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> 我弟硬盘家里随便找个旧的就能跑，<img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/1f622.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--cry" style="height:1.4em;width:auto;vertical-align:middle" title="😢" alt="😢" />，这个不用较真</p>
]]></description><link>https://lcz.me/post/31702</link><guid isPermaLink="true">https://lcz.me/post/31702</guid><dc:creator><![CDATA[terry]]></dc:creator><pubDate>Sat, 07 Nov 2026 07:54:55 GMT</pubDate></item><item><title><![CDATA[Reply to 【纯闲着】2700 块的洋垃圾跑 QFN：MI50 16G×2 + 128G DDR3，从装系统到 54 tok/s，这可能是目前价格最低的洋垃圾方案。 on Sat, 07 Nov 2026 07:44:06 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/rori" aria-label="Profile: rori">@<bdi>rori</bdi></a> <img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/1f527.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--wrench" style="height:1.4em;width:auto;vertical-align:middle" title="🔧" alt="🔧" /> <strong>奖励通知</strong>：感谢提供 MI50 / MI60 的优化信息（Strata 分支），对折腾这批卡的同好很有参考价值，奖励 <strong>+3 积分</strong>。</p>
]]></description><link>https://lcz.me/post/31701</link><guid isPermaLink="true">https://lcz.me/post/31701</guid><dc:creator><![CDATA[Xiaote]]></dc:creator><pubDate>Sat, 07 Nov 2026 07:44:06 GMT</pubDate></item><item><title><![CDATA[Reply to 【纯闲着】2700 块的洋垃圾跑 QFN：MI50 16G×2 + 128G DDR3，从装系统到 54 tok/s，这可能是目前价格最低的洋垃圾方案。 on Sat, 07 Nov 2026 07:24:36 GMT]]></title><description><![CDATA[<p dir="auto">1T的NVMe硬盘不计入可不行。这个不便宜。按小黄鱼价加上电源算1000不过分。<br />
加上1000，这也是很有性价比了。</p>
]]></description><link>https://lcz.me/post/31699</link><guid isPermaLink="true">https://lcz.me/post/31699</guid><dc:creator><![CDATA[xiongjie gao]]></dc:creator><pubDate>Sat, 07 Nov 2026 07:24:36 GMT</pubDate></item><item><title><![CDATA[Reply to 【纯闲着】2700 块的洋垃圾跑 QFN：MI50 16G×2 + 128G DDR3，从装系统到 54 tok/s，这可能是目前价格最低的洋垃圾方案。 on Sat, 07 Nov 2026 07:19:37 GMT]]></title><description><![CDATA[<p dir="auto">有时候我的剽的有点不好意思了，弟兄们测试，我水视频，只能给点积分奖励，以后流量大了，网站能够赚钱也搞点福利，只是现在流量还不行<img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/1f602.png?v=5be5614064c" class="not-responsive emoji emoji-android emoji--joy" style="height:1.4em;width:auto;vertical-align:middle" title="😂" alt="😂" /></p>
]]></description><link>https://lcz.me/post/31698</link><guid isPermaLink="true">https://lcz.me/post/31698</guid><dc:creator><![CDATA[terry]]></dc:creator><pubDate>Sat, 07 Nov 2026 07:19:37 GMT</pubDate></item><item><title><![CDATA[Reply to 【纯闲着】2700 块的洋垃圾跑 QFN：MI50 16G×2 + 128G DDR3，从装系统到 54 tok/s，这可能是目前价格最低的洋垃圾方案。 on Sat, 07 Nov 2026 07:17:48 GMT]]></title><description><![CDATA[<p dir="auto">這卡有潛力, 已經有大神做strata優化:<br />
<a href="https://github.com/Niko1221/Strata/pull/5361" rel="nofollow ugc">https://github.com/Niko1221/Strata/pull/5361</a></p>
]]></description><link>https://lcz.me/post/31697</link><guid isPermaLink="true">https://lcz.me/post/31697</guid><dc:creator><![CDATA[rori]]></dc:creator><pubDate>Sat, 07 Nov 2026 07:17:48 GMT</pubDate></item><item><title><![CDATA[Reply to 【纯闲着】2700 块的洋垃圾跑 QFN：MI50 16G×2 + 128G DDR3，从装系统到 54 tok/s，这可能是目前价格最低的洋垃圾方案。 on Sat, 07 Nov 2026 07:13:43 GMT]]></title><description><![CDATA[<p dir="auto">这个8卡是不是可以跑ds v4.1 flash了</p>
]]></description><link>https://lcz.me/post/31696</link><guid isPermaLink="true">https://lcz.me/post/31696</guid><dc:creator><![CDATA[Hackner Weinland]]></dc:creator><pubDate>Sat, 07 Nov 2026 07:13:43 GMT</pubDate></item><item><title><![CDATA[Reply to 【纯闲着】2700 块的洋垃圾跑 QFN：MI50 16G×2 + 128G DDR3，从装系统到 54 tok/s，这可能是目前价格最低的洋垃圾方案。 on Sat, 07 Nov 2026 08:11:02 GMT]]></title><description><![CDATA[<p dir="auto">补充点实拍图呢，我弟，我先水一集视频。</p>
]]></description><link>https://lcz.me/post/31694</link><guid isPermaLink="true">https://lcz.me/post/31694</guid><dc:creator><![CDATA[terry]]></dc:creator><pubDate>Sat, 07 Nov 2026 08:11:02 GMT</pubDate></item><item><title><![CDATA[Reply to 【纯闲着】2700 块的洋垃圾跑 QFN：MI50 16G×2 + 128G DDR3，从装系统到 54 tok/s，这可能是目前价格最低的洋垃圾方案。 on Sat, 07 Nov 2026 07:02:13 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>+6 积分</strong>奖励，希望再接再厉！</p>
<blockquote>
<p dir="auto">奖励凭证：精华 +6 分 · 编号 f2896-4934-1</p>
</blockquote>
]]></description><link>https://lcz.me/post/31693</link><guid isPermaLink="true">https://lcz.me/post/31693</guid><dc:creator><![CDATA[Xiaote]]></dc:creator><pubDate>Sat, 07 Nov 2026 07:02:13 GMT</pubDate></item></channel></rss>