2026年8月、FreeTokenというエッジ向けMoE推論エンジンの論文が公開されました。「290B+級のMoEモデルをゲーミングPC上で動かせる」という強気な謳い文句で、DeepSeek-V4やQwen3.6、gpt-ossなどをコンシューマ向けGPUで動かせるとのことです。FreeTokenにはClaude CodeやCodexといった既存のコーディングエージェントCLIをそのままバックエンドとして接続する機能もあるので、ベンチマークだけでなく実際にエージェントから使えるかどうかまで確認しています。

5090の検証記事は多く見かけますが、5080、しかもメモリはDDR4という構成での検証はあまり見当たらなかったので、私の作業用マシン(WSL2 + RTX 5080、DDR4-3200)で実際に動かしてみました。動くことは動きましたが、デフォルト設定のままだと性能を大きく損なう場面がいくつかありました。以下、その記録です。

先に結論

長い記事なので、実測して分かったことを先に5点だけ挙げておきます。

  • 自動選択(auto)のままだと遅いことがある。 NVFP4形式のモデルは--moe-backend offloadを明示指定するだけで、Qwen3.6-35B-A3Bが28.7 → 108.8 tok/sになりました。
  • 20B〜35B級のMoEなら80〜160 tok/s出る。 体感速度はクラウドAPIと遜色ありません。
  • 「ゲーミングPCで290B級」は実装RAM 48GBでは無理。 1つ下の120B級(重み56.9GB)でもOOM Killerに強制終了され、起動しませんでした。
  • 同じモデルでも、接続するハーネス次第で成否が変わる。 gpt-oss-20bはCodex(/v1/responses)経由なら成功するのに、Claude Code(/v1/messages)経由では14回以上ループして完了しませんでした。Qwen3.6はどちらも成功。
  • エージェント用途ではKVキャッシュの明示拡張がほぼ必須。 自動確保された8,486トークンでは、Claude Codeのシステムプロンプト(約2万トークン)が入りません。

検証環境

項目
OS WSL2 Ubuntu 24.04(Windows 11ホスト)
CPU Intel Core i7-14700F(20コア28スレッド)
GPU NVIDIA GeForce RTX 5080(Blackwell, sm_120)
VRAM 総16GB
メモリ(実装RAM) 48GB(DDR4-3200、8GBx2 + 16GB×2の4枚構成・デュアルチャネル)
CUDA Toolkit 13.3(WSL専用リポジトリ)
FreeToken v0.1.2(PyPI freetoken[accel])

この記事のCPU計算まわりの数値はDDR4-3200環境でのもので、DDR5環境では結果が変わる可能性があります。

試したモデルは以下3つ。

いずれもGPU1枚には乗り切りませんが、MoEなのでアクティブパラメータ分だけなら現実的、というサイズ感のモデルです。

  • openai/gpt-oss-20b(重み13.7GB、active ~3.6B)
  • nvidia/Qwen3.6-35B-A3B-NVFP4(重み21.8GB、active 3B)
  • nvidia/Gemma-4-26B-A4B-NVFP4(重み17.5GB、active 4B)

MoEモデルはExpert256個(Qwen3.6-35B-A3Bの実際の値)の重みをホストRAMに置いたまま、トークンごとにtop-8(+常時使う共有専門家1個)だけをGPU VRAM 16GBにロードして計算するため、全パラメータを毎トークン使うDenseモデルと違い、GPU1枚のVRAMに全パラメータを乗せる必要がない

環境構築でハマった点も2つだけ挙げておくと、TritonカーネルのJITコンパイルにpython3.12-dev(Python.h)が必要なこと(Ubuntuには標準で入っていません)と、CUDAは通常のLinux用ではなくwsl-ubuntuリポジトリを使わないとGPUパススルー用の/dev/dxgを壊してしまうことです。

1. 性能編 — どう設定すれば速く動くのか

ベンチマーク結果

先に数値を出します。動作が安定した範囲での実測値で、プロンプト長を変えて2回ずつ実行し、2回目(ウォームアップ後)を定常値としています。

