# GPUを忙しくするだけでは速くならない — M4で測ったDFlashと有効tokenの最適点

測定日：2026-09-07。公開時点の運用者自身による探索報告。

## 結論：単一要求では幅8〜10が有望だった

Apple M4・Qwen3-4B BF16で162件の主測定を行った。今回の単一課題では、DFlashのblock幅8〜10が有効出力の速い領域だった。参考rooflineに合わせて幅40へ増やすと、演算量は増えても出力速度は低下した。これは共有Macでの探索結果であり、GPUの理論上限や全課題に共通の最適値ではない。

## 何を成功と数えたか

主指標は最終的に出力されたtokens / GPU-second。1 GPU上のdecode wall-clock時間で計算し、prefillと最初のtokenは測定区間から除いた。GPU active-time counterではない。利用率80%そのものは成功条件にせず、採用token当たりの計算量と待ち時間も併記した。

## ハードウェアと測定条件

M4、10 GPU cores、32 GiB unified memory、MLX 0.32.2、mlx-lm 0.31.3。Apple公称メモリ帯域は120 GB/s。今回の再校正ではBF16 4096角の行列積が2.712 TFLOP/s、配列加算の論理帯域が56.18 GB/sだった。この比48.28 FLOP/byteは参考値であり、DRAMカウンタから求めたridge pointではない。前回は約2.91 TFLOP/s・75 GB/sで、共有負荷による変動もある。

## 単一要求：投機幅を増やしても有効出力は増えない

二分探索を説明する同じpromptからgreedyで256 tokensを生成し、255 tokens分のdecodeを計測した。広域探索の中央値はAR 6.66、幅8が14.05、幅16が8.88、幅40が5.06、幅64が4.59 tokens/GPU秒。幅40では出力1 tokenにつきtarget位置を13.56個処理し、幅8の2.34個を大きく上回った。幅16を超える条件はdraftの学習block幅外である。

## 幅8と10の差を最適値と断定しない

別の2反復ではAR 7.99、幅8が15.15、幅10が15.25、幅12が13.00 tokens/GPU秒だった。8と10の差は約0.6%で、反復差より小さい。さらに別の2反復で幅5/10/15を比較し、11.06/14.26/9.92、対照ARは6.06だった。幅10のAR比は比較群により約1.9〜2.35倍。異なる時点の値を混ぜて唯一の最適幅を選んでいない。

## 出力一致と無駄な計算

投機生成26回すべてで256 token全体が同じ反復のARに一致した。これは今回の1課題についての一致であり、一般的な品質保証ではない。幅を増やすほどtargetの推定演算速度が上がる一方、有効出力は下がった。余剰FLOPsは単純ARに対するtarget密行列演算の増分で、draftやattentionを含む全GPU FLOPsではない。

## 実モデルの行列形状が重要

実BF16 weightを使った4形状・M=1〜1024の測定では、M=40で0.31〜0.90 TFLOP/sだった。測定範囲内の最大値はLM headがM=128、MLP gateが256、MLP downが512、q_projが1024に分かれた。各呼出しの同期・launch費用も含むため、モデル全体の非同期実行とは異なる。AI≈Mという単純近似だけで最適幅を決められない。

## 実装の境界を仮説に使う

MLX v0.32.2のgemv_wide_configには、条件を満たす行列について最大5 vectors/pass・3 passesの経路があり、M=16から対象外になる。この公開ソースを手掛かりに5/10/15を追加した。ただし実際に選択されたkernel名は追跡しておらず、減速原因をこの分岐だけに帰していない。

## 複数要求：本当に必要なtokensをbatchへまとめる

異なる配列の例題を複数要求として与えた同期ARでは、batch 40で95.11、batch 64で128.34 tokens/GPU秒だった。各要求64出力のうち63出力を測定した。先頭要求は元の2反復18条件でbatch 1と一致したが、全要求の回答品質は評価していない。DFlash試験とは長さとruntimeが異なり、両者の数字を直接speedupとして比べない。

## 待ち時間を含む条件付きの候補

観測した全反復でp95 stepが200 ms以内だった条件の最高throughputはbatch 4の30.62、500 ms以内ではbatch 40の95.11、1秒以内ではbatch 64の128.34 tokens/GPU秒。batch 40のp95は499.6 msで境界に近い。batch 64のp95は629.8 ms、prefill＋最初のtokenは中央値29.69秒。これは到着済みfull batchの容量試験で、要求が揃うまでのqueue待ちは含まない。

## 動的制御は採用数と所要時間から選ぶ

簡単なbatch=1 simulationでは、独立で一定の採用確率pを仮定し、期待排出数sum(p^i, i=0..K-1)を実測1ラウンド時間で割って幅を選んだ。広域探索のcostではp=0.2でAR、0.4〜0.9で幅8、0.95以上で幅64。ただし高幅でその採用率を実現した測定ではなく、pを変えてもcost一定という仮定がある。queueやlatency制約を備えた実運用schedulerは未実装。

## 測定の限界と再現資料

主データはGEMM 64件、target forward 38件、decode 32件、AR batch 28件。メモリ保持設定の差を見つけ、初期のunwired測定を参考扱いに隔離し、本文のGEMM・target・ARは公式生成と同じwired_limitで測り直した。他の作業は停止せず、load averageが100を超えた観測もある。実DRAM帯域、Tensor/SM利用率、実MFU、50/70/80%到達のM、dLLM/treeとの実測比較は未取得。この結果をMurakumo本番サービスの速度保証やNVIDIA GPUの結果とは扱わない。

## 図とデータ

- [gemm-roofline.png](https://murakumo.cloud/research/m4-roofline-2026-09-07/gemm-roofline.png)
- [decode-tradeoff.png](https://murakumo.cloud/research/m4-roofline-2026-09-07/decode-tradeoff.png)
- [ar-throughput-latency.png](https://murakumo.cloud/research/m4-roofline-2026-09-07/ar-throughput-latency.png)
- [gemm.csv](https://murakumo.cloud/research/m4-roofline-2026-09-07/gemm.csv)
- [target.csv](https://murakumo.cloud/research/m4-roofline-2026-09-07/target.csv)
- [decode.csv](https://murakumo.cloud/research/m4-roofline-2026-09-07/decode.csv)
- [ar-batch.csv](https://murakumo.cloud/research/m4-roofline-2026-09-07/ar-batch.csv)
- [calibration.json](https://murakumo.cloud/research/m4-roofline-2026-09-07/calibration.json)
- [method.json](https://murakumo.cloud/research/m4-roofline-2026-09-07/method.json)
- [validation.json](https://murakumo.cloud/research/m4-roofline-2026-09-07/validation.json)
- [scheduler-simulation.csv](https://murakumo.cloud/research/m4-roofline-2026-09-07/scheduler-simulation.csv)

## 出典

- [Apple M4 Air仕様](https://support.apple.com/en-us/122209)
- [MLX v0.32.2 Metal matmul](https://github.com/ml-explore/mlx/blob/v0.32.2/mlx/backend/metal/matmul.cpp)
- [DFlash](https://github.com/z-lab/dflash)
- [Draft block 16](https://huggingface.co/z-lab/Qwen3-4B-DFlash-b16)
