17
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[Mac Studio vs DGX Spark] 同じモデルで2倍速 — ローカルLLM×Claude Codeの最適化で見えた本当のボトルネック

17
Last updated at Posted at 2026-03-21

はじめに

本記事は、ローカルLLMでClaude Codeを動かす検証シリーズの第4弾です。

第2弾でDGX Spark(NVIDIA GB10 Blackwell)の実力は確認できました。では、MacStudio RAM256GB(M3 Ultra)だとどうなるか? 同じモデル、同じタスク、同じ評価基準で対決させました。

結果: Mac Studioが1.9倍速。ただし、そこに至るまでに4つのボトルネックを発見・解消する必要がありました。その過程こそが本記事の本題です。

結論

# タスク DGX Spark Mac Studio 速度比
1 知識Q&A 12.3s 12.0s 1.0x
2 ファイル読み取り 22.4s 16.0s 1.4x
3 コード生成 24.1s 16.1s 1.5x
4 バグ修正 79.3s 29.3s 2.7x
5 マルチステップ 51.5s 25.1s 2.1x
合計 189.6s 99.4s 1.9x

成功率は両方とも 5/5(100%)。

環境

ハードウェア

項目 Mac Studio DGX Spark
チップ Apple M3 Ultra NVIDIA GB10 (Grace + Blackwell)
メモリ 256 GB (UMA) 128 GB (UMA)
メモリ帯域 ~800 GB/s ~273 GB/s
CPU 28コア 20コア (ARM Cortex)
価格帯 約82万円 約70万円

ソフトウェア

項目 Mac Studio DGX Spark
LLMバックエンド MLX (mlx-lm) vLLM
モデル Qwen3.5-122B-A10B-4bit Qwen3.5-122B-A10B-int4
量子化 INT4 (63 GB) INT4 (63 GB)
APIゲートウェイ 自作 (aiohttp) パススルー
Raw速度 55.3 tok/s ~15 tok/s(推定)

Raw速度ではMac Studioが約3.7倍速い。 メモリ帯域(800 vs 273 GB/s)の差がそのまま出ています。LLM推論はメモリ帯域律速なので、この差は本質的です。

最適化の記録: 289.7秒 → 99.4秒

最終結果に至るまでに4つのボトルネックを発見しました。記事にする価値があるのは、どれも「ハードウェアの問題」ではなく「ソフトウェアの問題」だったことです。

最適化の全体像

段階 合計時間 改善率 施策
初回 起動失敗 Python 3.14でuvloopが壊れてLiteLLM起動不可
自作ゲートウェイ v1 289.7s ベースライン Anthropic→OpenAI変換プロキシを自作
thinking無効化 252.2s -13% Qwen3.5のthinkingモードをOFF
settings.json最適化 217.2s -14% KVキャッシュ無効化ヘッダーを除去
--tools制限 99.4s -54% 22ツール → 3ツール

ボトルネック1: APIフォーマットの壁

問題: Claude CodeはAnthropic Messages API形式でリクエストを送りますが、MLXはOpenAI Chat Completions形式しか受け付けません。DGX SparkのvLLMはAnthropic形式をネイティブサポートしていたので問題になりませんでした。

最初の試み: LiteLLM — Claude Code公式推奨のAPIゲートウェイですが、macOS 26.3の標準Python 3.14でuvloopのビルドが失敗。Python 3.12で別venvを作っても、LiteLLM内部のルーティングバグ(Anthropic APIがOpenAI Responses APIに誤ルーティングされる)で動かず。

解決策: Anthropic→OpenAI変換ゲートウェイを自作しました。aiohttp + uvloopベースで、ストリーミングSSE変換を含む約300行のPythonスクリプトです。

Claude Code (Anthropic形式)
    ↓ POST /v1/messages
自作ゲートウェイ (port 4000)
    ↓ POST /v1/chat/completions
MLXサーバー (port 8000)
    ↓ Qwen3.5-122B-A10B-4bit