モデル バックエンド decode tok/s(単発) 並行4集約 tok/s
gpt-oss-20b(MXFP4) offload 163.9 217.0
Qwen3.6-35B-A3B-NVFP4(NVFP4) offload(明示) 108.8 221.3
Qwen3.6-35B-A3B-NVFP4(NVFP4) hybrid(自動選択) 28.7 70.9
Gemma-4-26B-A4B-NVFP4(NVFP4) offload(明示) 83.0 129.4
Gemma-4-26B-A4B-NVFP4(NVFP4) hybrid(自動選択) 29.5 75.0

NVFP4の2モデルはいずれもoffloadを明示指定した方がhybrid自動選択より2.8〜3.8倍速く、decodeは108.8対28.7 tok/s、83.0対29.5 tok/sだった

offloadhybridはFreeTokenのMoE Expertの重みの扱い方の違いで、詳細は後述しますが、ここで注目してほしいのはNVFP4形式の2モデルとも、バックエンドをoffloadに明示指定した方が3倍前後速いという点です。デフォルト(自動選択)のままだと本来の性能を出せていませんでした。20B〜35B級のMoEモデルなら80〜160 tok/s程度出るので、体感的にはクラウドAPIと遜色ない速度です。

(補足:decode tok/sは生成トークン数が少ないとブレやすく、Gemma-4は即答するタイプのモデルなので短いプロンプトだと数トークンしか生成せずノイズの影響を受けやすかったため、上表は生成トークン数が十分に確保できたプロンプトでの値を採用しています)

なお、gpt-oss-20b・Qwen3.6はどちらも応答前に内部で思考を生成するモデルで、この挙動もそのまま体感速度に影響します。詳細は後述の「思考(thinking)を軽くできるか」で扱います。

実験1: なぜ自動選択のバックエンドは遅かったのか

Expertの重みは基本的にホストRAM(CPU側メモリ)に置かれ、GPU VRAM側にはそのうち一部だけがLRUキャッシュとして常駐します。処理に必要なExpertがこのキャッシュに無い場合(キャッシュミス)にどう埋めるかで、FreeTokenのMoEバックエンドは2種類に分かれます。

  • offload:ミスは常にホストRAMからGPU VRAMへPCIe転送して埋める
  • hybrid:ミスの一部だけPCIe転送し、残りはホストRAM上でCPUが直接計算する

offloadはキャッシュミスを常にPCIe転送で埋めてGPUが計算するのに対し、hybridはPCIe転送が12.5%だけで残り87.5%をホストRAM上のCPUが計算するため、decodeが108.8から28.7 tok/sまで落ちる

どちらを使うかはft bench bwという付属のマイクロベンチマークが、機種ごとのCPU/PCIe帯域を実測して自動で選ぶ仕組みです。

Qwen3.6-35B-A3B-NVFP4を何も指定せず起動すると、私の環境では自動的にhybrid(PCIe転送12.5%・CPU計算87.5%)が選ばれました。

benchbw profile recommends hybrid for 'nvfp4' experts on this GPU
Auto-selected MoE backend: hybrid
--moe-hybrid-max-fetch auto: fetching 12.5% of each decode step's
expert misses over PCIe ... the rest on the CPU

hybridのままPCIe転送比率を引き上げる--moe-hybrid-max-fetchも試しましたが、39.7 tok/sまででoffloadには届きませんでした。比率の問題というより、hybridという経路自体に固定のオーバーヘッドがありそうです。

ft bench bwはExpert 1個単位の理論帯域を測るマイクロベンチマークなので、実際のデコードループの挙動までは反映しきれていないのかもしれません。少なくとも私の環境では、nvfp4系のモデルは--moe-backend offloadを明示指定した方が速いという結果でした。念のため別モデル(Gemma-4-26B-A4B-NVFP4)でも同じ検証をしましたが、こちらも約2.8倍の差がついたので、単一モデルだけの偶然ではなさそうです。

(補足:この差はVRAM容量とモデルサイズの比率に依存する可能性があります。VRAMがモデルのExpertの重み全体を上回るような環境では、そもそもキャッシュミス自体が発生しにくくなるため、offloadとhybridの差は縮む、あるいは出ないと考えられます。私の環境はVRAM 16GBで、35B級(Expertの重み21.8GB)でも全体は載り切らないため、この差が大きく出たと見ています)

