<?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[【实测】Mac Studio M5 Max 64GB 跑 Strata + Qwen3.8-Flash-Next Q2_0：安装、配置与 256K 上下文阶梯实测]]></title><description><![CDATA[<blockquote>
<p dir="auto">结论先说：<strong>64GB 的 M5 Max 能跑 125B 的 Qwen3.8-Flash-Next（Q2_0 量化），262K 上下文完整跑通，512K 卡在时间预算而不是模型本身。</strong><br />
实测 prefill 吞吐约 <strong>1,870–2,077 tok/s</strong>，生成吞吐约 <strong>79–89 tok/s</strong>；512K 请求引擎侧实际跑了 <strong>310.5 s</strong> 才被客户端中止。</p>
</blockquote>
<hr />
<h2>一、测试机器</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>项目</th>
<th>配置</th>
</tr>
</thead>
<tbody>
<tr>
<td>机型</td>
<td>Mac Studio（Mac17,14，型号 MHQJ4LL/A）</td>
</tr>
<tr>
<td>芯片</td>
<td>Apple M5 Max</td>
</tr>
<tr>
<td>CPU</td>
<td>18 核（6 超级核 + 12 性能核）</td>
</tr>
<tr>
<td>统一内存</td>
<td>64 GB</td>
</tr>
<tr>
<td>GPU</td>
<td>内置，40 核，Metal 4</td>
</tr>
<tr>
<td>系统</td>
<td>macOS 27.0.1（Build 26A434），arm64</td>
</tr>
</tbody>
</table>
<p dir="auto">引擎自报的 CPU 配置（启动日志）：</p>
<pre><code class="language-text">CPU pool: 16 workers by default (18 physical cores, 18 logical processors;
bounded by physical cores, one kept free)
host thread on core 0 (draining too)
this CPU has no AVX-512: the expert kernels run on ggml-cpu vec_dot
</code></pre>
<hr />
<h2>二、软件与模型</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>项目</th>
<th>内容</th>
</tr>
</thead>
<tbody>
<tr>
<td>推理框架</td>
<td><strong>Strata</strong>（开源，MIT）—— 版本 0.2.1，Metal 引擎 <strong>0.1.46.2</strong>（日志显示 <code>engine 0.1.46-metal</code>）</td>
</tr>
<tr>
<td>模型</td>
<td><strong>Qwen3.8-Flash-Next</strong>，125B 参数 MoE（48 层，每层 512 专家）</td>
</tr>
<tr>
<td>量化版本</td>
<td>ISTA-DASLab 的 <strong>GSQ-RCO Q2_0</strong>（分 2 个 shard）</td>
</tr>
<tr>
<td>模型体积</td>
<td>shard1 <strong>37.6 GB</strong> + shard2（PLE n-gram 表） <strong>28.8 GB</strong> = <strong>66.4 GB</strong></td>
</tr>
<tr>
<td>视觉编码器</td>
<td><code>mmproj-Qwen3.8-Flash-Next-BF16.gguf</code>，<strong>0.91 GB</strong></td>
</tr>
<tr>
<td>MTP 草稿层</td>
<td><code>mtp-q2_0.gguf</code>，<strong>0.89 GB</strong>（draft 词表 106,299 tokens）</td>
</tr>
<tr>
<td>本地 pack</td>
<td><code>packs/q2_0/dense.bin</code>，<strong>1.49 GB</strong>（1,079 个张量）</td>
</tr>
<tr>
<td>磁盘总占用</td>
<td><code>Strata-data/</code> 约 <strong>70 GB</strong></td>
</tr>
<tr>
<td>服务地址</td>
<td>OpenAI 兼容 API：<code>http://127.0.0.1:8080/v1</code>；聊天页：<code>http://127.0.0.1:8080/</code></td>
</tr>
</tbody>
</table>
<p dir="auto"><code>/v1/health</code> 返回：</p>
<pre><code class="language-json">{"status":"ok","max_context":524288,"model":"qwen3.8-flash-next-q2_0",
 "images":true,"api_key":false,"loaded":true,"service":"strata"}
</code></pre>
<hr />
<h2>三、安装过程（Mac 源码路线）</h2>
<p dir="auto">Strata 在 Mac 上有两条路：<code>.dmg</code> 应用 / Terminal 版（预编译引擎），或源码 <code>./setup.sh</code>（自己编译 Metal 引擎）。本机走的是<strong>源码路线</strong>。</p>
<pre><code class="language-bash">git clone https://github.com/Niko1221/Strata &amp;&amp; cd Strata
./setup.sh          # 问模型尺寸；--yes 走推荐答案
</code></pre>
<p dir="auto"><code>setup.sh</code> 依次做 7 件事（已完成的步骤会自动跳过）：</p>
<ol>
<li><strong>Python</strong>：需要 3.10+，macOS 自带 3.9 时会下载一个 25 MB 的独立 Python 3.12（SHA-256 校验），不需要 sudo/Homebrew。本机已有 Homebrew Python 3.14，直接建 <code>.venv</code>。</li>
<li><strong>体检</strong>：芯片、内存、macOS 版本、Command Line Tools、磁盘空间。</li>
<li><strong>Python 依赖</strong>装进 <code>.venv</code>，CMake 与 Ninja 也来自 pip。</li>
<li><strong>编译引擎</strong> <code>build-metal/strata</code>（Apple metal-cpp 头文件 + llama.cpp 的 ggml，本机 AppleClang 21）。</li>
<li><strong>下载模型</strong>（断点续传；已有 GGUF 可用 <code>--gguf-dir</code>）。</li>
<li><strong>准备模型</strong>：生成 pack（几秒）+ MTP 草稿层（约 5 GB 原始 checkpoint）。</li>
<li><strong>写 <code>strata-&lt;model&gt;.json</code> 与 <code>run-&lt;model&gt;.sh</code>，然后启动服务。</strong></li>
</ol>
<h3>本机实际时间线（2026-10-20）</h3>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>时间</th>
<th>事件</th>
</tr>
</thead>
<tbody>
<tr>
<td>14:02</td>
<td>创建 <code>.venv</code>（Python 3.14.7）</td>
</tr>
<tr>
<td>14:03</td>
<td>Metal 引擎编译完成（<code>build-metal/strata</code>，4.7 MB）</td>
</tr>
<tr>
<td>14:17</td>
<td>模型 shard 1 下载完成（37.6 GB）</td>
</tr>
<tr>
<td>14:27</td>
<td>模型 shard 2 下载完成（28.8 GB）</td>
</tr>
<tr>
<td>14:28</td>
<td>视觉编码器 + pack（<code>dense.bin</code> 1.49 GB）就绪；<code>strata-vision</code> 编译完成</td>
</tr>
<tr>
<td>14:31</td>
<td>MTP 草稿层（0.89 GB）生成；写入 <code>run-q2_0.sh</code></td>
</tr>
<tr>
<td>14:31:43</td>
<td>引擎首次启动，<code>--max-context 32768</code></td>
</tr>
<tr>
<td>15:24 / 15:32 / 16:52</td>
<td>上下文依次调到 131072 → 262144 → 262144</td>
</tr>
<tr>
<td>20:19 / 20:56</td>
<td>上下文调到 <strong>524288</strong>，跑阶梯实测</td>
</tr>
</tbody>
</table>
<hr />
<h2>四、配置信息</h2>
<p dir="auto"><code>strata-q2_0.json</code>（由 <code>run-q2_0.sh</code> 调用）：</p>
<pre><code class="language-json">{
  "exe": ".../build-metal/strata",
  "args": [
    "--pack",        ".../Strata-data/packs/q2_0",
    "--native",      ".../Qwen3.8-Flash-Next-GSQ-RCO-Q2_0-00001-of-00002.gguf",
    "--ple-gguf",    ".../Qwen3.8-Flash-Next-GSQ-RCO-Q2_0-00002-of-00002.gguf",
    "--expert-profile", ".../Strata/data/expert-profile.bin",
    "--expert-cache", "64",
    "--prefill",     "auto",
    "--spec",        "2",
    "--mtp",         ".../Strata-data/mtp/rt",
    "--max-context", "524288",
    "--mmap-experts",
    "--vision"
  ],
  "tokenizer": ".../packs/q2_0/tokenizer",
  "model_name": "qwen3.8-flash-next-q2_0",
  "port": 8080,
  "backend": "metal",
  "env": { "STRATA_METAL_STREAM": "0" },
  "vision": {
    "exe": ".../build-vision/bin/strata-vision",
    "mmproj": ".../mmproj-Qwen3.8-Flash-Next-BF16.gguf",
    "gpu": true,
    "max_tokens": 1024
  }
}
</code></pre>
<p dir="auto">参数含义（按本机实测理解）：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>参数</th>
<th>作用</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>--native</code></td>
<td>37.6 GB 主文件被 Metal <strong>直接映射</strong>进统一内存（"wrapped"），专家权重不复制</td>
</tr>
<tr>
<td><code>--ple-gguf</code></td>
<td>28.8 GB 的 n-gram PLE 表，从 SSD 逐行读，不计入显存</td>
</tr>
<tr>
<td><code>--expert-cache 64</code></td>
<td>常驻 GPU 的专家槽位 64 个，仅 0.08 GiB；按路由频率排序，不淘汰</td>
</tr>
<tr>
<td><code>--expert-profile</code></td>
<td>24,576 个专家配对的排序表，决定哪些专家常驻</td>
</tr>
<tr>
<td><code>--spec 2</code></td>
<td>MTP 投机解码窗口 2（Mac 默认值）</td>
</tr>
<tr>
<td><code>--mtp</code></td>
<td>草稿层，实测 <code>drafts accepted 7 of 8</code></td>
</tr>
<tr>
<td><code>--max-context</code></td>
<td>上下文窗口，本机从 32768 逐步调到 <strong>524288</strong></td>
</tr>
<tr>
<td><code>--vision</code></td>
<td>图片输入开启（默认开）</td>
</tr>
</tbody>
</table>
<p dir="auto"><img src="https://lcz.me/assets/plugins/nodebb-plugin-emoji/emoji/android/26a0.png?v=ec85ec55bc1" class="not-responsive emoji emoji-android emoji--warning" style="height:1.4em;width:auto;vertical-align:middle" title="⚠" alt="⚠" />️ 524K 上下文时引擎的警告：</p>
<pre><code class="language-text">serve: 0 MiB of VRAM free with everything loaded - LOW: requests may stall;
  add --vram-reserve-mib 1212 to the config's args (or lower --max-context)
</code></pre>
<p dir="auto">另外 <code>memory guard: the available RAM cannot be read; parking and session save/restore are refused</code> —— 所以 Strata 侧没有 oMLX 那样的 <code>/admin/api/stats</code>，测试脚本无法采集内存峰值（报告里 <code>peak GiB</code> 为 <code>-</code>）。</p>
<hr />
<h2>五、测试工具</h2>
<p dir="auto">自写脚本 <code>scripts/local-test/context_capacity_probe.py</code>：</p>
<ul>
<li>扫描本机 OpenAI 兼容端口（8000 / 8080），列出在线模型供选择；</li>
<li>先做 <strong>校准</strong>（测 chat 模板开销与 tokens/字符比例，本次模板开销 72 tokens，filler 47 tokens/行）；</li>
<li>然后按 <strong>16K → 32K → 64K → 128K → 256K → 512K</strong> 阶梯上升；</li>
<li>每步 <code>max_tokens=16</code>，记录真实 <code>prompt_tokens / completion_tokens / prefill_ms / total_time / 墙钟时间</code>；</li>
<li>任一步失败（OOM、memory guard、超时、上下文超限、服务端截断）立即停止，不再试更高阶梯；</li>
<li>每次运行独立目录，不覆盖旧结果。</li>
</ul>
<p dir="auto">本次运行参数：<code>--mode ladder</code>，<code>--gen-tokens 16</code>，<code>--time-budget 480</code>，<code>--max-requests 20</code>，<code>--request-timeout 360</code>。</p>
<hr />
<h2>六、实测结果（run-20261020-201926-074430ec）</h2>
<ul>
<li>目标模型：<code>qwen3.8-flash-next-q2_0</code> @ <code>http://127.0.0.1:8080/v1</code></li>
<li>状态：<code>ladder_stopped_timeout</code>，总耗时 <strong>479.61 s</strong>，请求 10 条（9 成功 / 1 失败）</li>
</ul>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th style="text-align:right">阶梯上下文</th>
<th style="text-align:right">目标 prompt</th>
<th style="text-align:right">实际 prompt</th>
<th style="text-align:right">prompt 字符</th>
<th style="text-align:right">gen tokens</th>
<th style="text-align:right">prefill(ms)</th>
<th style="text-align:right">prefill tok/s</th>
<th style="text-align:right">total(s)</th>
<th>状态</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:right">16,384</td>
<td style="text-align:right">16,304</td>
<td style="text-align:right">16,286</td>
<td style="text-align:right">60,408</td>
<td style="text-align:right">16</td>
<td style="text-align:right">7,840.0</td>
<td style="text-align:right">2,077</td>
<td style="text-align:right">8.14</td>
<td>OK</td>
</tr>
<tr>
<td style="text-align:right">32,768</td>
<td style="text-align:right">32,688</td>
<td style="text-align:right">32,689</td>
<td style="text-align:right">121,483</td>
<td style="text-align:right">16</td>
<td style="text-align:right">16,048.3</td>
<td style="text-align:right">2,037</td>
<td style="text-align:right">16.26</td>
<td>OK</td>
</tr>
<tr>
<td style="text-align:right">65,536</td>
<td style="text-align:right">65,456</td>
<td style="text-align:right">65,448</td>
<td style="text-align:right">243,458</td>
<td style="text-align:right">16</td>
<td style="text-align:right">32,262.5</td>
<td style="text-align:right">2,029</td>
<td style="text-align:right">32.49</td>
<td>OK</td>
</tr>
<tr>
<td style="text-align:right">131,072</td>
<td style="text-align:right">130,992</td>
<td style="text-align:right">131,013</td>
<td style="text-align:right">487,583</td>
<td style="text-align:right">16</td>
<td style="text-align:right">66,416.4</td>
<td style="text-align:right">1,973</td>
<td style="text-align:right">66.69</td>
<td>OK</td>
</tr>
<tr>
<td style="text-align:right">262,144</td>
<td style="text-align:right">262,064</td>
<td style="text-align:right">262,049</td>
<td style="text-align:right">975,483</td>
<td style="text-align:right">16</td>
<td style="text-align:right">140,141.4</td>
<td style="text-align:right">1,870</td>
<td style="text-align:right">140.48</td>
<td>OK</td>
</tr>
<tr>
<td style="text-align:right">524,288</td>
<td style="text-align:right">524,208</td>
<td style="text-align:right">—</td>
<td style="text-align:right">1,951,633</td>
<td style="text-align:right">—</td>
<td style="text-align:right">—</td>
<td style="text-align:right">—</td>
<td style="text-align:right">210.54</td>
<td><strong>timeout</strong></td>
</tr>
</tbody>
</table>
<p dir="auto">关键指标：</p>
<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"><strong>262,144 tokens</strong></td>
</tr>
<tr>
<td>实测最大 prompt tokens</td>
<td style="text-align:right"><strong>≥ 262,049</strong></td>
</tr>
<tr>
<td>上下文可信区间</td>
<td style="text-align:right"><code>[262,049, 524,208]</code></td>
</tr>
<tr>
<td>prefill 吞吐中位数 / P95</td>
<td style="text-align:right"><strong>2,029 / 2,077 tok/s</strong></td>
</tr>
<tr>
<td>生成吞吐中位数</td>
<td style="text-align:right"><strong>78.7 tok/s</strong></td>
</tr>
<tr>
<td>最大单请求耗时</td>
<td style="text-align:right">210.54 s</td>
</tr>
<tr>
<td>请求体总字节</td>
<td style="text-align:right">3,853,524 B</td>
</tr>
<tr>
<td>缓存命中 token</td>
<td style="text-align:right">0（每阶梯都是新会话）</td>
</tr>
</tbody>
</table>
<p dir="auto">引擎侧对应日志（同一请求）：</p>
<pre><code class="language-text">prompt 262049 tokens = 0 reused + 262049 read in 140141 ms (1869.9 tok/s),
  16 generated in 203 ms (78.7 tok/s), drafts accepted 7 of 8, 6 checkpoints
prompt 524215 tokens = 0 reused + 524210 of 524215 read in 310525 ms (1688.1 tok/s),
  0 generated in 2 ms (0.0 tok/s) (cancelled)
</code></pre>
<hr />
<h2>七、结果解读</h2>
<p dir="auto"><strong>1. 262K 是真跑通的，不是"声明支持"。</strong><br />
服务端 <code>/health</code> 声明 <code>max_context: 524288</code>，但声明不等于可用。实测 262K 完整 prefill + 生成 16 token，没有任何截断或报错。</p>
<p dir="auto"><strong>2. 512K 失败是"时间预算"问题，不是模型拒绝。</strong><br />
失败类型是 <code>Timeout: TimeoutError</code>，HTTP 状态 <code>-1</code>（客户端侧），而不是服务端返回 400/500。整轮运行耗时 479.61 s，正好撞上 <code>--time-budget 480</code> 的全局预算，所以这条请求在 <strong>210.5 s</strong> 处被客户端看门狗中止；引擎日志显示该请求的 prefill 推进到 <strong>524,210 / 524,215 tokens</strong>，累计 <strong>310.5 s（1,688 tok/s）</strong> 后才被标记为 <code>cancelled</code>。<br />
→ 把 <code>--time-budget</code> 提到 900 s、<code>--request-timeout</code> 提到 600 s，512K 大概率能跑通。</p>
<p dir="auto"><strong>3. prefill 吞吐随上下文下降约 10%。</strong><br />
2,077 → 2,037 → 2,029 → 1,973 → 1,870 tok/s。16K 到 262K 只降 10%，说明长上下文没有明显的平方级恶化（MoE + PLE 的读取走 SSD，专家命中走 GPU）。</p>
<p dir="auto"><strong>4. 真正的瓶颈是显存余量。</strong><br />
32K 上下文时 <code>10273 MiB of VRAM free</code>；524K 时 <code>0 MiB of VRAM free</code>，引擎直接提示"requests may stall"。64 GB 统一内存跑 Q2_0（官方建议 64 GB 起）在 512K 上是<strong>刚好卡在边界</strong>。</p>
<p dir="auto"><strong>5. KV 缓存复用效果非常明显。</strong><br />
同一会话重复请求时，日志出现：</p>
<pre><code class="language-text">prompt 262132 tokens = 262127 reused + 5 read in 25 ms (197.0 tok/s)
</code></pre>
<p dir="auto">262K 上下文从 140 s 降到 <strong>25 ms</strong>。阶梯测试每步都是新会话，所以 <code>cached_tokens = 0</code>；日常多轮对话的实际体验远好于阶梯数字。</p>
<p dir="auto"><strong>6. 生成速度稳定。</strong><br />
带 MTP（<code>--spec 2</code>）实测 79–89 tok/s，草稿接受率约 7/8。</p>
<hr />
<h2>八、复现命令</h2>
<pre><code class="language-bash"># 1) 启动服务
cd /Users/snow/local-ai/Strata/Strata
./run-q2_0.sh

# 2) 健康检查
curl http://127.0.0.1:8080/v1/health

# 3) 阶梯实测
cd /Users/snow/Documents/workspace
python3 scripts/local-test/context_capacity_probe.py --list
python3 scripts/local-test/context_capacity_probe.py --select 2

# 4) 想跑满 512K，把预算放宽
python3 scripts/local-test/context_capacity_probe.py \
  --select 2 --time-budget 900 --request-timeout 600 --max-requests 12
</code></pre>
<hr />
<h2>九、给同样配置的人的建议</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>场景</th>
<th>建议</th>
</tr>
</thead>
<tbody>
<tr>
<td>64 GB M5 Max，日常使用</td>
<td><code>--max-context 262144</code>，稳；实测 262K 无压力</td>
</tr>
<tr>
<td>想试 512K</td>
<td>保留 <code>--vram-reserve-mib 1212</code>，并把客户端超时/预算放宽到 600–900 s</td>
</tr>
<tr>
<td>磁盘</td>
<td>至少预留 80 GB。本机模型放在内置 SSD（剩余 618 GB），外接 4 TB SSD 存放 oMLX 的模型</td>
</tr>
<tr>
<td>多轮长对话</td>
<td>开启缓存复用，实际首 token 延迟远低于阶梯测试值</td>
</tr>
<tr>
<td>想要更高质量</td>
<td>官方文档：64 GB 内存 Q2_0 / IQ2_XS / IQ3_XXS 都能装，但 IQ3_XXS 需要关闭浏览器并把上下文控制在 128K 以内；IQ3_S 建议 96 GB 起</td>
</tr>
</tbody>
</table>
<hr />
<h2>附：数据来源</h2>
<ul>
<li>硬件：<code>system_profiler SPHardwareDataType</code> / <code>sysctl</code> / <code>diskutil</code></li>
<li>服务元数据：<code>/v1/health</code>、<code>/v1/models</code>、<code>strata-q2_0.json</code>、<code>build-metal/BUILD.json</code></li>
<li>引擎日志：<code>Strata/strata-q2_0.log</code></li>
<li>测试报告：<code>scripts/local-test/results/run-20261020-201926-074430ec/summary.md</code>（另有 <code>result.json</code> / <code>probes.csv</code> / <code>probes.jsonl</code> / <code>meta.json</code>）</li>
<li>复现性：20:27 的第二轮（<code>run-20261020-202748-1342eaf6</code>）得到同样的结论——256K 成功、更高阶梯超时。</li>
</ul>
]]></description><link>https://lcz.me/topic/2475</link><generator>RSS for Node</generator><lastBuildDate>Sun, 25 Oct 2026 00:56:32 GMT</lastBuildDate><atom:link href="https://lcz.me/topic/2475.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 21 Oct 2026 01:37:49 GMT</pubDate><ttl>60</ttl></channel></rss>