【自宅サーバー勢向け】 RTX 4090とRTX 4000 AdaでVRAMに乗らないMoE LLMを動かし比べてみた話 【ローカルLLM】
手元の開発用 Linux サーバーに RTX 4090 と RTX 4000 Ada の2枚が挿さっているので、VRAM に乗りきらない大きな MoE モデルを、どの推論エンジンでどれくらいの速度で動かせるのかを比べてみました。 普段の LLM 利用はクラウドのサブスクや従量課金がメインですが、取引先の資料のようにクラウドに出せないデータをローカルで処理できると強みになるので、「今の構成でどこまで実用になるのか」を把握しておきたかった、という動機です。
比べたのは、定番の llama.cpp / Ollama と、ここ数週間で話題になっている MoE 専用の推論エンジン Strata と Project Maya です。 結果から言うと、専用エンジンは llama.cpp より生成で3倍強、入力の読み込みで最大10倍速く、125B〜321B の MoE が「普通に使える」速度で動きました。100万トークンのコンテキストも現実的で、Claude Code のバックエンドとしても動きます。 一方で、異種の2枚を並べても速くなるとは限らない、というのも分かりました。
(どのエンジンもモデルも日単位で版が上がっているので、数字は 2026年10月18〜23日時点のものです)
結論
| 項目 | 結果 |
|---|---|
| VRAM に乗らない MoE の速度 | 専用エンジンが圧勝。Qwen3.8-Flash-Next(125B)は Strata で 143 tok/s(llama.cpp は 41)、GLM-5.3-Flash(321B)は Project Maya で 53 tok/s(同 16) |
| 2枚にする効果 | モデルが RAM には乗るなら、4090 1枚の方が速い(2枚目の帯域の遅さが毎トークン効く)。RAM にも乗らないモデルでは 2枚の方が速い |
| 100万トークン | Qwen3.8(Strata)・GLM-5.3(Maya)とも、約100万トークンの途中に埋めた合言葉を 11回中11回取り出せた。1M の読み込みは約10〜14分 |
| Claude Code のバックエンド | Anthropic 互換 API をそのまま指定して動く。実在のリポジトリへの機能追加も約3分で完了 |
| 外部への通信 | Maya は外部に出られない Docker ネットワークでも動作し、通常の起動でも外部への接続は無し(客先データ用途の前提を満たす) |
作業環境
- CPU / メモリ: AMD Ryzen 9 9950X3D / 96GB(DDR5-5600 48GB × 2、デュアルチャネル。OS 上 89GiB、swap なし)
- GPU: RTX 4090 24GB + RTX 4000 Ada 20GB(どちらも PCIe 4.0 x8 で接続、NVLink・P2P なし)
- ストレージ: Crucial T500 2TB。検証の途中(検証3の Project Maya 以降)で3枚の btrfs RAID0 に組み替えました(その話は 前回の記事。後述のとおり、今回の測定ではストレージの速さは結果にほぼ影響していません)
- OS: Ubuntu 26.04.1(カーネル 7.0.0-38)、NVIDIA ドライバ 595.99.02(CUDA 13.2)
- 推論エンジン(Ollama 以外は Docker で動かしています)
- llama.cpp b11718(
ghcr.io/ggml-org/llama.cpp:server-cuda) - Ollama 0.40.6
- Strata v0.1.45(Qwen3.8-Flash-Next 向け)、Strata-DualGPU 0.1.38-dual
- Project Maya v1.1.20(Strata 派生。GLM-5.3-Flash と DeepSeek-V4.1-Flash-1017 専用)
- llama.cpp b11718(
- 計測ツールとすべての生データは GitHub に置いています: https://github.com/akivajp/local-llm-bench
VRAM に乗らないモデルを動かすときは、どこに置いた重みを、どの経路で読むかで速度がほぼ決まるので、帯域も実測しておきました(測り方は後述のリポジトリの scripts/hw-bandwidth.sh、root 不要)。
| 経路 | 実測 | 理論値 | 補足 |
|---|---|---|---|
| RTX 4090 の VRAM | 920GB/s | 1,008GB/s | デバイス内コピー |
| RTX 4000 Ada の VRAM | 303GB/s | 360GB/s | 4090 の約1/3 |
| RAM(読み込みだけ) | 63GB/s | 89.6GB/s | DDR5-5600 × デュアルチャネル。8スレッドで最大(理論値の約7割)。書き込みを含む STREAM Triad だと 45GB/s |
| PCIe(RAM → GPU) | 13.4GB/s | 15.75GB/s | 2枚とも Gen4 x8(2枚挿しだとマザーボードが CPU の x16 を x8/x8 に分けるため) |
- アイドル中は、省電力で PCIe が Gen1 に落ちています(
nvidia-smiで x8 / Gen1 と出て一瞬焦りますが、転送が始まれば Gen4 に上がります) - この表から、だいたい次のことが読み取れます。後の結果もほぼこのとおりになりました
- 2枚にレイヤを分けると、4000 Ada が担当する層は VRAM の読み出しが4090 の3倍遅くなる
- RAM に置いたエキスパートを PCIe 越しに GPU へ運ぶ(13.4GB/s)より、CPU でその場で計算した方が速い(RAM から 63GB/s で読める)。Strata・Maya はまさにこの方式で、VRAM に乗らない分は CPU で計算します
比べたモデル
| モデル | 総 / アクティブ | 量子化(サイズ) | VRAM 44GB に |
|---|---|---|---|
| Qwen3.6-35B-A3B | 35B / 3B | UD-Q4_K_XL(22GB) | 乗る(比較用) |
| Qwen3.8-Flash-Next | 125B / 6B | IQ3_S(本体 55GB + n-gram 表 29GB) | 乗らない |
| GLM-5.3-Flash | 321B / 18B | Maya-S24(95GB) | 乗らない(RAM 込みでぎりぎり) |
| DeepSeek-V4.1-Flash-1017 | 748B | Maya-S(340GB) | 乗らない(RAM にも乗らない) |
ほかに gpt-oss-120b、Qwen3.5-122B-A10B、Nemotron 3.5 Super、DeepSeek-V4-Flash も llama.cpp で測っています(後述)。
測り方
- OpenAI 互換 API にストリーミングでリクエストを送り、クライアント側で時間を測りました
- prefill(入力の読み込み)= 入力トークン数 ÷ 最初のトークンが返るまでの時間
- decode(生成)= (出力トークン数 − 1) ÷ 最初から最後のトークンまでの時間
- プロンプトの先頭に毎回ランダムな ID を入れて、プロンプトのキャッシュが効かないようにしています
- 入力は約120トークン / 8K / 32K の3種類。断りがなければ decode は短い入力のときの値です
検証1: VRAM に乗るなら、4090 1枚が一番速い
まずは比較用に、VRAM に全部乗る Qwen3.6-35B-A3B(22GB)です。
| 構成 | decode (tok/s) |
|---|---|
| llama.cpp・4090 だけ | 178 |
| llama.cpp・2枚にレイヤ分割 | 115 |
| Ollama(自動で2枚に分散) | 114 |
- 2枚に分けると、1枚のときより35%遅くなります。レイヤを分けると、4000 Ada が担当する層の読み出し(帯域が 4090 の1/3)がトークンごとに待ち時間になるためです
- Ollama は、1枚に収まるモデルでも2枚に分散するので、同じく遅い側になります
検証2: VRAM に乗らない Qwen3.8-Flash-Next は Strata が3倍速い
本命の1つ目、Qwen3.8-Flash-Next(125B)の IQ3_S です。本体だけで 55GB あるので、VRAM 44GB には乗りません。
| 構成 | decode (tok/s) | 32K の prefill (tok/s) |
|---|---|---|
| Strata・4090 だけ | 143 | 2,456 |
| Strata・4090 だけ(MTP なし) | 100 | 2,528 |
| Strata・2枚 | 100 | 3,314 |
| Strata-DualGPU・2枚 | 106 | 3,236 |
llama.cpp・2枚(--fit) | 41 | 685 |
llama.cpp・4090 だけ(--fit) | 41 | 423 |
| Ollama | 40 | 703 |
- Strata は llama.cpp の3.5倍です。内訳はざっくり次のとおりです
- よく使われるエキスパートを事前のプロファイルで VRAM に置いておく方式で、キャッシュのヒット率はおおむね95%以上。MTP(投機的デコード)を切っても llama.cpp の約2.5倍
- MTP でさらに約1.4倍
- ここでも 2枚より 4090 1枚の方が速いです(143 → 100)。2枚が効くのは長い入力の prefill だけ(+35%)でした
- 2GPU 用のフォーク(Strata-DualGPU)は、RAM が 32GB しかない PC で2枚を使うための工夫が主眼なので、RAM が十分あるこの PC では本家との差は小さめです
- 日本語の随筆やコード生成など、話題を変えるとヒット率が 95% 前後に下がり、decode は 127〜130 tok/s になりました。それでも llama.cpp の3倍以上です
品質も軽く確認しました(GSM8K 30問 + 日本語 MMMLU 40問)。Strata の IQ3_S が 65/70、IQ2_XS が 64/70、同じ重みを llama.cpp で動かすと 63/70 で、エンジンや量子化による大きな劣化は見えませんでした(問題数が少ないので、目安程度です)。
検証3: GLM-5.3-Flash と DeepSeek-V4.1 は Project Maya で実用域に入る
本命の2つ目は、321B の GLM-5.3-Flash と、748B の DeepSeek-V4.1-Flash-1017 です。どちらも Project Maya という、Strata から派生した専用エンジンがあります。
| モデル / エンジン | 4090 だけ | 2枚 | prefill (tok/s) | 品質(30問) |
|---|---|---|---|---|
| GLM-5.3-Flash / Maya(Maya-S24, 95GB) | 38 | 53 | 1,529(32K、2枚) | 27/30 |
| GLM-5.3-Flash / llama.cpp(UD-IQ1_S, 87GB) | 16 | 16 | 153(32K、2枚) | 26/30 |
| DeepSeek-V4.1 / Maya(Maya-S, 340GB) | 19 | 22 | 428(8K、2枚) | 25/30 |
| DeepSeek-V4.1 / llama.cpp(UD-IQ1_S, 233GB) | 13 | 16 | 148(8K、2枚) | - |
(decode は tok/s)
- GLM は Maya で llama.cpp の3.3倍、prefill は10倍。53 tok/s あれば、エージェント用途でもそれほど待たされません
- 748B の DeepSeek-V4.1 も 4090 1枚 + RAM 89GB で 19 tok/s 出ました。ただ、32K の読み込みに1分近くかかるので、普段使いには少ししんどい印象です
- こちらは 2枚の方が速いです。どちらも RAM にすら乗りきらないので、2枚目の VRAM(20GB)にエキスパートを置ける分だけ得をします。Qwen3.8 と逆なのが面白いところ
- GLM の上位の量子化(Maya-M 116GB / Maya-L 156GB)も試しましたが、RAM からあふれた分を SSD から読むようになり、decode が 54 → 35 → 13.5 tok/s と落ちました。30問の範囲では品質差は見えなかったので、この PC では Maya-S24 一択です
参考までに、Strata・Maya が対応していないモデルは llama.cpp で次のとおりでした(2枚、--fit)。
| モデル | decode (tok/s) | 品質(30問) |
|---|---|---|
| gpt-oss-120b(61GB) | 39 | 25/30 |
| Qwen3.5-122B-A10B(UD-IQ4_XS, 57GB) | 31 | 23/30 |
| Nemotron 3.5 Super(UD-Q3_K_XL, 62GB) | 24 | 25/30 |
| DeepSeek-V4-Flash(UD-IQ1_S, 77GB) | 20 | 25/30 |
ちなみに、llama.cpp の --moe-cache-mib(CPU 側に置いたエキスパートを VRAM にキャッシュする、最近入ったオプション)は、Qwen3.8 では +13% でしたが、gpt-oss・Nemotron・GLM では逆に12〜27%遅くなりました。モデルによって効き方が違うので、試してから使うのがよさそうです。
検証4: 100万トークンのコンテキストは現実的
個人的に一番気になっていたところです。約100万トークンの詰め物の途中(先頭から10% / 50% / 90% の位置)に合言葉を1つ埋め、それを答えさせました。
| モデル / エンジン | 32K〜256K | 512K | 約1M | 1M の読み込み | 1M のあとの decode |
|---|---|---|---|---|---|
| Qwen3.8 / Strata(4090 だけ) | 3/3 | 4/4 | 4/4 | 9.5分 | 90〜107 tok/s |
| GLM-5.3 / Maya(2枚) | 3/3 | 4/4 | 4/4 | 14分 | 22〜25 tok/s |
| DeepSeek-V4.1 / Maya(2枚) | 3/3 | 1/1 | 1/1 | 34分 | 19 tok/s |
- Qwen3.8 は学習時のコンテキストが 262K なので、YaRN で4倍に延ばしています。それでも崩れず、100万トークン読んだ後でも 100 tok/s 前後で生成できるのには驚きました
- Qwen3.8・GLM の読み込みは、1M でも 1,200〜1,750 tok/s で、長さに比例して時間が延びるだけです(長くなっても極端に遅くはならない)。とはいえ 1M で10分以上かかるので、大きな資料を一度読ませて会話を続ける使い方向きです
- 確かめたのは「合言葉を1つ取り出す」ことだけです。長い資料の要約など、実際の使い方での精度は別途確認が必要です
- Maya で 1M にする場合は、後述の RAM の余裕の設定が必要でした
検証5: Claude Code のバックエンドにする
Strata も Maya も Anthropic 互換の /v1/messages を持っているので、Claude Code の接続先をそのまま向けられます。
起動例(Maya の場合。ポートは環境に合わせて)
$ ANTHROPIC_BASE_URL=http://127.0.0.1:8080 ANTHROPIC_API_KEY=dummy \ ANTHROPIC_DEFAULT_HAIKU_MODEL=glm-5.3-flash \ claude --model glm-5.3-flashANTHROPIC_DEFAULT_HAIKU_MODELは、Claude Code が裏で使う小型モデル用の呼び出しも同じサーバーに向けるためのものです- 知らないモデル名を指定すると警告が1行出ますが、そのまま動きます
小さな課題(FizzBuzz の実装とテスト、既存コードのバグ修正)と、実在のリポジトリへの機能追加(この計測ツールに CSV 出力を足してテストも書く)を頼み、終わった後にこちらでテストを流して判定しました。
| バックエンド | FizzBuzz | バグ修正 | 機能追加 |
|---|---|---|---|
| GLM-5.3 / Maya(2枚) | 19秒 | 30秒 | 169秒(11ターン) |
| Qwen3.8 / Strata(4090) | 52秒 | 18秒 | 163秒(37ターン) |
- すべて成功し、テストファイルを書き換えてごまかすようなこともありませんでした
- Qwen3.8 は機能追加で、頼んでいない README まで直していました。指示どおりに最小限の変更で済ませるのは GLM の方が得意な印象です
- Claude Code はコンテキストを 200K と見なして動くので、サーバー側はそれより長いコンテキストで起動しておくと安心です
ハマったところ
- llama.cpp の
--fitは、-otを1つでも指定すると黙って無効になる- ログに
tensor_buft_overrides already set by user, abortという W 行が1行出るだけで、全部を GPU に置こうとして OOM になります。VRAM に収まる構成だと気づけません - 配置は
--fitに任せて、-otは付けないのが正解でした
- ログに
- Strata・Maya は空き RAM のほぼ全部を固定する
- Maya の既定では、起動時の空き RAM から 6GB だけ残して全部を pinned memory にします。常駐のプロセスが 8〜9GB ある PC では足りず、4090 1枚のときや 1M コンテキストのときに OOM killer に落とされました。
MAYA_GLM_RAM_HEADROOM_GB=14で解消 - モデルを
HF_XET_HIGH_PERFORMANCE=1でダウンロードしている間(RSS 約 25GB)に起動したときも同じく落ちました。ダウンロードと計測は重ねない方がいいです
- Maya の既定では、起動時の空き RAM から 6GB だけ残して全部を pinned memory にします。常駐のプロセスが 8〜9GB ある PC では足りず、4090 1枚のときや 1M コンテキストのときに OOM killer に落とされました。
- Linux 向けのビルド済みエンジンが無い
- Strata は配布物が Windows 版だけで、Maya はソースからのビルドのみです。CUDA Toolkit を入れていない(入れたくない)ので、
nvidia/cuda:13.0.0-develのコンテナの中でビルド・実行しました。どちらもビルドは数分で終わります - llama.cpp の
server-cuda13イメージは CUDA 13.4 以上のドライバが必要で、595 系では起動しませんでした(server-cudaを使えば OK)
- Strata は配布物が Windows 版だけで、Maya はソースからのビルドのみです。CUDA Toolkit を入れていない(入れたくない)ので、
- チューニングは不要だった
- Maya の
--calibrateは「既定の設定がすでに最速」という結果でした - 下書きモデルの DFlash2 は、この PC では逆に38%遅くなりました。ライセンスも CC BY-NC-ND 4.0(非営利のみ)なので、業務用途ではそもそも使えません
- Maya の
- 同時に複数の要求を処理しても速くならない
- Maya の
--parallel 4で4件同時に送っても、全体の生成速度は1割前後しか伸びず、1件あたりは件数に比例して遅くなりました。エージェントは1つずつ動かした方がよさそうです
- Maya の
- ストレージの帯域は律速になっていなかった
- SSD から読みながら動く DeepSeek-V4.1 で、cgroup(
docker run --device-read-bps)で RAID0 の各 SSD を絞り、SSD 1枚相当(7.2GB/s)にして比べましたが、速度は変わりませんでした。読み込みは平均 3.7GB/s で、1枚でも足りている計算です - 前回の記事でも、モデルのロードは RAID0 でも速くならなかったので、LLM 用途では「SSD を速くするより RAM を増やす」方が効きそうです
- SSD から読みながら動く DeepSeek-V4.1 で、cgroup(
追加投資するなら: RAM 増設か、GPU の入れ替えか
そもそもこのサーバーは、ローカル LLM を快適に動かすことを主眼に組んだものではなく、ローカル LLM「も」現実的に動かせる、汎用性の高い開発サーバーのつもりです(LLM が主眼なら、RTX 4000 Ada はあまり良い候補ではありません)。ローカル LLM の速さだけで言えば、ここまでの結果のとおり今のままでも十分実用になっています。 そのうえで、追加投資するならどこか、という話です。
マザーボードのメモリスロットはあと2つ空いていて、64GB × 2 を足せば RAM は 96 + 128 = 224GB になります。ただ、メモリの価格が高騰していて、2026年10月時点の新品は 48GB × 2 が約26万円〜、64GB × 2 が約40万円〜(今の 48GB × 2 は2年半前に約4.5万円でした……)。40万円あれば、価格高騰の今でもそこそこの GPU が買えるので、なかなか悩ましいところです。今回の結果から考えると、次のような整理になりました(数字の一部は推定です)。
- RAM の増設: 汎用サーバーとしてはありがたいが、4枚挿しで帯域が落ちる
- VM・コンテナ・ビルド・大きなデータの処理など、LLM 以外の用途にも直接効きます。今あるパーツに足すだけなので、無駄になるものもありません
- ただし、AMD の公称値は2枚なら DDR5-5600 ですが、4枚(2R)だと DDR5-3600 です(AMD の製品ページ)。それより上はオーバークロック扱いで、マザーボードやメモリとの相性次第。容量の違うキットを混ぜるならなおさらです。3600 だと理論値は 57.6GB/s で、実効の読み込みは今の 63GB/s から 40GB/s 前後に落ちる見込みです
- LLM について言うと、GLM-5.3-Flash(Maya-S24、2枚)はすでに RAM と VRAM に全部乗っていて、SSD からは読んでいません。VRAM に無いエキスパートは CPU で計算しているので、RAM が遅くなる分、今の構成はむしろ少し遅くなるおそれがあります
- 代わりに、GLM の上位の量子化(Maya-M / Maya-L)が全部乗る、DeepSeek-V4.1 が SSD から読まずに済む、GLM-5.3 本体(Flash でない方。GGUF で 217〜254GB)を動かせる、といった「動かせるモデルの幅」は広がります。ただ、今回の30問では量子化による品質差は見えず、GLM-5.3 本体は今のところ llama.cpp でしか動かないので、一桁 tok/s 台になりそうです。Kimi-K3 は最小の量子化でも 466GB あるので、224GB でも乗りません
- GPU の入れ替え: LLM の高速化には一番効くが、「交換」になる
- ローカル LLM を速くするのが目的なら、4000 Ada より速い GPU か、VRAM の多い GPU(1〜2世代前の型落ちなど)に替える方が効果が大きいのは間違いなさそうです。今回は、遅い2枚目(VRAM 303GB/s)がレイヤ分割の足を引っ張っていたので、それが消えるうえ、VRAM が増える分だけエキスパートのヒット率も上がります
- ただ、速く使えるスロットは x8/x8 の2つだけなので、買い足しても「増設」ではなく「4000 Ada との交換」になり、外した 4000 Ada の扱いに困ります
- 200GB を超えるモデルは、GPU を替えても乗りません
| 観点 | RAM を 224GB に | GPU の入れ替え |
|---|---|---|
| 汎用サーバーとしての使い勝手(LLM 以外) | ◎ | △ |
| 既存パーツの扱い | ○(足すだけ) | △(4000 Ada が余る) |
| 今の主力(GLM-5.3-Flash、Qwen3.8)の速度 | △(RAM が遅くなり、少し落ちるおそれ) | ◎ |
| 動かせるモデルの幅(200GB 超など) | ○(llama.cpp で低速) | ✕ |
| Kimi-K3 級(466GB〜) | ✕ | ✕ |
ローカル LLM の高速化だけが目的なら GPU の入れ替えですが、汎用サーバーとして見ると、帯域が落ちるのは痛いものの RAM の増設の方が素直にありがたい、という悩ましい結論です(価格さえ落ち着いてくれれば……)。 4枚挿しにしたときの速度の低下は、BIOS でメモリを DDR5-3600 に落として測り直せば買わずに確かめられるので、続編ではまずそこから試してみるつもりです。
まとめ
- VRAM に乗らない大きな MoE は、汎用の llama.cpp / Ollama より、モデル専用の推論エンジン(Strata、Project Maya)が生成で3倍強、入力の読み込みで最大10倍速い
- Qwen3.8-Flash-Next は 4090 1枚で 143 tok/s、GLM-5.3-Flash は2枚で 53 tok/s。どちらも「普通に使える」速度です
- 異種の2枚(4090 + 4000 Ada)は、モデルが RAM に乗るなら1枚の方が速い。RAM にも乗らない大きなモデルや、長い入力の prefill では2枚が効きます
- 100万トークンのコンテキストも現実的で、Claude Code のバックエンドとしても動きました
- 用途ごとの使い分けとしては、長い資料や速さ重視なら Qwen3.8 + Strata(1枚で済む)、エージェントに作業を任せるなら GLM-5.3 + Maya(2枚)、という感じに落ち着きました
続編でやってみたいこと:
- 長い資料の要約など、実際の使い方での精度と、クラウドのモデルとの比較
- ログやダッシュボードにプロンプトの本文が残らないかの確認(機密データを扱う前提で)
- 常駐の別サービスと GPU を分け合いながら動かす運用
- 長時間・多数のタスクを連続で任せたときの安定性
- 消費電力と、100万トークンあたりの電気代(API 料金との比較)
- メモリを DDR5-3600 に落としたときの速度の低下(4枚挿しの影響)と、RAM 増設・GPU 入れ替えの実際の効果
お疲れ様でした!