ローカルLLMの新しい推論エンジンやモデルを試した際、ブログやSNSに「M1 Macで 8.5 tok/s 出ました!」といった測定結果を投稿したり、社内の技術選定資料にまとめた経験はないでしょうか。

その測定、本当に何回か測って確認した数値でしょうか?

多くの開発者コミュニティやベンチマーク手順では、「1回のウォームアップ(計測破棄)を行った後、本計測を1回実行する」という手順が一般的です1。しかし、この「warmup 1回+本計測1回」で得られた単一の数値(single number)を「そのマシンの絶対的な推論速度」として報告することには、大きな罠が潜んでいます。

自分の手元で出た値と他人の報告値が食い違ったとき、私たちはつい「機体差」や「個体差」という言葉で納得しがちです。しかし実際には、同一のマシン・同一の入力プロンプトであっても、1回測定の数値は大きく揺らぎます。

この記事では、同一環境で入力条件を揃えて 16 回連続測定した実測データをもとに、なぜ1回測定が危険なのか、そして今後どのように計測・報告すべきかを解説します。

16ランの実測データが示す「2.77倍ブレ」の現実

まずは、実際に同一の Mac 上で入力条件を完全に固定し、16 回連続で推論を走らせた結果をご覧ください。

前回の記事 で検証した TurboFieldfare エンジンを用い、MacBook Pro(M1 Pro 8コア / RAM 16GB / macOS 26.5.2 / 内蔵 512GB SSD)上で Gemma 4 26B-A4B 4bit モデル(実測 14.29GB)を動かした際の記録です。入力プロンプト(prefill 61 tokens)、生成上限(511 tokens)、サンプリングパラメータ(Temperature=0.2, top-k=64, top-p=0.95, context=4096)はすべて全ランで厳格に統一しています。

16 回の測定結果を集計すると、以下のようになりました。

  • サンプル数 ($n$): 16
  • 最小速度: 4.298 tok/s
  • 最大速度: 11.884 tok/s
  • 最速 ÷ 最遅: 2.77倍
  • 中央値 (Median): 9.495 tok/s

まったく同じプロンプトを同じマシンに投入しているにもかかわらず、推論速度は 4.298 tok/s から 11.884 tok/s まで 2.77 倍も動揺 しました。

時系列の推移を辿ると、さらに興味深い傾向が見えてきます。

時刻tok/s状態・備考
12:1610.124インストール直後の初回実行
12:3711.88416ラン中の最高速
12:409.921
12:454.29816ラン中の最低速
12:506.666連続実行ブロック
12:525.281連続実行ブロック
13:1110.63015分アイドル後(計装あり)
13:1211.19115分アイドル後(計装あり)
16:23〜16:318.729 〜 9.8313時間10分空けた後の8連続実行(平均 9.36 tok/s)

12:37 に 11.884 tok/s を記録したわずか 8 分後の 12:45 には、4.298 tok/s まで落ち込んでいます。もし開発者が 12:37 の 1 回測定だけで「11.9 tok/s 出る」と社内に報告していたら、あるいは 12:45 の 1 回測定だけで「4.3 tok/s しか出ない遅いエンジンだ」と判断していたら、どちらも真実の半分しか捉えていないことになります。

先行報告値との比較

この実測データは、オープンソースコミュニティにおける先行報告と突き合わせることで、さらに味わい深くなります。

例えば、GitHub の Issue #37 で報告されている同型機(M1 Pro 16GB)での測定値は 9.477 tok/s でした2。本計測の 16 ラン中央値(9.495 tok/s)や後半 8 ランの平均値(9.36 tok/s)と見事に合致しています。報告者は非常に誠実な計測を行ったと考えられます。しかし、単発の測定で偶然 4.3 tok/s や 11.9 tok/s を引き当てて報告していた可能性も否定できません。