変換で最も難しかったのはツール呼び出しの双方向変換です。

Anthropic形式 OpenAI形式
content block type: "tool_use" message.tool_calls[]
content block type: "tool_result" role: "tool" メッセージ
tool_choice.type = "any" tool_choice = "required"
SSE content_block_delta SSE delta.tool_calls[].function.arguments

ボトルネック2: Qwen3.5のthinkingモード

問題: Qwen3.5はデフォルトで「thinking」モードが有効です。応答の前に推論過程をreasoningフィールドに出力しますが、これがmax_tokensを消費します。

# "Say hello in Japanese" に対して:
max_tokens=64:   reasoning=64 tokens, content="" (空!)
max_tokens=1024: reasoning=700 tokens, content="こんにちは。"

Claude Codeのようなエージェント用途では、thinkingトークンは無駄です。特にツール呼び出し時は、ツール名と引数を返すだけなのに700トークンの「考え中」が挟まります。

解決策: MLXのchat_template_kwargsでthinkingを無効化。

oai_req["chat_template_kwargs"] = {"enable_thinking": False}

効果: 同じ質問に対して780トークン → 3トークンに削減。

ボトルネック3: MLXのプレフィックスキャッシュの制約

第2弾の記事で紹介したCLAUDE_CODE_ATTRIBUTION_HEADER=0設定。DGX SparkではvLLMの--enable-prefix-cachingと組み合わせて4倍の高速化を実現しました。

しかしMLXでは同じ効果が得られませんでした。

調査の結果、MLXのキャッシュ実装に根本的な制約があることが判明:

# mlx_lm/models/cache.py (v0.31.1)
class ArraysCache:
    def is_trimmable(self):
        return False  # ← ハードコードでFalse!

vLLMはトークン列の共通プレフィックスを検出してKVキャッシュを再利用できますが、MLXは完全一致のみ。Claude Codeのように毎回微妙に異なるプロンプトを送るユースケースでは、MLXのキャッシュはほぼ効きません。

# 同一プロンプト → ヒット
Request 1: cached=20329/20334, time=1.0s
Request 2: cached=20329/20334, time=0.4s  ← 完全一致

# 末尾だけ異なる → ミス
Request "Say A": cached=0/20334, time=31.6s
Request "Say B": cached=0/20334, time=31.1s  ← 毎回31秒
特性 vLLM MLX (0.31.1)
キャッシュ方式 Block-level prefix sharing LRU prompt cache
プレフィックス再利用 共通プレフィックスで再利用 完全一致のみ
Claude Codeとの相性 ◎ 25Kトークンの共通部分を再利用 △ 毎回フルプレフィル

MLXの今後に期待: ArraysCache.is_trimmable()True になれば、さらなる高速化が見込めます。

ボトルネック4: ツール定義のサイズ(最大の発見)

これが最大のボトルネックでした。

Claude Codeはデフォルトで22個のツールを送信します。その合計サイズ:

要素 文字数 割合
ツール定義(22個) 69,640 79%
システムプロンプト 16,082 18%
ユーザーメッセージ 1,833 2%

プロンプトの8割がツール定義です。MLXのプレフィックスキャッシュが効かないため、毎回20,000トークン以上のプレフィルが発生していました。

22ツール: 20,335 tokens → プレフィル 32秒
 3ツール:  ~6,000 tokens → プレフィル 12秒(初回), 0.8秒(キャッシュヒット時)

解決策: claude --tools "Bash,Read,Write" で必要最小限の3ツールに制限。

この変更だけで 217.2秒 → 99.4秒(54%削減)。最適化の中で最も効果が大きく、かつ最も簡単な変更でした。

なぜDGX Sparkでは問題にならなかったか

DGX Sparkでもツール定義は同じ22個(70K文字)が送られていましたが、vLLMのプレフィックスキャッシュが共通プレフィックスを再利用するため、2回目以降のリクエストでは25Kトークンのプレフィル分が丸ごとスキップされていました。