実験2: 290B級は実装RAM48GBのマシンでは厳しい

20B級・35B級は問題なく動いたので、起動しないだろうとは思いつつ、1つ上のクラスのopenai/gpt-oss-120b(重み56.9GB)も試しました。結果は想定通りで、ロード終盤にOOM Killerによって強制終了されました。

Out of memory: Killed process 4245 (python3) total-vm:184149192kB ...

そもそもWSL2はデフォルトで実装RAMの約半分しか使えないため、.wslconfigmemory=40GBと書いて上限を広げた上での結果です(offload/hybridバックエンドはExpertの重みをホストRAMに置くので、この上限がそのまま動かせるモデルサイズの上限になります)。実装RAM48GBの私のマシンでは、290B級はもちろん120B級もまだ厳しいという結論でした。

なお、FreeTokenのダウンローダーは必要なmainのsafetensors(56.9GB)だけでなく、Apple Metal形式のmetal/model.binやbf16重複データoriginal/まで含めたリポジトリ全体(182GB)を取得しようとする挙動も見られました。モデルが大きいほど無駄が効いてきます。

実験3: 並行数は8までが安全圏

デフォルトの同時リクエスト数(--max-running-requests)は4です。8まで上げると集約スループットは222→356 tok/sまで伸び、安定して動作しました。

16にすると--moe-cache-sizeを3パターン変えて試しましたが、いずれも別種のエラー(LRUキャッシュカーネル内部のAssertionError、起動時のNot enough memory for KV cacheCUDA driver error: device not ready)で落ちました。GPUをクリーンな状態に戻して再試行しても同じ箇所で落ちたので、一過性の問題ではなさそうです。--moe-cache-autoが高い並行数を想定していない(v0.1.2時点の)可能性か、あるいはVRAM 16GBのクラスだと8並列あたりが予算の限界という可能性が考えられます。

2. エージェント接続編 — Claude Code・Codexのバックエンドとして使えるか

FreeTokenにはft launch {claude,codex,dsh,hermes,openclaw,opencode}というコマンドがあり、既存のコーディングエージェントCLIをそのままFreeTokenサーバーに向けて起動できます。このPCにはClaude Codeが入っていたので先に試し、Codexはft launch codex --install-onlyから辿ってOpenAI公式インストーラで新規に導入した上で同じ検証をしました。

既存環境は壊れないのか

まず気になるのが、普段使っているエージェント設定を書き換えられないかという点です。結論としては、Claude Code・Codexどちらも既存環境には影響しませんでした。

  • Claude Code:--dry-runで確認したところ、これは設定ファイルを書き換えるものではなく、環境変数(ANTHROPIC_BASE_URLなど)を設定した上でclaudeコマンドを起動するだけでした。~/.claude/settings.jsonのような永続設定は変更されません。
  • Codex:Claude Codeと方式が違い、~/.codex/に専用の名前付きプロファイル(freetoken-launch.config.toml)を書き込む形でした。デフォルトプロファイルは変更しません。

ft launchはClaude Codeには環境変数を注入し、Codexには専用プロファイルを書き込む形で同じFreeTokenサーバーへ向けるが、使われるAPI経路は/v1/messagesと/v1/responsesに分かれる

つまずいた点: KVキャッシュのデフォルトがエージェント用途には小さすぎる

Claude Codeで最初につまずいたのがこれです。「memo.mdというファイルに1行追記して」という簡単なタスクを投げただけで、こうエラーが出ました。

Prompt is too long · the request is ~20601 tokens (limit 8486)

Claude Codeのシステムプロンプト+ツール定義だけで約2万トークンあるのに対し、FreeTokenが自動確保したKVキャッシュはわずか8,486トークンでした。--kv-reserve-tokens 32768を明示指定して解消しました。

結果: モデルとハーネスの組み合わせで結果が変わった

同じタスク(テキストファイルを読んで1行追記する)を、gpt-oss-20b・Qwen3.6-35B-A3B-NVFP4の2モデル×Claude Code・Codexの2ハーネスで試しました。

