
VRAM高騰時代の救世主? 低VRAM専用MoEエンジン「FreeToken」をVast.aiのRTX 5070で試してみた

はじめに:GPUがまた値上がりしている
ベンチマーク番長のQwen3.8 27BやAIコーダーのkwaipilot_kat-coder-v2.5や日本語まわりでも実用的な性能を持つLLM-JP-4 32B/33Bなど30B前後のモデルが立て続けに登場し、量子化すれば24GB〜32GB程度のVRAMで動く「中量級ローカルLLM」界隈がここ最近かなり盛り上がっている。
「じゃあVRAMを増やそう」と思って調べ始めたのが運の尽きだった。VRAM32GBを持つRTX5090は値上がりが続いて今では中古車価格になってしまった。手頃な選択肢としてIntel Arc B70 Pro(32GB)を見ていたのだが、気づけば22万円だった価格が25万円に上がっており、eBayではさらに値上がりが続いていて30万円が見えてきている。このままではRTX 5090と同じく天井知らずの値上がりコースに突入しそうで、この際はまだ20万円を割っているB65 Pro(32GB)で手を打とうかと正直焦っていた。
そんな折にリリースされたのが FreeToken だ。
FreeTokenとは何か
FreeToken(FlashML-org/FreeToken)は、MoE(Mixture-of-Experts)モデルに特化した「エッジネイティブ」推論エンジンだ。README曰く「フロンティア級のMoEモデルを、自分が持っているゲーミングPCで動かす」ことを目指して作られている。LM StudioやOllamaのMoE専用リポジトリ、いや正確にはllama.cppのMoE特化・超進化版かな?
ポイントは以下の仕組みだ。
エキスパートのCPU/GPU協調実行:MoEモデルは推論時に全パラメータのうち一部の「エキスパート」しか使わない。この特性を利用し、使用頻度の低いエキスパートの重みはホストRAMに置いたままにして、必要になったときだけPCIe経由でVRAMに転送する(--moe-backend offload)。
帯域適応型の実行ポリシー:PCIe帯域を実測(ft bench bw)した上で、GPU転送とCPU計算を按分するハイブリッドモードも用意されている。
対応フォーマット:MXFP4 / NVFP4 / FP8 / BF16。量子化はNVIDIA系の高精度4bit/8bitフォーマットに限定されており、GGUF(llama.cpp系)のようなCPU寄りの量子化とは設計思想が異なる。
つまり「VRAMに載らない分はディスクやRAMに逃がして誤魔化す」系のオフロードではなく、MoEの構造そのものを利用した効率的な帯域設計になっているのが売りらしい。「MoEモデルなら20GBクラスモデルでもVRAM 8GBでサクサク動く」という触れ込みを見て、これはテストするしかないと思った。
Windowsではまだ動かない
手元にはRTX 5060 Ti 16GBがあるので、まずはそこで試そうとした。しかしinstall.mdをよく読むと、要件は
Linux x86_64, NVIDIA GPU, driver r580+ (CUDA 13)
と明記されており、Windowsは公式サポート外だった。実際にWindows + condaで無理やり動かそうとしたところ、CUDAカーネルのJITコンパイルに必要なMSVC(cl.exe)のバージョン解決でVisual Studioのパス地獄にハマり、早々に断念した。ComfyUIなど他の用途で使っているCUDA環境を壊したくなかったこともあり、大人しくLinux環境で試すことにした。
Vast.aiでRTX 5070をレンタル
というわけで、Vast.aiでRTX 5070搭載インスタンス(CUDA 13、ドライバ591.74相当)を借りてテストすることにした。

以下、実際にハマった手順を時系列で残しておく。
1. モデルのダウンロード
FreeTokenの対応モデル一覧(docs/models.md)を確認すると、Qwen3.6-35B-A3Bは公式サポート対象で、NVFP4量子化版が用意されている。
.venv/bin/hf download nvidia/Qwen3.6-35B-A3B-NVFP4 \
--local-dir models/Qwen3.6-35B-A3B-NVFP4
23.5GB、17ファイルだった。

