← 記事に戻るDecode speed by configuration (tok/s, M1 Ultra, 27B-4bit)
GPU active residency during decode (powermetrics, %)
発見
Copy article
Qwen 3.8-27B M1 Ultra 上で: 12.1から20.3まで tok/s すべてを測定して
5つの制御実験でQwen 3.8-27Bを128 GB M1 Ultra上で実行:scheduler QoS pinning、MTP speculative decoding、GGUF challenger、そしてMoEがdispatchオーバーヘッドで失敗したもの — Kimi K3で高い思考モードで実行し、各呼び出しのpowermetrics証拠を添付。
Developed by Robert E. Beckner III (Merlin) | rbeckner.com
Qwen3.8-27B の重みは朝に着地し、同じ日に Kimi K3 とともにハイ・シンキングモードで冒険を始めました。 私は一つの質問で全てを開始しました:この新鮮で密度の高い27B ― そのサイズクラスで最も強力なオープンモデルであることは明らかです ― が、Mac Studio の M1 Ultra、20 CPU コア、128 GB の統合メモリ、そして 800 GB/s のメモリ帯域幅を備えた環境で実際の速度で私のコーディングエージェントをサポートできるかどうかです? 一般知識では、密度の高いモデルは Apple Silicon 上で遅くデコードするのはメモリ帯域幅に制限されているためだと言われていますが、私はこの量の RAM と帯域幅がパターンを破るかどうかを知りたかったです。 4-bit の MLX 重みは 15 GB に達し、フレームワークは最新で、ボックス上で他に何も動いていなかったため、最初の数値は 12.1 トークン/秒 でした。 それは間違っていると感じました。
私はしばらくこの種の実験を回っていました。 3 月に、別の AI と自律改良ラボで作業していたとき、M4 Max 上の 30B モデルで 20 トークン/秒未満の壁を OS レベルのページングによる帯域幅飢餓と追跡し、その調査はプレイブックを残しました:
powermetrics まず、クラスターごとのサンプリング、メモリピンニングを行い、責任を追及する前に。 今回の実行は純粋な好奇心から始まりました:私は Qwen3.8 の最適化について聞いており、このマシンでこの量の RAM を備えてボックスから高速で動作するかどうかを知りたかったのです。実験の途中で帯域幅制限の現実が自覚されました。 その後に続いたのは、私たちが一緒に設計した制御実験のスプリントでした — Kimi が仮説を作成し、私の側でハードウェアカウンタを読み取り、私は金属に手を置き続けました。各実験はスタックの単一レイヤーを有罪または無罪にするように構築されていました。 勝利は 2 の場所から来ました。ローカル推論のフォークロアでは過小評価されるもの:CPU スケジューラのヒントと投機的デコード。 2 の流行の代替手段 — llama.cpp によって提供される GGUF ビルド、そして紙上では圧倒的に見える専門家混合モデル — は両方とも測定で失敗しました。 この記事は、私たちが一緒に構築した完全な証拠トレイルです。方法は単一の数値よりも価値があると判明しました。ネットワークリレーとサーバーが最初の疑いの対象であり、両方とも無罪でした。
サービングパスは 3 つのホップを持っていました:私のワークステーション、SSH ベースの実行リレー、そしてスタジオのループバック上のモデルサーバー。 リレーを非難するのは簡単だったでしょうが、まずそれを測定しました。 サーバー自身のタイミングは 12.1 tok/s のデコードを示しました。サーバーもリレーもない状態での生のインプロセス生成ベンチマークは 11.5 tok/s を生成しました。 伝送は接続ごとのオーバーヘッドで約 25% を費やしており、モデル自体が遅い層でした。
1 つの伝送バグは修正する価値があり、見たことがないと数時間かかるような詳細です:バッファ付き
read(65536) を使用する Python TCP リレーは、チャッティなローカルプロトコルに対してデッドロックします。バッファリーダーは完全なバッファまたは EOF を待ってから返すためです。 単一の基礎読み取り後に返す read1() に切り替えると、リレーの動作が改善しました。 症状はネットワークスタールのように見えましたが、原因は stdio のセマンティクスでした。伝送が除外されたので、通常の sysctl レイヤーを通じて作業しました。 GPU の有線メモリ制限(
iogpu.wired_limit_mb)を上げても、128 GB の RAM が空いている状態では何も変わらず、したがってそれを元に戻しました。 Python プロセスはネイティブ arm64 で、MLX は GPU をデフォルトデバイスとして報告し、powermetrics はデコード中に 20-23 W を消費しながら 54-62% のアクティブレジデンシーで GPU を表示しました。 このラウンドのすべての疑いは無罪で終わりました ― それ自体が有用な結果であり、調査を CPU に向けることを示しました。スケジューラは推論を効率コアに停止させていました
マシンごとではなくCPUクラスターごとに
powermetricsを読むことで、最初の実際の発見が露呈しました。 デコード中、効率クラスターは75-93%の稼働率で動作し、パフォーマンスクラスターは1-12%でアイドル状態でした。 SSHを超えて起動されたものは、macOSが低優先度作業として読み取る品質保証クラスを継承し、スケジューラはそのヒントを尊重して遅いコアでレイテンシークリティカルなワークロードを保持していました。修正は1行のctypesで、モデル重みのロード前に実行されました:
python
import ctypesctypes.CDLL("libSystem.B.dylib").pthread_set_qos_class_self_np(0x21, 0) # QOS_CLASS_USER_INTERACTIVE
そのピンと、完全なビジョンスタックではなく
mlx-lmを介してモデルのテキストタワーをロードすることで、rawデコードは11.5から15.1 tok/sに移行しました — スケジューラ配置とより軽量なローダーによる31%の向上で、モデルには変更がありませんでした。 後で、ピンの到達範囲には制限があることが分かりました:それは呼び出しスレッドを移動させ、MLXのワーカースレッドは独自のスケジューリングクラスを保持します。 このモデルでは、メインスレッドが十分な作業を担っていたため重要でした。推測デコードは sysctl ができなかったジャンプを実現しました
最大の単一の勝利は、ベースモデルがすでに所有していた機能から得られました。 Qwen3.8 はマルチトークン予測ヘッドを備えており、数トークン先をドラフトする小さな補助モジュールです — MLX コンバータは変換中に静かにそれらの 15 テンソルをドロップします。 コミュニティパッケージはヘッドをスタンドアロンの 253 MB ドラフターとして再ホストし、訓練時に共に使用されたモデルと再ペアリングできました。
サービングパターンはドラフト→検証です:ドラフターが数トークンを提案し、完全モデルが 1 パスでそれらをチェックし、受理されたトークンはすべてカウントされます。 サーバーで
--draft-model と --draft-kind mtp を使用すると、ドラフト受理は現実的なコーディングとチャットプロンプトで 94% を測定し、デコードは 15.1 から 20.3 tok/s(サーバー側)へ、リレーを通じて 13.4 tok/s(エンドツーエンド)へ、9.0 から増加しました。 GPU は確認ストーリーを語りました:77% アクティブレジデンシー、すべてがフル 1296 MHz で、48 W を消費し、パフォーマンスクラスターは 97% が で稼働していました。 Prefill は同じアップグレードで改善され、14.7 tok/s から 18-55 へ、プロンプト形状に応じて変化しました。Chart data
| MLX stack | llama.cpp Q4_K_M | |
|---|---|---|
| raw stack | 11.5 | 9.2 |
| + text tower | 13.6 | |
| + QoS pin | 15.1 | |
| + MTP drafter | 20.3 | 12.2 |
GGUF チャレンジャーは 40% で敗れた
コミュニティ投稿は llama.cpp が推測ドラフトでこのモデルクラスの 25-32 tok/s を達成したと示している 1 Ultra で、私たちの MLX 数値よりも快適に先行しているため、チャレンジャーに公平なリングを与えた:公式 Q4_K_M GGUF、マッチング MTP-のみドラフトモデル、そして Metal アクセラレーションがアクティブであることが確認された現在の llama.cpp ビルド。 GGUF レーンは 9.2 tok/s ベースラインと 12.2 でドラフトを測定し — それは 40% MLX スタックよりも遅れ、意図されたデスティネーションを奪うべきだった。
llama.cpp は優れたエンジニアリングを維持している;ギャップはおそらく各ランタイムの Metal カーネルがこのチェックポイントをこのチップでどのように処理するかにある。 耐久性のある教訓は単純だ:誰かが自分のマシン、ビルド、チェックポイントで測定した数値は、あなたのものに関する仮説である。 18 GB のチャレンジャー重みは同じ午後にマシンを離れ、50 MB llama.cpp バイナリは将来の再対戦のために残った。 私は以前にこのルールについて書いたことがある benchmark-driven development — それは SEOReport from heuristics to a product を運んだ — そしてここでそれはマイグレーションを救った。
3B-アクティブ MoE は勝つべきだった、そしてGPUメーターが損失を説明した
最後のチャレンジャーは最も強力な理論を持っていた — 私たちが最初にテストしようとした同じ一般知識。 密集モデルはAppleシリコンで遅くデコードする。生成されるすべてのトークンがほぼすべての重みを読むために支払う。35B総パラメータのMixture-of-Expertsモデルはトークンあたり約3Bしか活性化しないので、帯域幅制限のあるマシンではデコードが密集27Bより数倍速くなるはずで、各トークンは重みの約11%を読む。 私たちは4ビット MoE とその対応するMTPドラッファーをダウンロードし、サーバーをウォームアップし、14.7 tok/sの生速度を測定した:それは屈辱されるべきだった密集モデルと同じ速度だった。 推測デコードで現実的なプロンプトで19 tok/s、非常に予測可能なテキストで26.3に達した — 密集モデルの20.3に対しては引き分けで、品質の議論で勝負を決める根拠はなかった。
powermetrics は1サンプルでレジームを特定した。 MoE デコード中、GPUは0-3%のアクティブレジデンシーで、効率クラスタは60-90%で動作した。 モデルはトークンあたりの予算をCPU側の作業に費やし、オペレーションレベルのタイミングが理由を示した:各ディスパッチ操作は50-100マイクロ秒のオーバーヘッドを費やし、このハイブリッドアーキテクチャ — GatedDeltaNet 線形注意と小さな2048幅の隠れ状態の背後に256の専門家 — は40層でレイヤーあたり約78オペレーションを発行する。 バッチサイズ1で、GPUはCPUが次のカーネルをキューに入れる前に各小さなカーネルを終了する。 マシンはディスパッチバウンドで、ディスパッチバウンドワークロードはトークンあたりの重みを減らしても利益を得られない。Diagram source
graph TB
A[遅いデコード
バッチ1] --> B{GPUバッシー
デコード中?}
B -->|はい| C[帯域幅バウンド
バイト数が少ないほど勝つ]
B -->|いいえ| D[ディスパッチバウンド
オペレーション数が少ないほど勝つ]
C --> E[MoEは助ける
小さい量子化が助ける]
D --> F[推測デコード
最も効果的]
style E fill:transparent,stroke:#10B981,stroke-width:2px
style F fill:transparent,stroke:#3B82F6,stroke-width:2pxループを閉じるために、GPUパス自体が健康であることを合成ホグで証明した:8192³行列乗算ループはbfloat16で10.8 TFLOPSに達し、GPUは97-100%のレジデンシーと68 Wを示した。外部証拠はローカル診断と一致し、独立した推定はこのMoEクラスをM2 Ultraで約21.7 tok/sに位置付け、OpenVINO問題は同じモデルが弱いディスパッチパスを持つバックエンドで密集8Bに敗れることを文書化している。 密度の高い27BとそのMTPドラフターは生産スロットを保持し、38.5 GBのMoEウェイトは同じ晩に削除された。
Chart data
| GPU active residency (%) | |
|---|---|
| dense 27B + MTP | 77 |
| MoE 35B-A3B | 2 |
| matmul hog test | 100 |
5制御実験が残したもの
マシンは現在Qwen 3.8-27Bを20.3トークン/秒でサーバー側で提供しており、当初より68%改善され、より耐久性のある収益は将来のすべてのボックスで再利用するチェックリストだ:
- バッチサイズ1でのデコードは2つのレジーム、帯域幅制限とディスパッチ制限があり、2秒の
powermetricsサンプルが誤った修正にダウンロードを費やす前にあなたのものを特定する。 - 推測デコードは単一ユーザーのボックスにとって最高レバレッジのサービスノブだ。 ここに34%を追加し、他のすべての最適化と合成される。検証バッチはGPUを稼働させ、ドラフターはアイドルギャップを吸収する。
- スケジューラQoSはmacOSでの実際の推論パラメータだ。SSHを超えて起動されたものはスレッドを意図的にピン留めすべきで、ピンの効果は雰囲気ではなくクラスターごとに検証可能だ。
- コミュニティのスループットの主張はチェックポイント、ビルド、チップ間でうまく伝わらない。 ローカルベンチマークは移行よりも安価だ。
- 削除はワークフローの一部だ。 失敗したすべての挑戦者はその日中にディスクを離れ、次の実験を正直に保ち、マシンをスリムに保つ。
この冒険の満足できる部分は、答えがすべてハードウェアカウンタにあり、誰かが正確な質問をするのを待っていたことだ――そして今回は一緒に尋ねた。 測定したローカルモデルは推測したより大きなモデルより価値がある――local AI gains as infrastructureを扱うことで得られる同じ複利リターンを得る。 重みが着地した朝に全体を開始し、Kimi K3はすべての実験、すべてのカウンタ読み取り、そして同じ夜のラボノートからのこの書き込みに対して闘い続けた。 次の実験はすでにキューに入っている:コンパイルされたデコードグラフはMoE判決を決定したオペレーションごとのディスパッチコストを縮小することを約束し、MLXリリースが着地すると、再戦は午後と1回のダウンロードで済む。
#AI#apple-silicon#benchmarking#local-inference#mlx#performance#experiential#insights
Apple Silicon inference, measured
Qwen 3.8-27B M1 Ultra 上で: 12.1から20.3まで tok/s すべてを測定して
MTPLX 上で M1 ウルトラ: その 25 トーク/ス 調整 その 提供した 16.5