モデル Claude Code(/v1/messages) Codex(/v1/responses)
gpt-oss-20b ❌ 失敗(90秒でタイムアウト、14回以上ループ) ⚠️ 成功(5リクエスト)だが差分に余分な半角スペースが混入
Qwen3.6-35B-A3B-NVFP4 ✅ 成功(3リクエスト、クリーン) ✅ 成功(4リクエスト、クリーン)

gpt-oss-20bはClaude Code経由だと、同じ約2万トークンのプロンプトを毎回まるごと再送し、40トークンほど生成しては停止する、というのを14回以上繰り返して完了しませんでした。ところが同じgpt-oss-20bでもCodex経由なら普通に成功しました。つまりこの無限ループは、gpt-oss-20bというモデル自体の欠陥ではなく、FreeTokenのAnthropic Messages API(/v1/messages)ブリッジ側に何か原因がありそうです。CodexはOpenAIのResponses API(/v1/responses)を使うため、この経路では問題が出ませんでした。GitHubのissueやWeb検索で同じ現象の報告がないか調べましたが、今のところ見つかっていません。

ただしgpt-oss-20b × Codexも完全に問題なしとは言えず、生成した差分パッチに余分な半角スペースが混ざり、- ステータス: 完了 - ステータス: 完了(行頭にスペース1個)として追記される軽微な整形ミスがありました。Qwen3.6はClaude Code・Codexどちらでもクリーンに完了しています。

思考(thinking)を軽くできるか

gpt-oss-20b・Qwen3.6はどちらも応答前に内部で思考(reasoning_content)を生成するモデルで、簡単な質問でもデフォルトでは思考し続け、トークン制限に達して回答が空になることがありました。単体で使う場合は、APIにreasoning_effort: "none"を渡すか、対話シェル(ft shell)で/think offと打てば即答モードにできます(Gemma-4はこのタイプではなく、最初から即答でした)。

問題は、これをエージェント経由でどう指定するかです。Qwen3.6の思考をClaude Code経由で軽くできないか試しました。Claude Codeには--effort {low,medium,high,xhigh,max}という設定がありますが、--effort lowを指定しても思考は止まりませんでした。FreeToken側の思考オフの判定はreasoning_effortが文字通り"none"/"off"の時だけ発動する仕組みで、Claude Codeの--effortにはその選択肢がないためです。

一方Codexは、セッション開始時のログにreasoning effort: noneと表示されました。この値がデフォルトで思考オフの状態だったのか、FreeTokenが生成したプロファイルの設定なのか、設定周りは検証が必要な点になりそうです。ハーネス側のデフォルト値や設定の違いが、そのまま体感速度の差につながる可能性が高い箇所だと思います。

まとめ

用途別に評価をまとめると、こんな感じです。

用途 評価 コメント
20B〜35B級MoEをローカルで試す 80〜160 tok/s程度出るので、体感的にクラウドAPIと遜色ない
「ゲーミングPCで290B級」の再現 通常のゲーミングPCのメモリを少し増やした程度のRAM48GB程度では現実的でない。ワークステーション級の容量のRAMが必要
自動設定(auto)をそのまま使う 今回は2.8〜3.8倍の速度差があったので、バックエンドは明示指定した方が安心
高い並行数での運用 v0.1.2時点では16並列で落ちた。8までにとどめるのが無難
Claude Code・Codexのバックエンドとして使う モデルとハーネスの組み合わせ次第。Qwen3.6はどちらも成功、gpt-oss-20bはCodexなら成功・Claude Codeだと失敗した

正直な感想としては、20B〜35B級のMoEモデルなら実用に足る速度が出ましたが、「290B級をゲーミングPCで」をそのまま体験するのは、少なくとも私の環境(実装RAM48GB)では難しいというのが結論です。Claude Code・Codexのバックエンドとしても実際に動かせましたが、同じモデルでも接続するハーネス(APIの経路)次第で結果が変わったのは意外でした。自動選択やドキュメントの数値を鵜呑みにせず、自分の環境で実測してから使うのが良さそうです。同じようにローカルLLMを試す方の参考になれば幸いです。