株式会社ホコサキ

VRAMに乗らないMoEモデルをcolibriでローカル実行する

天京祐輔
天京祐輔
VRAMに乗らないMoEモデルをcolibriでローカル実行する

Mixtral 8x22B を手元で試そうと思い、必要 VRAM を調べた瞬間に諦めた——そういう経験がある人は少なくないはずです。
Q4_K_M 量子化でも約 90.9 GB の VRAM が要るという数字を前にすれば、「自分の環境では無理だ」という結論は自然に見えます。

でも、その前提は本当に正しいのでしょうか。

colibri は、VRAM に収まらない frontier 級の MoE モデルをディスクからストリーミングしながら推論する、純 C 実装の推論エンジンです。
依存ライブラリはゼロで、make 一発でビルドできます。

まずスパース活性化の話から入ります。
設計の論理が分かってからビルドすると、ディスク I/O が走るあの独特の間合いに対して「なるほどこういうことか」という理解が変わります。

Mixtral 8x22Bを動かすのに90GBのVRAMが要る、という前提を疑う

willitrunai.com の調査 によれば、Mixtral 8x22B を Q4_K_M 量子化で実行するには 約90.9 GB の VRAM が必要です。
推奨スペックは 105 GB 以上で、NVIDIA H200 でなければ話にならない水準です。

一方で、同じページに気になる数字が並んでいます。
このモデルのパラメータ数は 141B ですが、推論時に実際に活性化されるのは 39B 相当 です。

ここに MoE(Mixture of Experts)の構造的な非対称性があります。
Dense モデルでは全パラメータが毎トークン必ず計算に参加します。
一方、MoE モデルはエキスパートと呼ばれる FFN(フィードフォワードネットワーク)のサブモジュールを複数持ち、各トークンの処理では Router がそのうちの少数だけを選んで使います。

Mixtral 8x22B の場合、1 トークンを処理するたびに全エキスパートのうち上位 2 つだけが活性化されます。
残りのエキスパートはその時点では一切使われません。

「じゃあ、使われないエキスパートはメモリに乗せなくていいのでは」という問いは、論理的には自然です。
なのに従来の実装が全エキスパートをメモリに読み込んでから推論するのは、実装上の都合——「そのほうがコードが単純で速いから」という理由です。
これは設計の選択であって、MoE アーキテクチャが要求している制約ではありません。

Dense モデルなら全パラメータが毎回必要なので逃がしようがありませんが、MoE はスパースに活性化される構造を持っているため、「その都度必要なエキスパートだけ引っ張ってくる」設計が原理的に成立します。
colibri はその原理をそのまま実装に落とし込んでいます。

colibriの設計:エキスパートをディスクから「その都度」引っ張る

colibri の核心は、VRAM・RAM・NVMe SSD を 単一のメモリ階層 として扱うことです。
推論エンジンの側が、どの層にどのエキスパートを置くかを管理し、必要なタイミングで必要なエキスパートだけをストリーミングロードします。

この設計を理解するために、VRAM 制約の回避手法を「何を単位として、どこに逃がすか」という軸で整理してみます。

  • AirLLM(レイヤー単位の分割ロード): Transformer レイヤー全体を一段ずつ順番に読み込んで推論し、終わったら次のレイヤーへ進む方式。Dense モデルでも MoE モデルでも使えるが、「今使うかどうかに関係なくレイヤー単位で全部ロード」するため、MoE のスパース性は活かせない。
  • llama.cpp の CPU オフロード: VRAM に乗りきらないエキスパートを CPU の RAM に置き、推論時にアクティベーションベクトルを PCIe 経由で送って CPU 側で計算させる方式。PCIe バスのレイテンシがボトルネックになりやすい。
  • colibri のエキスパートストリーミング: エキスパートをディスク(NVMe SSD)に置き、Router が選んだエキスパートだけをその都度読み込んで使う方式。VRAM も RAM も最小限しか使わず、MoE のスパース性を直接活用する。

colibri が MoE に特化しているのは、スパース性(1 トークンあたり少数のエキスパートしか使われない)がなければ、ディスクからのストリーミングロードのオーバーヘッドが致命的になるからです。
Dense モデルに同じ設計を適用しても、毎トークンでほぼ全パラメータを読み込むことになり、ディスク I/O が完全に破綻します。

もう一つ注目したいのが、pure C・ゼロ依存という実装上の選択です。
外部ライブラリがなければビルド環境の差異が最小化され、コードのどこで何をしているかが追いやすくなります。
「ランタイムが何をしているかわからない」という不透明さは、推論エンジンをカスタマイズしたいエンジニアにとって地味に厄介な問題ですが、colibri はその透明性を設計方針として打ち出しています。

ビルドから実行まで:make一発で通るか、モデルはどう渡すか

まず環境の話から。
colibri は Linux または macOS で動作します。
必要なのは GCC か Clang が通ること、それだけです。
外部依存がゼロなので、パッケージマネージャで何かを追加インストールする必要はありません。

ただし CPU 命令セットに AVX2 が使えるかどうかで性能が変わるため、古い Xeon 環境などでは事前に確認しておくと安心です。

ディスク容量も余裕を見てください。
Mixtral 8x22B の Q4_K_M 量子化 GGUF は 86 GB 前後あります。
ストリーミングロード前提とはいえ、モデルファイル自体はどこかに置く必要があります。