つまり:

  • DGX Spark: 22ツールでもキャッシュが効く → 問題にならない
  • Mac Studio: キャッシュが効かない → ツールを減らして物理的にプロンプトを小さくする

同じモデル、同じClaude Codeなのに、バックエンドのキャッシュ実装の違いで最適化アプローチが変わるという、興味深い結果です。

タスク別の詳細比較

Task 1: 知識Q&A(12.0s vs 12.3s)

ツール不要の単純なQ&A。ほぼ同等。Claude Codeの起動オーバーヘッド(~10秒)が支配的で、モデル推論時間はわずか。

Task 4: バグ修正(29.3s vs 79.3s → 2.7倍速)

最も差がついたタスク。バグ修正は:

  1. ファイルを読む(Read)
  2. バグを分析する(長いトークン生成)
  3. 修正版を書く(Write)

ステップ2の長いトークン生成でMac Studioの55.3 tok/sが威力を発揮しました。DGX Sparkの~15 tok/sとの3.7倍の差が、そのままタスク時間の差に表れています。

Task 5: マルチステップ(25.1s vs 51.5s → 2.1倍速)

ディレクトリ作成→実装→テスト作成→テスト実行→結果報告という5ステップ。複数のツール呼び出しが連鎖するため、各ステップでの推論速度の差が累積しました。

再現手順

前提条件

  • Mac Studio M3 Ultra (128 GB以上推奨)
  • Homebrew, Node.js, Claude Code
  • Python 3.12 + Python 3.14

セットアップ

# Python 3.12 venv(ゲートウェイ用)
brew install python@3.12
/opt/homebrew/opt/python@3.12/bin/python3.12 -m venv .venv312

# Python 3.14 venv(MLX用)
python3 -m venv .venv
source .venv/bin/activate
pip install mlx-lm

Claude Code設定

// ~/.claude/settings.json
{
  "env": {
    "CLAUDE_CODE_ATTRIBUTION_HEADER": "0",
    "CLAUDE_CODE_ENABLE_TELEMETRY": "0",
    "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1"
  }
}

実行

# ターミナル1: MLXサーバー
source .venv/bin/activate
python3 -m mlx_lm.server --model mlx-community/Qwen3.5-122B-A10B-4bit --port 8000

# ターミナル2: ゲートウェイ + ベンチマーク
source .venv312/bin/activate
python3 gateway.py &  # port 4000
ANTHROPIC_BASE_URL=http://127.0.0.1:4000 \
ANTHROPIC_AUTH_TOKEN=local \
claude --print --tools "Bash,Read,Write" --max-turns 5 --permission-mode bypassPermissions \
  -p "Pythonのデコレータの仕組みを3文で説明してください"

まとめ

学び 内容
メモリ帯域が全て M3 Ultra(800 GB/s)はGB10(273 GB/s)の3倍 → tok/sも3.7倍
キャッシュ実装が鍵 vLLMのプレフィックスキャッシュとMLXのLRUキャッシュは根本的に違う
ツール定義が巨大 Claude Codeのプロンプトの79%はツール定義。--toolsで制御可能
thinkingは切るべき エージェント用途ではQwen3.5のthinkingモードは無駄
API変換は避けたい Anthropic→OpenAI変換ゲートウェイは工数がかかる。vLLMのネイティブ対応は大きな利点

DGX Sparkの70万円 vs Mac Studioの82万円。価格は1.17倍ですが、性能は2倍。そしてMac StudioはmacOSの普段使いマシンとしても使えることを考えると、研究者の個人環境としてはMac Studioに分があるかもしれません。

一方、DGX SparkはvLLMのエコシステム(プレフィックスキャッシュ、Anthropic API対応)の恩恵をフルに受けられるため、サーバー用途やチーム共有環境では有利です。

ローカルLLMでClaude Codeを動かすという試みは、ハードウェアの選択だけでなく、ソフトウェアスタックの最適化が性能を大きく左右することを教えてくれました。


シリーズ記事:

GitHub: https://github.com/amu815/claude-local

17
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?