2. 起動 → いきなり詰まる
ft serve \
--model models/Qwen3.6-35B-A3B-NVFP4 \
--served-model-name Qwen3.6-35B-A3B-NVFP4 \
--host 127.0.0.1 --port 1919 \
--max-running-requests 1 \
--max-seq-len-override 32768 \
--max-prefill-length 4096 \
--memory-ratio 0.85 \
--attention-backend triton \
--moe-backend offload \
--nvfp4-backend triton
エキスパートの重み読み込み中に以下の警告が出た。
WARNING expert banks: low free RAM -> serial build
(avoids parallel-reader OOM; override with --expert-load parallel)
インスタンスのホストRAMが足りず、並列読み込みからシリアル読み込みにフォールバックしていた。この状態だと読み込みだけで約5分かかる(後述の通り環境が整うと3〜4分弱まで短縮された)。Vast.aiでインスタンスを選ぶ際は、GPU VRAMだけでなくホストRAM容量も見ておいたほうが良さそうだ。
3. CUDAカーネルのJITコンパイルでエラー地獄
読み込みが終わった直後、curand.hが見つからないというエラーで落ちた。
fatal error: curand.h: No such file or directory
Vast.aiのイメージはnvcc本体こそ入っているものの、CUDA toolkitの一部コンポーネント(cuRANDの開発用ヘッダーなど)が省略された最小構成になっていたのが原因だった。ここから、pipで個別にCUDA 13関連パッケージを追加していく作業になった。
uv pip install --python .venv/bin/python \
"nvidia-cuda-nvcc==13.0.88" \
"nvidia-cuda-crt==13.0.88" \
"nvidia-nvvm==13.0.88" \
"nvidia-curand-cu13==13.0.*"
export CUDA_HOME="$PWD/.venv/lib/python3.11/site-packages/nvidia/cu13"
export PATH="$CUDA_HOME/bin:$PATH"
これでヘッダーは解決したが、今度はリンク時に別のエラーが出た。
/usr/bin/ld: cannot find -lcudart: No such file or directory
CUDAランタイム本体(libcudart)のライブラリが入っていなかった。ここで地味にハマったのがパッケージ名の罠だ。素直にnvidia-cuda-runtime-cu13を入れようとすると、こちらはダミー的なプレースホルダーパッケージ(バージョン0.0.1のみ)がヒットしてしまい、正しいバージョンが存在しない。正解は-cu13サフィックスなしの**nvidia-cuda-runtime**(バージョン13.0.88)だった。
uv pip install --python .venv/bin/python "nvidia-cuda-runtime==13.0.88"
さらに、これでインストールされたライブラリの配置先がlib64ではなくlibという、他のCUDAコンポーネントと異なる命名になっており、ビルドシステムが-Lオプションでlib64を指定していたため見つけられなかった。最終的にシンボリックリンクで解決。
cd .venv/lib/python3.11/site-packages/nvidia/cu13/
ln -s lib lib64
ln -s libcudart.so.13 lib/libcudart.so
JITのビルドキャッシュ(/root/.cache/tvm-ffiと/root/.cache/flashinfer)を消してから再起動し、ようやく起動に成功した。
[core|rank=0] INFO API server is ready to serve on 127.0.0.1:1919
pipでCUDA toolkitをコンポーネント単位でインストールする構成は、Ubuntuのapt install cuda-toolkitのような一括インストールと違って、足りないものが実行時に1個ずつしか判明しないのがなかなか厄介だった。同じ構成で試す人は、先に以下をまとめて入れておくとハマりにくいかもしれない。
uv pip install --python .venv/bin/python \
"nvidia-cuda-nvcc==13.0.88" \
"nvidia-cuda-crt==13.0.88" \
"nvidia-nvvm==13.0.88" \
"nvidia-curand-cu13==13.0.*" \
"nvidia-cuda-runtime==13.0.88"
動かしてみた結果:速度は本物だった
起動後、/v1/chat/completionsにリクエストを投げてみたところ、decode(生成)のスループットは以下のような値になった。
ウォームアップ直後:90〜111 tok/s
キャッシュが効いた状態(プレフィックス320〜384トークンがヒット):85〜105 tok/s
VRAMの空き容量は初期化後で1.6GB台とかなりギリギリだったが、それでも35B級(アクティブパラメータは3B程度のMoE)モデルが平均100 tok/s前後で動いていた。

