<?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[Strix Halo本地部署 Qwen3.8 Flash Next — 環境、失效、可行與技術總結]]></title><description><![CDATA[<h1>Qwen3.8-Flash-Next 180B 在 Strix Halo 單機:一個旗標換到 prefill +22%</h1>
<blockquote>
<p dir="auto">結論先講:在 128GB 的 Ryzen AI MAX+ 395 上跑 180B-A6B,把 <code>-lm mmap</code> 換成 <code>-lm dio</code>,<br />
prefill 從 171 提到 209 tok/s,載入時間從 111 秒降到 53 秒,tg 不變。<br />
前提是 Windows 的 pagefile 初始值要調大。</p>
</blockquote>
<hr />
<h2>一、硬體與軟體配置</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>CPU / iGPU</td>
<td>AMD Ryzen AI MAX+ 395 w/ Radeon 8060S(gfx1151),16C/32T</td>
</tr>
<tr>
<td>記憶體</td>
<td>128 GB LPDDR5X,<strong>BIOS 切 64/64</strong>(iGPU carve 64 GB,OS 可見 63.6 GiB)</td>
</tr>
<tr>
<td>OS</td>
<td>Windows 11 Home 26200</td>
</tr>
<tr>
<td>後端</td>
<td>Vulkan(AMD 專有驅動)</td>
</tr>
<tr>
<td>build</td>
<td><a href="https://github.com/apepojken/llama.cpp" rel="nofollow ugc">apepojken/llama.cpp</a> <code>qwen4exp-spec-mtp</code> @ 843d575</td>
</tr>
<tr>
<td>模型</td>
<td>Qwen3.8-Flash-Next 180B-A6B,unsloth <strong>UD-IQ4_XS</strong>(87.3 GiB)</td>
</tr>
<tr>
<td>投機解碼</td>
<td>自編 MTP sidecar <code>mtp-ape-Q8_0.gguf</code>(4.14 GB)</td>
</tr>
</tbody>
</table>
<p dir="auto">模型本身的結構值得先記住,因為後面的優化跟它直接相關:</p>
<ul>
<li>48 層 = <strong>12 層 QSA</strong>(稀疏注意力,帶 indexer)+ <strong>36 層 Gated DeltaNet</strong>(線性注意力,狀態固定大小)</li>
<li>512 experts / 10 active</li>
<li>一張 <strong>51.2B 參數的 n-gram / PLE 查表</strong>:<code>per_layer_token_embd.weight</code>,shape <code>[160, 320001536]</code>,在 IQ4_XS 下佔 <strong>26.82 GiB</strong></li>
<li>原生 262144 context</li>
</ul>
<hr />
<h2>二、思維目標</h2>
<p dir="auto">一開始我在調的是<strong>運算面</strong>的旋鈕:<code>-ub</code>、<code>-tb</code> 執行緒數、KV 量化型別、投機解碼的 draft 深度、要不要移植上游還沒合併的 Vulkan FA 修正。</p>
<p dir="auto">這些方向掃完之後,pp 仍卡在 170 上下。</p>
<p dir="auto">轉折點是加上記憶體取樣之後看到的一行:</p>
<pre><code>\Memory\Available Bytes = 0.29 GiB
</code></pre>
<p dir="auto"><strong>不是 commit 快滿,是實體可用記憶體真的見底。</strong> 而且不論 context 開多大都會發生。</p>
<p dir="auto">追下去才理解這台機器的記憶體模型:</p>
<pre><code>iGPU carve 已配置    63.3 GiB    (carve 總量 64 GB)
行程私有記憶體峰值   70.99 GiB   (純 iGPU)
OS 可見實體 RAM      63.6 GiB
</code></pre>
<p dir="auto">63.3 + 71 = 134 GiB,在一台 128 GB 的機器上。原因是 <strong>WDDM 對每一筆 GPU 配置都會在系統 commit 上保留等量額度</strong>,所以放進 carve 的 63 GiB 同時也向 63.6 GiB 的實體 RAM 記一筆。64/64 的切分讓兩邊剛好都貼死。</p>
<p dir="auto">在這個前提下,<code>-lm mmap</code> 的問題就浮出來了:那張 26.8 GiB 的 engram 查表是 file-backed,它的檔案頁會把 standby list 吃光。<strong>模型在跟自己的 page cache 搶記憶體。</strong></p>
<p dir="auto">所以真正的目標從「怎麼算得更快」變成 <strong>「怎麼讓它不要在分頁」</strong>。</p>
<hr />
<h2>三、最佳化參數</h2>
<pre><code class="language-bash">llama-server \
  -m Qwen3.8-Flash-Next-UD-IQ4_XS-00001-of-00003.gguf \
  -dev Vulkan0 -sm layer -ngl 99 --fit off \
  -lm dio \
  --no-repack \
  -md mtp-ape-Q8_0.gguf -devd Vulkan0 -ngld 99 \
  --spec-type draft-mtp --spec-draft-n-max 3 --spec-draft-p-min 0.75 \
  -fa auto -ctk q8_0 -ctv q8_0 \
  -c 98304 --ubatch-size 1024 -b 2048 \
  -t 2 -tb 8 \
  --parallel 1 --cont-batching --no-warmup
</code></pre>
<p dir="auto">環境變數:</p>
<pre><code>GGML_VK_VISIBLE_DEVICES=0
LLAMA_ARG_CHAT_TEMPLATE_KWARGS={"enable_thinking":false}
</code></pre>
<p dir="auto"><strong><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/1f534.png?v=2fb7360d8c6" class="not-responsive emoji emoji-android emoji--red_circle" style="height:23px;width:auto;vertical-align:middle" title="🔴" alt="🔴" /> 系統前提 —— 沒做這個,上面的組態會慢 9.4%:</strong></p>
<pre><code>pagefile 初始大小 32768 MB  -&gt;  98304 MB
（系統內容 &gt; 進階 &gt; 效能設定 &gt; 進階 &gt; 虛擬記憶體 &gt; 自訂大小 &gt; 一定要按「設定」）
</code></pre>
<p dir="auto"><code>-lm dio</code> 會把 commit 需求推到約 119 GiB。若 pagefile 初始值太小,Windows 得<strong>邊跑邊擴</strong>,commit 餘裕會壓到只剩 0.56 GiB,prefill 因此掉到 190.70。預先配置好之後是 208.65。</p>
<p dir="auto"><img src="https://i.ibb.co/vxHB7rJ2/01-launch.png" alt="啟動組態" class=" img-fluid img-markdown" /></p>
<h3>幾個參數的理由</h3>
<ul>
<li><strong><code>-t 2 -tb 8</code></strong> — decode 只給 2 執行緒、prefill 給 8。CPU 使用率只有 8%,加執行緒是空轉搶 LPDDR5X 頻寬。<code>-tb</code> 12/16/20/32 全部更差。這一項在 41k 值 <strong>tg +40.7%</strong>。</li>
<li><strong><code>-ngl 99 --fit off</code></strong> — <code>--fit on</code> 會照 iGPU 回報的假 free 值(carve+shared 顯示 108 GiB)分配,配 <code>-ts</code> 時甚至直接放棄 fitting。</li>
<li><strong><code>--ubatch-size 1024</code></strong> — 2048 實測 pp −3.3%。注意 <code>-ub</code> 和 <code>-b</code> 是兩回事,<code>-b</code> 不影響顯存。</li>
<li><strong><code>-ctk/-ctv q8_0</code></strong> — q4_0 是 pp −0.9% / tg −2.5%,f16 是 pp −4.7% 而且在 98304 裝不下(37.4 + 44.3 &gt; 63.3 carve)。<strong>q8_0 在這台機器上就是最佳解</strong>,沒有量化 KV 的 dequant 稅。</li>
<li><strong><code>--spec-draft-n-max 3</code></strong> — 見下方「已排除」。</li>
</ul>
<hr />
<h2>四、實測</h2>
<p dir="auto">協定:code prompt、每組獨立行程冷啟、<code>ignore_eos</code> 固定生成量、全程記憶體取樣。</p>
<p dir="auto"><img src="https://i.ibb.co/nqwmVDdp/02-ab.png" alt="A/B 計時" class=" img-fluid img-markdown" /></p>
<p dir="auto"><img src="https://i.ibb.co/XkYdHcvj/03-mem.png" alt="記憶體取樣" class=" img-fluid img-markdown" /></p>
<p dir="auto"><code>Available Bytes</code> 從 <strong>0.29 → 18.50 GiB</strong>,這是整個優化的關鍵指標。有趣的是 dio 讓<strong>行程私有記憶體反而增加 28 GiB</strong>(71.87 → 99.83,約等於 engram 的大小)—— 它把 engram 讀進私有記憶體而不是靠 page cache,分頁決策交回給 OS 的一般機制,結果是可用記憶體大幅回升。</p>
<p dir="auto">載入時間 111s → 53s 也是同一個原因:mmap 要逐頁 fault,dio 是大塊循序讀。</p>
<h3>深度掃描</h3>
<p dir="auto"><img src="https://i.ibb.co/WNYHBkMC/04-depth.png" alt="深度掃描" class=" img-fluid img-markdown" /></p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>prompt tokens</th>
<th><code>-lm mmap</code> pp</th>
<th><code>-lm dio</code> pp</th>
<th>Δ</th>
</tr>
</thead>
<tbody>
<tr>
<td>9,815</td>
<td>200.01</td>
<td><strong>260.01</strong></td>
<td><strong>+30.0%</strong></td>
</tr>
<tr>
<td>40,477</td>
<td>171.09</td>
<td><strong>190.70</strong></td>
<td>+11.5%</td>
</tr>
<tr>
<td>80,943</td>
<td>—</td>
<td><strong>164.53</strong></td>
<td>—</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>淺 context 的增益反而更大。</strong> 直覺上 prefill 越短、engram 被查得越少,壓力應該越低;實際相反。推測 mmap 的逐頁 fault 是<strong>固定成本</strong>,在短 prefill 上佔比更高。</p>
<p dir="auto">tg 幾乎不隨深度衰減:10k 23.99 / 41k 24.4–26.2 / 80k 23.53。</p>
<hr />
<h2>五、已排除的項目(附數字,省得別人重跑)</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>項目</th>
<th>實測</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>-ub 2048</code></td>
<td>pp −3.3%</td>
</tr>
<tr>
<td><code>--cache-ram</code> 加大</td>
<td>預設 8192 MiB <strong>本來就在命中</strong>(41k 重送 269s → 34s,7.9×),16384 完全無差異</td>
</tr>
<tr>
<td><code>-c</code> 減半</td>
<td>mmap 下看似 +7.9%,<strong>是記憶體壓力的假象</strong>;dio 下 c98304 反而略快</td>
</tr>
<tr>
<td>KV <code>q4_0</code> / <code>f16</code></td>
<td>−2.5% / −4.7%,見上</td>
</tr>
<tr>
<td>MTP <code>n_max</code> 改值</td>
<td>3~6 之間無可測量差異,見下</td>
</tr>
<tr>
<td><code>-sm row</code></td>
<td>Vulkan 後端未實作 split buffers</td>
</tr>
<tr>
<td><code>-sm tensor</code></td>
<td>qwen4exp 的 GDN / hyper-connection / indexer 都不在切分邏輯的正規式裡</td>
</tr>
<tr>
<td><code>--spec-type ngram-*</code></td>
<td><code>ngram-mod</code> 接受率全 0;<code>ngram-cache</code> 有 24% 接受率卻慢 34%</td>
</tr>
<tr>
<td>DFlash</td>
<td>Flash-Next <strong>沒有對應 drafter</strong>(只有 Qwen3.8-27B / 3.6-27B / Coder-Next 有)</td>
</tr>
</tbody>
</table>
<h3>關於 MTP <code>n_max</code>:一個量測陷阱</h3>
<p dir="auto">我掃了 n = 2/3/4/5/6/8。在 <code>temperature 0.7</code> 下最佳是 n=4(tg 25.77)、最差是 n=5(20.97)。<br />
換成 <code>temperature 0</code> 貪婪解碼重跑,<strong>最佳變成 n=5(23.53)、n=4 幾乎墊底</strong>。</p>
<p dir="auto">兩個協定的最佳與最差完全對調,而貪婪那組自己的 pp 就在 196.9–205.2 之間跳(4.2%)。</p>
<p dir="auto"><strong>結論是 n 在 3~6 之間沒有可測量的差異。</strong> 但更值得分享的是背後的原因:MTP 的 acceptance 取決於 draft 猜的 token 跟 target 抽到的 token 一不一致 —— <strong>取樣一開,acceptance 就跟著隨機</strong>。實測 acceptance 會在 0.72–0.94 之間跳動,那不是模型特性,是取樣造成的量測誤差。</p>
<p dir="auto">要比較投機解碼的參數,<strong>請務必用貪婪解碼 + <code>ignore_eos</code> 固定生成量</strong>,否則量到的是隨機數。</p>
<hr />
<h2>附1:量測方法</h2>
<ul>
<li>每組獨立行程冷啟,啟動前確認 <code>llama-server</code> 行程數為 0(用 <code>Stop-Process</code>,<strong>Git Bash 的 <code>pkill -f</code> 殺不掉 Windows 行程</strong>)</li>
<li><code>mkdir</code> 原子鎖確保同時只有一個 bench 在跑（模型佔 63 GiB，兩個實例會直接互相排擠）</li>
<li>prompt 對齊的是 <strong>token 數不是字元數</strong>(程式碼 3.57 字元/token,散文 5.56,同字元數會差 50% token)</li>
<li>全程取樣 <code>\Memory\Committed Bytes</code>、<code>\Memory\Commit Limit</code>、<code>\Memory\Available Bytes</code>、行程私有記憶體</li>
<li>prompt 最前面插 nonce,避免 prefix cache 讓 pp 造假</li>
</ul>
<h2>附2:</h2>
<ul>
<li>
<p dir="auto">附上Pelican ride bicycle svg經典題＠dsh監控<br />
<img src="https://i.ibb.co/MdgdX3v/2026-09-01-184938636.png" alt="最後附上Pelican ride bicycle svg經典題＠dsh監控" class=" img-fluid img-markdown" /></p>
</li>
<li>
<p dir="auto">Deepseek Harness跑完畫面<br />
<img src="https://i.ibb.co/JF3WCcKs/2026-09-01-185325858.png" alt="替代文字" class=" img-fluid img-markdown" /></p>
</li>
<li>
<p dir="auto">最後svg完成圖截圖<br />
<img src="https://i.ibb.co/pj6T2HGY/2026-09-01-185530187.png" alt="替代文字" class=" img-fluid img-markdown" /></p>
</li>
</ul>
]]></description><link>https://lcz.me/topic/1453</link><generator>RSS for Node</generator><lastBuildDate>Mon, 07 Sep 2026 16:51:03 GMT</lastBuildDate><atom:link href="https://lcz.me/topic/1453.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 01 Sep 2026 10:27:08 GMT</pubDate><ttl>60</ttl></channel></rss>