MacBook M2 MaxでローカルLLM 81 tok/s達成 — Gemma 4 E4B + MTP + llama-swap


🖥️ MacBook Pro M2 Max (32GB) · macOS 26.5.1 · arm64 · llama.cpp b9820+ · llama-swap · Open WebUI

Gemma 4 E4B MTP speculative decoding llama-swap llama.cpp Open WebUI

🔍 Ollamaをやめた理由

MacBook M2 MaxでローカルLLMを動かす場合、Ollamaが最初の選択肢になることが多いです。インストールが簡単で、Web UIとモデルのpull機能が標準で付いています。しかし、Gemma 4 E4Bの性能を最大限に引き出すにはOllamaだけでは不十分でした。

核心はMTP(Multi-Token Prediction)です。Gemma 4はドラフターモデルによる推論加速のspeculative decodingをサポートしています。現在OllamaはGemma 4のMTPをサポートしていないため、llama.cppが必要です。

実測結果:M2 Max 32GB環境でGemma 4 E4B + MTP組み合わせにより約81 tok/sを記録しました。これはOllamaのMLXエンジンで8Bモデルを動かした場合(65–75 tok/s)を上回る数値です。4Bモデルでありながら、MTPなしのllama.cpp単体(50–60 tok/s)と比べて35–60%の性能向上を確認しました。本記事ではその環境の構成と運用過程をまとめます。

📋 環境構成 — 3つのコンポーネント

インストールパスは~/Git/local-llm/です。MacBook専用設定のためgitignoreしています。

コンポーネント 役割 備考
llama.cpp 推論エンジン Metal GPUバックエンド、MTP対応 b9549+
llama-swap マルチモデルプロキシ Goバイナリ、TTLアンロード、OpenAI互換API
Open WebUI Webインターフェース localhost:8888、ドロップダウンでモデル選択

llama-swapがlocalhost:11434でOpenAI互換APIを公開し、Open WebUIがそのエンドポイントを使用します。ドロップダウンでモデルを選択するとllama-swapが該当のllama-serverを起動し、600秒間無操作が続くと自動的にアンロードします。

🧠 MTP — コア技術

MTP (Multi-Token Prediction / Speculative Decoding)

ドラフターモデルが複数のトークンを事前に予測し、メインモデルが並列で検証する方式です。採用されたトークンは追加の演算なしに確定されます。採用率が高いほど速度向上が大きくなります。

このMacBookにおけるGemma 4 E4Bの採用率(Acceptance Rate)は42–57%です。DGX Sparkサーバー環境では84–93%まで上昇します。コンテキストパターンが一貫しているほどドラフターの予測精度が高まるためです。Googleの公式発表(2026-05-05)によると、MTPはGemma 4の主要な推論加速技術です。

設定時に注意すべき点が2つあります。

  • --flash-attnとMTPは競合します。--flash-attn offの設定が必須です。
  • ドラフト深度のスイートスポットは--spec-draft-n-max 4です。4を超えると収益逓減になります。DGX環境でn-maxを2に下げたとき+35%(80→109 tok/s)の向上を確認しました。
MTPはlosslessを保証しません。sample-match方式で動作し、n-max ≥ 3の設定でcommittedトークンの損傷が報告されています。精度が重要なコーディング作業などではn-maxを2–3に下げることを推奨します。

🛠️ モデルファイル構成

現在運用中のモデルは2つです。デフォルトモデルはUnslothのUD-Q4_K_XLです。QAT(Quantization-Aware Training)を適用しており、通常のQ4_K_M比で品質が高くなっています。uncensoredモデルはHauhauCS Aggressiveのコミュニティファインチューニングモデルです。

モデルID メインファイル(サイズ) MTPドラフター 速度
gemma-4-E4B(デフォルト) UD-Q4_K_XL.gguf (4.22GB) Q8_0-MTP.gguf (~156MB) ~81 tok/s
gemma-4-E4B-uncensored Q4_K_M.gguf (4.97GB) なし ~60 tok/s

MTPドラフター(Q8_0)は約156MBで、約1.5〜2GBの追加RAMを占有します。32GBメモリ環境では余裕のある範囲です。vision機能は両モデルともに別途mmproj(F16.gguf)でサポートします。

uncensoredモデルで気づいた特異点があります。オープンエンドの質問で英語のreasoningが長く出力され、答えのcontent部分が空に見える現象です。Open WebUIのシステムプロンプトにthinking出力を抑制する指示を追加して解決しました。推奨サンプラー設定はtemp=1.0, top_p=0.95, top_k=64, --jinjaです。

⚙️ 実行設定

llama-swapとOpen WebUIを同時に起動する統合スクリプトを使用しています。

# 統合起動
./start-webui.sh