# リポジトリをクローン
git clone https://github.com/JustVugg/colibri
cd colibri

# ビルド(依存ゼロなので make だけ通ればいい)
make

ビルドはほぼこれで完了します。
Makefile はシンプルな構成なので、コンパイラが通れば詰まるところはほとんどありません。
AVX2 非対応の環境で警告が出る場合は、Makefile 内のコンパイルフラグを確認して調整してください。

モデルファイルの準備には HuggingFace CLI を使うのが手軽です。

# huggingface_hub のインストール(Python 環境が必要)
pip install huggingface_hub

# Mixtral 8x22B の GGUF をダウンロード(例)
huggingface-cli download \
  bartowski/Mixtral-8x22B-v0.1-GGUF \
  --include "*Q4_K_M*.gguf" \
  --local-dir ./models

ファイルが揃ったら colibri に渡して推論を実行します。
正確なフラグは README を確認してください。
以下は代表的なパターンです。

./colibri \
  --model ./models/Mixtral-8x22B-v0.1-Q4_K_M.gguf \
  --prompt "Explain the difference between MoE and Dense LLMs."

実行すると、まず初期化フェーズでモデルのメタデータが読み込まれます。
そのあと、トークンを生成するたびにディスク I/O が走ります。
最初の数トークンはかなりゆっくりに感じるはずで、「止まったかな」と思うくらいの間合いになることもあります。
これはストリーミングロードが動いている証拠なので、焦って強制終了しないようにしてください。

動いた。で、どのくらい使えるのか

正直に言うと、速くはないです。

ディスク I/O がボトルネックになる構造なので、ストレージの種類が推論速度に直接影響します。
NVMe SSD(PCIe 4.0 以上)があれば体感できる速度で出力が進みますが、SATA HDD ではほぼ実用にならないと考えていいです。
1 トークン生成のたびに複数のエキスパートをディスクから読む以上、シーケンシャルリードの帯域幅がそのまま速度の上限になります。

それでも「動く」ことには価値があります。

用途として現実的なのは、リアルタイムの対話ではなく、バッチ処理や非同期のタスクです。
夜間にコードレビューのコメントを生成させておく、長めのドキュメントを要約してファイルに書き出す、といった使い方なら推論が遅くても問題ありません。
「人間が待っていない」状況であれば、処理時間の長さはそれほど気になりません。

API を使わずに済むという点も見逃せません。
機密性の高い社内ドキュメントや顧客データを扱う場合、クラウド API に流せないケースがあります。
ローカルで完結するなら、そのリスクは原理的にゼロです。
モデルの規模を妥協せずに手元で動かせるという選択肢は、そういう場面でかなり効いてきます。

現時点での制約についても触れておきます。
colibri はまだ成熟したプロダクションツールではなく、対応モデルや量子化フォーマットの範囲は発展途上です。
GGUF 形式のモデルを前提としており、全ての MoE モデルがすぐに動くわけではありません。
プロジェクト自体がアクティブに開発中なので、README やイシューを事前に確認してから使うモデルを決めるのが現実的なアプローチです。

「遅いし制約もある、でも手元で動く」という状態をどう評価するかは用途によります。
ただ、「VRAM が足りないから諦める」という一択しか見えていなかったのを、「遅くてもいいなら動かせる」という選択肢に変えられるのは、やはり大きいです。

colibriのコードを読んで、改造する

colibri が pure C・ゼロ依存にこだわっているのは、単に依存を減らしたかったからだけではありません。
GitHub の README には「open research platform」という言葉が出てきます。
推論エンジンを動かすだけでなく、実装を読んで手を入れる前提で設計されているプロジェクトです。

llama.cpp のコードベースは機能豊富ですが、その分どこで何が起きているかを追うのに慣れが要ります。
エキスパートのオフロードロジックを追おうとすると、GGML のテンソル処理・スケジューラ・バックエンド抽象化といった層を横断することになります。

colibri はコード量が少ない分、エキスパートのロードタイミングやメモリ管理の仕組みを直接読んで理解できます。
「Router がどのエキスパートを選んだか」→「そのエキスパートをどのタイミングでディスクから読むか」→「VRAM・RAM・ディスクのどこに何を置くか」という流れが、大きな抽象化レイヤーに隠れることなく見えます。

改造の余地として面白いのは、たとえばエキスパートのキャッシュ戦略です。
連続するトークンで同じエキスパートが選ばれやすいという局所性は実際に観測されており、直近で使ったエキスパートを RAM に残しておくだけで再ロードのコストを減らせる場面があります。
llama.cpp のイシューでも「ホットなエキスパートを VRAM に残すキャッシュ」が議論されていて、これは colibri のようなディスクストリーミング設計でも同様に試せるアイデアです。

もちろん「動けばいい」用途なら改造の必要はありません。
ただ、ストリーミングロードの挙動を自分で触って確かめたい、あるいはエキスパートオフロードの仕組みをコードレベルで理解したいというエンジニアにとって、colibri のコードは読む価値があります。
コンパクトな C の実装は、推論エンジンの内側に踏み込む入口として、今のところかなり入りやすい部類です。


株式会社ホコサキは、山口県宇部を拠点に Web 制作・業務システム開発・AI 活用支援を手がけています。
ローカル LLM の活用やエッジ環境での推論など、実務レベルでの AI 導入についてご相談があればお気軽にどうぞ。
詳しくは お問い合わせページ からご連絡ください。