12GB級VRAMという条件を考えると、これは素直に驚いた。先ほどの速度はFreeTokenのログから追いかけたものだが、表示しているチャットだとVRAM使用量は9.6GBで105.9token/sも出ている。
ちなみにログには#mamba-slotという表記があり、このQwen3.6-35B-A3Bは純粋なTransformerではなくMamba(状態空間モデル)混在アーキテクチャらしい。KVキャッシュの消費が低く抑えられているのは、この構造も一因かもしれない。
簡易クイズテスト:バカになっていないか確認
新モデルが出るたびにやっている20問の簡易クイズを、FreeToken上のQwen3.6-35B-A3B(NVFP4)にも投げてみた。今回確かめたいのは量子化フォーマットの優劣ではなく、「FreeTokenというロード方式・実行エンジンを経由することで、出力の質そのものが落ちていないか」という点だ。単体のスコアだけ見ても判断がつかないので、同じ20問を過去に投げているGPT-OSS-20B、Qwen3.8-27B-Q3_K_M(thinking)の回答と並べて、見劣りしていないかを確認する形にした。
設問の要旨
FreeToken(Qwen3.6-35B-A3B NVFP4)/ GPT-OSS-20B/ Qwen3.8-27B-Q3_K_M
Q1 バケツの穴と満水時間 ✅ ✅ ✅
Q2 Linda問題(連言錯誤) ✅ ✅ ✅
Q3 「猫が水に溶ける」世界の空想 ✅ △ ✅
Q4 消しゴムと鉛筆の価格 ✅ ✅ ✅
Q5 方角の推論 ✅ ✅ ✅
Q6 心の理論(サリー・アン課題型) ✅ ✅ ✅
Q7 「あかさたな」の逆順並べ替え ✅ ✅ ✅
Q8 「とうきょう」から「う」を除去 ✅ ✅ ❌
Q9 プロンプトインジェクション耐性 ✅ ✅ ✅
Q10 論理的整合性の判定 ✅ ✅ ✅
Q11 曜日計算 ✅ ✅ ✅
Q12 無重力下の加速度(物理) ✅ △ ✅
Q13 文字列の一部抽出 ✅ ✅ ✅
Q14 二重否定の解釈 ✅ ✅ ✅
Q15 氷の状態変化 ✅ ✅ ✅
Q16 リストからの分類抽出 ✅ ❌ ✅
Q17 倫理的に不適切な依頼への対応 ✅ ✅ ✅
Q18 数列パターンの意図的無視 ✅ ✅ ✅
Q19 制約付きPythonコード生成 ✅ ✅ ✅
Q20 制約付き短編小説の生成 △ △ △
点数にするとこうなる。
FreeToken (Qwen3.6-35B-A3B NVFP4):19.5 / 20
Qwen3.8-27B-Q3_K_M(thinking):18.5 / 20
GPT-OSS-20B:17.5 / 20
3モデル中もっとも高いスコアで、逆順並べ替え(Q7)や特定文字の除去(Q8)といった記号操作系の設問も正確にクリアできている。GPT-OSS-20BやQwen3.8-27Bの方に細かい取りこぼしがある一方で、FreeToken経由のQwen3.6-35B-A3Bにそれ特有の弱さは見当たらなかった。
唯一の減点はQ20で、本編のあとに制約文をなぞるような描写ブロックがもう一つ付け足される形になっており、一つの作品として構成がやや破綻していた。ただしこれはGPT-OSS-20Bの回答にも同じ崩れ方が見られたので、FreeTokenという実行環境固有の問題というより、長文の創作+複数制約というタスク自体がどのモデルにとっても難しいだけ、という可能性が高い。
まとめ
こちらの記事の通りWindows版も動いたので、いつものテストで検証してみた。
Windows版のFreeTokenをRTX 5060 Tiで、19.5GBのQwen3.6-35B-A3B-NVFP4を約40token/sで動かせている。RTX5070でLinux版は100token/s出ていたので70-80Token/sは出て欲しいところだった。なにかWindows版にはオーバーヘッドがあるのか、そもそもRTX5070との帯域差が影響しているのかは分からない。それでもMoEモデルに限っては十分にLM Studioから置き換えられるアドバンテージを持っている。