# OpenAI互換APIエンドポイント
http://localhost:11434/v1

# 停止
pkill -f "open-webui serve" \
  && pkill -f "llama-swap" \
  && pkill -f "llama-server"

llama-swap.yamlの主要設定です。${PORT}はllama-swapが自動的に割り当てます。

healthCheckTimeout: 120
ttl: 600  # 10分間アイドル後に自動アンロード

models:
  gemma-4-E4B:
    cmd: |
      llama-server
        --model /path/to/main-Q4_K_XL.gguf
        --model-draft /path/to/draft-Q8_0.gguf
        --mmproj /path/to/mmproj-F16.gguf
        --spec-type draft-mtp
        --spec-draft-n-max 4
        --flash-attn off
        --port ${PORT}

  gemma-4-E4B-uncensored:
    cmd: |
      llama-server
        --model /path/to/uncensored-Q4_K_M.gguf
        --mmproj /path/to/mmproj-uncensored-F16.gguf
        --port ${PORT}
llama-swapのインストールはHomebrew 1行です:brew tap mostlygeek/llama-swap && brew install llama-swap。Ollamaのエコシステムに縛られることなく、すべてのGGUFをサポートし、コンテナのオーバーヘッドなしにMetal GPUを100%活用できます。GitHub:mostlygeek/llama-swap

📊 速度比較 — 実測と外部ベンチマーク

M2 Max(メモリ帯域幅400 GB/s)基準の実測値と外部ベンチマークデータです。

構成 tok/s 備考
Ollama(MLXエンジン、8B Q4_K_M) 65–75 2026 macOS MLX JITコンパイル基準
llama.cpp(E4B Q4_K_XL、MTPなし) 50–60 GGUF単体実測
llama.cpp + Gemma 4 E4B + MTP ~81 採用率42–57%、実測

他ハードウェア参考値の出典:GitHub karany97/llamacpp-gemma4-mtpReddit — RTX PRO 6000 3.34x検証Medium — ローカル推論ベンチマーク(2026-05-22)

ハードウェア MTP前 MTP後 向上
Samsung Galaxy S26+ ~12 tok/s ~14 tok/s +15%
NVIDIA Jetson Orin NX ~13 tok/s 18–20 tok/s +30–40%
RTX 3060 12GB ~30 tok/s 60+ tok/s 2x–3x
RTX PRO 6000 基準 3.34x 検証済み

GPU環境で採用率が70–100%まで上昇する理由は、コーディング作業の反復的なパターンにあります。MacBook Metal環境は42–57%水準ですが、これでも有意な速度向上をもたらします。llama.cppのMTPサポートはPR #23398(b9549、2026-06-07)でマージされました。Reddit LocalLLaMAでも+40% speedupのレポートが継続的に報告されています。

🔧 トラブルシューティング — 主要な問題

症状 原因 解決策
“no implementations specified” –spec-typeフラグ不足 --spec-type draft-mtpを追加
MTPコンテキスト生成失敗 flash-attn競合 --flash-attn off
b9820でフラグエラー フラグ名変更 --spec-draft-n-max(旧:--draft-max
uncensoredの応答が空に見える 英語thinking出力の漏洩 WebUIシステムプロンプトで抑制
py3.13 audioop ImportError 標準ライブラリから削除 uv pip install audioop-lts

uncensoredモデルのthinking漏洩は最初はモデルの欠陥かと思いました。確認したところ、英語のreasoningがすべて出力されて実際の回答contentが後ろに押し出される構造でした。Open WebUIのシステムプロンプトで出力を制御して解決しました。モデル自体のバグではありませんでした。

📚 参考資料

✅ まとめ

M2 Max 32GBでローカルLLMを効率的に使うにはllama.cpp + llama-swapの組み合わせが最善です。Ollamaよりも設定は複雑ですが、MTPサポートと細かいパラメーター制御がその価値を十分に発揮します。Gemma 4 E4B + MTPの組み合わせは約81 tok/sを記録し、4BモデルでありながらOllamaのMLXエンジンの8Bモデル(65–75 tok/s)を上回る数値です。すべてのコンポーネントはMITまたはGemma Licenseに基づくオープンソースです。

llama-swapのTTLベースのアイドルアンロード機能は複数モデルの運用において非常に実用的です。モデルの切り替えがスムーズで、未使用のモデルを10分後にメモリから解放してSSDの消耗を防ぎます。

ローカルLLMの設定に関するより詳しい情報はローカルAIカテゴリでご確認いただけます。


Discover more from AI-Girls Lab

Subscribe to get our latest posts delivered to your inbox.


AI-Girls Labをもっと見る

今すぐ購読し、続きを読んで、すべてのアーカイブにアクセスしましょう。

続きを読む