また、M4 Mac mini(16GB RAM / 256GB SSD)のユーザーコミュニティでは、ある報告者が「5 tok/s 程度しか出ない」と述べたのに対し、別の報告者(Issue #23)が「8.43〜11.38 tok/s 出ている」と返し、議論が平行線になる事例が起きています3。同一型番・同一ストレージ容量であっても、測定タイミングや試行回数によって見えている数値が2倍以上食い違う典型例です。

ブレの要因を探った記録と探求の限界

「なぜ同じ入力なのに 2.77 倍もブレるのか?」の原因を突き止めるべく、考えられる仮説をひとつずつ検証しました。

1. スワップ説(否定)

物理メモリを超えたことによるスワップ増大(Swap death spiral)が原因ではないかと疑いましたが、これは明確に否定されました。

推論中の Peak RSS は 1,521.5 〜 1,551.3 MB で安定して常駐し、計装を行った 4 ランの Swap Used は 1061.38 → 1053.38 MB(むしろ 8MB 減少)で、スワップの増加はゼロ でした。物理メモリ枯渇による書き込みスパイクは発生していません。

2. 空きRAM説(説明不能)

次に「他のプロセスがメモリを圧迫して空きRAMが減ったのではないか」と疑いましたが、空きRAM量と tok/s には直感的な相関がありませんでした。

  • 空きRAM 1.1GB(69,872 pages)時 → 10.630 tok/s(高速)
  • 空きRAM 3.4GB(219,595 pages)時 → 11.191 tok/s(最高速クラス)
  • 空きRAM 3.0GB 前後推移時 → 4.298 tok/s(最低速が発生)

空きRAMが多いから速い、少ないから遅い、という単調な関係にはなっていません。macOS では、Pages free にファイルキャッシュ(file-backed pages)が含まれないため、空きページ数が少ないことはむしろ「ファイルキャッシュが充足している」ことを意味する場合があります。作者自身も Show HN のコメントで「メモリ圧迫時に 35 tok/s から 27 tok/s に落ちた」と述べており、ページキャッシュの充足度が大きく影響していることが分かります4

3. サーマル(熱)説(判定不可能)

「連続実行による熱スロットリングではないか」を検証するため、sudo powermetrics を走らせて 6 分 06 秒間(74サンプル)の CPU/GPU 熱動態を記録しました。

Thermal Pressure Level は 74 サンプルすべてで Nominal(正常)であり、警報は一度も出ませんでした。GPU P-state も全サンプルで最上段の 1296 MHz に到達しており、クロックの上限自体は解放されていました。HW Active Frequency の微減(644.9 → 615.3 MHz, -4.1%)と tok/s の微減(9.359 → 8.796 tok/s, -6.0%)の方向性は一致したものの、観測窓の 6 分間では 4.3 tok/s の低速フェーズが発生しなかったため、サーマル要因の完全な肯定も否定もできませんでした。

4. I/Oオフロードと構造的待機

SSD オフロード型の推論エンジンでは、GPU 計算と SSD からの重み読み出しが交互に実行され、互いの完了を待つ短時間の待機(brief idle periods)がトークンごとに発生します5。MoE(Mixture of Experts)モデルの SSD オフロード推論に関する学術論文(arXiv:2508.06978)でも、Decode ステージでのトークンあたりエネルギーが HBM 比で 3.8〜12.5 倍に増大することが示されています6

ファイルキャッシュの乗り具合、SSD 読み出しのわずかなレイテンシ変化、GPU の周波数遷移タイミングが複雑に噛み合うことで、この大きな振れ幅が生じていると考えられます。そして重要なのは、エンドユーザーが日常の Mac 環境でこの原因を100%特定しコントロールすることは実質不可能 という点です。

採用すべき計測手順と標準報告テンプレート

ブレの原因を完全に制御できないからこそ、私たちが取るべきアプローチは「1回の結果で一喜一憂するのをやめ、統計的かつ再現可能な手順で計測・報告する」ことです。

ベンチマーク計測の4原則

今後ローカルLLMの性能を測る際は、以下の4原則を徹底することを推奨します。

  1. ウォームアップ除去: 初回のモデルロードやコンパイルを含む 1〜2 回の実行データは必ず計測結果から破棄する。
  2. 複数回試行(Minimum 5 runs): ウォームアップ除去後、最低 5 回(できれば 10 回以上)の試行を行い、外れ値を平滑化する。
  3. 測定条件の厳格な固定: 入力プロンプト長、生成トークン上限、サンプリング設定(Temperature=0 または固定値, top_p, top_k)、コンテキスト長を明記・固定する。
  4. Prefill(TTFT)と Decode(tok/s)の分離: 初頭応答時間(Time to First Token: TTFT)と、トークン生成速度(Decode tok/s)を分けて評価する7

ローカルLLM性能報告テンプレート

社内資料や技術ブログで推論速度を報告する際は、以下のフォーマットのように「中央値」と「レンジ(最小〜最大)」を併記してください。

### ローカルLLM 推論パフォーマンス報告

#### 1. 測定環境
- **OS / 機種**: macOS 26.5.2 / MacBook Pro (M1 Pro, 16GB RAM)
- **ストレージ**: 内蔵 Apple NVMe SSD (512GBクラス)
- **推論エンジン**: TurboFieldfare v0.x (Release Build)
- **対象モデル**: Gemma 4 26B-A4B 4-bit (14.3GB)

#### 2. 測定条件
- **試行回数**: 5回(ウォームアップ1回破棄)
- **プロンプト長 / 生成トークン数**: 61 tokens / 511 tokens
- **サンプリング設定**: Temperature=0.2, Top-P=0.95, Top-K=64
- **バックグラウンド**: アイドル状態

#### 3. 測定結果
| メトリクス | 中央値 (Median) | レンジ (Min - Max) | 備考 |
|---|---|---|---|
| **Decode Speed** | **9.50 tok/s** | 4.30 - 11.88 tok/s | 16ラン連続計測時 |
| **TTFT (初頭応答時間)** | **10.45 sec** | 10.20 - 10.70 sec | Prefill 61 tokens |
| **Peak RSS (メモリ)** | **1.53 GB** | 1.52 - 1.55 GB | 常駐メモリ |
| **Swap 増加量** | **0 MB** | 0 - 0 MB | 増加なし |

自動計測ツールの活用

llama.cpp コミュニティが提供する llama-bench などの標準ツールを使用する場合は、-r オプションで複数回試行を指定し、JSON 出力で分散を集計するのが効果的です8

# llama-bench を用いた 5回試行の自動集計例
./llama-bench -m models/gemma-26b-q4.gguf -p 512 -n 128 -r 5 -o json > benchmark_result.json

結論 ── 単一の数字から「分散の報告」へ

ローカルLLMの実効速度を考える際、用途によって求められる速度の基準は異なります。

一般に、人間が画面上のテキストを無理なくストレスなく読む速度の目安は 7〜8 tok/s と言われています9。本計測の中央値である 9.5 tok/s であれば、インタラクティブなチャットや要約用途として十分に実用的です。しかし、下振れして 4.3 tok/s になった瞬間、読書速度を下回り体感待機時間が急増します。

さらに、AIエージェントのようにモデルを自動で複数回往復させる用途(「働かせる用途」)では、prefill 61 tokens であっても 10 秒以上の TTFT がかかり、回数ごとの速度ブレが積算されていくため、1 回の最高速度(11.9 tok/s)だけを前提にシステムを設計すると深刻なスループット未達に直面します。

単一の数字は、その瞬間の一片のスナップショットに過ぎません。

「1回測って終わり」を卒業し、「複数回測って分散を報告する」文化を定着させること。それこそが、ローカルLLMという変化の激しい領域で、自分とチームを守る最も確実なベンチマークの手法です。


ローカルLLMの導入・パフォーマンス評価や、社内AIインフラの最適化についてご相談があれば、コンタクトフォーム よりお気軽にお問い合わせください。

Footnotes

  1. COMMUNITY_BENCHMARKS.md (turbo-fieldfare)

  2. Benchmark: M1 Pro, 16 GB, macOS 26.5.2 (turbo-fieldfare Issue #37)

  3. Benchmark: Apple M4, 16 GB RAM / 256 GB SSD (turbo-fieldfare Issue #23)

  4. Show HN: TurboFieldfare (Page cache comment)

  5. Show HN: TurboFieldfare (I/O & GPU alternating comment)

  6. SSD Offloading for LLM Mixture-of-Experts Weights (arXiv:2508.06978)

  7. ray-project/llmperf (LLM Performance Metrics)

  8. ggerganov/llama.cpp (llama-bench tool)

  9. 24/365稼働の自分用ローカルLLMに最適なMacは? (Zenn)