
284B の DeepSeek V4 Flash-0731 を DGX Spark 2 台で動かしてみた
はじめに
こんにちは、クラスメソッド製造ビジネステクノロジー部の森茂です。
284B のモデルを手元で動かす、と聞いてどのくらいの速度を想像するでしょうか。8 月頭に DeepSeek V4 Flash-0731 を DGX Spark 1 台で動かす記事を書いたときは、2-bit まで落として 20 tok/s ほどでした。読める速さではありますが、待たされる感じは残ります。
同じモデルを 2 台に広げたらどうなるか、というのが今回の話です。1 台では載らなかった 4-bit の GGUF と、DeepSeek 公式の FP8 チェックポイントを、それぞれ別のスタックで動かしてみました。
実はこの 2 台構成、6 月末にも一度組んでいます。当時は preview 系の DSpark 版で、コード生成の thinking を切って 55 tok/s、長文は 247K トークンを読ませた時点で 2.4 tok/s まで落ちていました。しかもその 55 tok/s は curl で直接叩いたときの値で、OpenAI 互換のクライアントからは空応答に見えるという制約つきです。
それから 2 か月足らずで、モデルも動かし方もそっくり入れ替わりました。モデルは公式リリースの 0731 になり、レシピは独自パッチを当てなくても起動するようになり、ノード間は MTU 9000 の RDMA でつながっています。同じ 2 台の箱で測り直したら、数字がまるで違いました。
先に結論を書いておくと、284B が手元で実用になりました。公式 FP8 を vLLM で動かすと decode が 76 tok/s 出ます。人が黙読する速度よりだいぶ速いので、生成を待っている感覚がほぼありません。90 万トークンのプロンプトも通り、6 人で同時に叩いても合計 210 tok/s を保ちます。ツール呼び出しもコードの修正タスクも、手元のハーネスでは全部通りました。
これがクラウドの API ではなく、机の上の箱 2 つで動いています。
この記事では、DGX Spark 2 台で DeepSeek V4 Flash-0731 を動かす 2 つの構成を実測で比べ、用途ごとにどちらを選ぶかを整理します。ローカル LLM をどこまで実務に寄せられるか気になっている人に刺さるといいなと思っています。
2 台にすると選択肢がどう増えるか
DeepSeek V4 Flash-0731 は 284B のうち 13B が稼働する MoE モデルです。手に入る形は 2 通りあって、Unsloth の GGUF と、DeepSeek 公式の safetensors です。
GGUF は量子化のバリエーションが豊富で、サイズと 1 台に載るかどうかは次のようになります。GB と GiB を混ぜると判断を誤るので両方書いておきます。DGX Spark の「128GB」は OS から見ると 121 GiB です。
| 量子化 | GB (10^9) | GiB | 1 台(121 GiB) |
|---|---|---|---|
| UD-IQ2_M | 90.9 | 84.68 | ✅ |
| UD-IQ3_XXS | 104.2 | 97.1 | ✅ |
| UD-IQ3_S | 116.1 | 108.1 | ✅ 上限 |
| UD-Q3_K_XL | 128.2 | 119.4 | ❌ |
| UD-IQ4_XS | 136.7 | 127.3 | ❌ |
| UD-Q4_K_XL | 155.1 | 144.44 | ❌ |
今回 1 台だけで動かせたのは UD-IQ3_S までで、その次の UD-Q3_K_XL は 119.4 GiB あって KV キャッシュの置き場が残りません。つまり 1 台構成の実用上限は 3-bit です。
一方、公式の safetensors は 1 種類しかありません。
こちらは 166.9 GB、GiB になおすと 155.43 GiB で 48 シャードです。FP8 に MoE 部分の FP4 が混ざった形式で、量子化を選ぶ余地はありません。当然 1 台には載らないので、これを動かすこと自体が 2 台構成の理由になります。
整理すると、2 台にして手が届くのは「4-bit の GGUF」と「公式 FP8」の 2 つです。とくに後者は量子化なしの公式配布物なので、ローカルで動かす前提だとここが天井になります。
llama.cpp で 4-bit を 2 台に分ける
llama.cpp には RPC バックエンドがあって、別のマシンで動かした ggml-rpc-server にレイヤーを預けられます。クライアント側だけが GGUF を持っていればよく、テンソルはネットワーク越しに送られます。今回はモデルのダウンロードがクライアント側だけで済みました。後で出てくる vLLM は両ノードに 167 GB ずつ必要なので、ここは地味に効いてきます。
起動はクライアントとワーカーを別々に立てます。2 台目でワーカーを待たせておき、1 台目からクライアントを叩く形です。
ggml-rpc-server --host 192.168.200.14 -p 50052 -c
llama-server -m DeepSeek-V4-Flash-0731-UD-Q4_K_XL-00001-of-00005.gguf \
--rpc 192.168.200.14:50052,127.0.0.1:50052 \
-ngl 999 -sm layer --no-mmap --cache-ram 0 \
-c 32768 -np 1 --host 127.0.0.1 --port 8080
1 台目でもワーカーを 1 つ立てて、自分の GPU も RPC 経由で使わせています。こうするとどちらのノードも同じ扱いになり、レイヤーが素直に分かれます。
ノード間は QSFP のケーブルで直結していて、200 Gb/s のリンクに MTU 9000、往復 0.7 ミリ秒です。llama.cpp は libibverbs を見つけるとビルド時に RDMA を組み込むので、起動すると勝手に RoCEv2 でつながります。
RDMA probed: dev=rocep1s0f1 gid=3 RoCEv2 qpn=595 inline=316
RDMA activated: qpn=595->595 mtu=4096 rx_depth=24
GID のインデックス選びは以前は手で指定していたところですが、今は自動で解決してくれました。
144.44 GiB のモデルは 401 秒かけて読み込まれ、1 台目に 101 GB が乗る形に落ち着きました。レイヤー分割なので厳密な折半にはなりません。
ここで 1 つ、組む前に知っておきたいことがあります。2026 年 8 月時点の llama.cpp 本体では、ワーカーを 2 つ以上つなぐと推論が始まった瞬間に落ちます。未マージの PR #26500 を当てると通ります。自分もこれで半日ぶんの遠回りをしたので、経緯を畳んでおきます。
ワーカーが 2 つあると落ちる話
壁 1: 推論の 1 手目でワーカーが落ちる
モデルの読み込みは通るのに、そこから先で落ちます。クライアント側はこう出ます。
ggml/src/ggml-rpc/ggml-rpc.cpp:519: Remote RPC server crashed or returned malformed response
ワーカー側のログはこうでした。
[create_node] invalid data ptr[graph_compute] failed to create graph node 3085
切り分けると 2 つのことがわかりました。落ちるのはリモートのワーカーだけで、同じマシンで動いている loopback のワーカーは無傷です。そしてワーカーを 1 つに減らすと落ちません。
同じ症状が Issue #26820 に上がっていて、モデルまで 0731 で一致していました。報告者は Windows の CPU で 8 ワーカー、自分は Linux の CUDA で 2 ワーカーなので、環境に依存しない話のようです。
修正は PR #26500 にあります。他のサーバが持っているバッファのポインタまでシリアライズしてしまい、受け取った側で解決できなくなる、という内容でした。当てたら通りました。実測値を添えて Issue に報告してあります。
壁 2: 2 リクエスト目でサーバが落ちる
llama-bench は通るのに llama-server が 2 リクエスト目で落ちる、という症状も踏みました。これは Issue #26529 にある --cache-ram 0 で解決します。付けないと 2 回目のリクエストで abort します。
vLLM で公式 FP8 を 1M コンテキストで動かす
もう 1 つの経路は vLLM です。公式の FP8 チェックポイントをテンソル並列で 2 台に分けます。ゼロから組むのは骨が折れるので、公開されているレシピを使いました。
DGX Spark 2 台を前提にした構成一式で、Docker Compose と起動スクリプトが揃っています。中で使うイメージは Anemll が公開している GB10 向けの vLLM ポートです。
レシピの既定値をそのまま使いました。max_model_len は 1,048,576、max_num_seqs は 6、KV キャッシュは nvfp4_ds_mla、投機デコードの DSpark が 5 トークンで有効になっています。変えたのは thinking を明示的に切ったところだけです。
起動時のログから、確保できた KV の量がわかります。
Available KV cache memory: 12.34 GiB (TP0) / 12.05 GiB (TP1)
GPU KV cache size: 1,789,449 tokens
Maximum concurrency for 1,048,576 tokens per request: 1.71x
179 万トークンぶんの KV が乗りました。1M のリクエストなら 1.71 本ぶんの余裕がある計算です。メモリは 1 台目が 108 GB、2 台目が 107 GB でほぼ均等でした。テンソル並列なので、レイヤー分割の llama.cpp と違ってきれいに半分ずつになります。
セットアップのコストは llama.cpp より重めです。イメージが 9.79 GB、モデルが 167 GB でこれを両ノードに置く必要があり、Hugging Face のキャッシュ配置にも作法があります。手元では hf download --revision <sha> で落としたところ refs/main が作られず、オフラインモードでスナップショットを見つけられませんでした。リビジョンを固定して落とすなら、refs/main を自分で書いておくと素直に動きます。
とはいえ、6 月末に同じことをやったときと比べると格段に楽になっています。当時と今で何が変わったかを並べるとこうなります。
| 項目 | 2026 年 6 月末 | 今回 |
|---|---|---|
| モデル | DSpark 版(preview 系) | 公式リリースの 0731 |
| レシピ | 独自パッチ 3 点が必須 | パッチなしで起動 |
| イメージ | 自前ビルド 22.7 GB | 配布イメージをそのまま |
| ノード間の設定 | GID インデックスを手で指定 | 起動時に自動解決 |
| コンテキスト既定 | 262K | 1M |
| 同時リクエスト | 1(並列は動かず) | 6 |
| 長文の decode | 247K で 2.4 tok/s | 900K で 69.04 tok/s |
| クライアント互換 | thinking を切ると空応答 | そのまま content が返る |
6 月末の値は当時の記事に載せたもので、今回のように測り直したわけではありません。モデルが preview 系から公式版に替わっているので厳密な比較にはならないのですが、プロンプトが 3.6 倍長いのに 28 倍速いという差はさすがに誤差では説明できないと思います。KV キャッシュの形式が nvfp4_ds_mla に変わったこと、vLLM 側が 0.25 系に上がったこと、GB10 向けのポートが整ったことが重なった結果でしょう。どれがどれだけ効いたかまでは切り分けていません。
4 つの軸で比べてみる
ここからが本題です。速度、長文、同時アクセス、品質の順に見ていきます。
速度はスタックの選び方で 3.8 倍変わる
まず llama.cpp で、同じ量子化を 1 台と 2 台で測りました。ハーネスは 1 台編で使ったものをそのまま流用しています。コンテキスト 2,048 トークン、生成 128 トークン、3 回の中央値です。
| 量子化 | GiB | 1 台 decode | 2 台 decode | decode 比 | prefill 比 |
|---|---|---|---|---|---|
| UD-IQ2_M | 84.68 | 20.13 | 19.58 | 0.973x | 0.846x |
| UD-IQ3_S | 108.1 | 18.02 | 17.69 | 0.982x | 0.859x |
| UD-Q4_K_XL | 144.44 | 載らない | 16.54 | — | — |
目を引くのは decode 比のほうです。2 台に分けても decode は 0.97 倍から 0.99 倍しか落ちません。分散のコストがほとんど無い、と言い換えてもいいと思います。レイヤー間で送るデータが 1 層あたり数十 KB と小さく、往復 0.7 ミリ秒のリンクなら埋もれてしまうからでしょう。prefill は MB 級を動かすので 0.85 倍から 0.90 倍とやや落ちますが、こちらもコンテキストが伸びるほど差が縮みます。
2 月に DGX Spark 2 台をつないだ記事では、Qwen3-235B で 6% ほど落ちていました。当時とはモデルが違うものの、劣化の幅は 2% まで縮んでいます。RDMA が入ったぶんが効いているのかもしれません。
そのうえで、量子化を上げるコストを見ます。同じ 2 台構成での比較です。
| 量子化 | GiB | decode tok/s | UD-IQ2_M 比 |
|---|---|---|---|
| UD-IQ2_M | 84.68 | 19.58 | — |
| UD-IQ3_S | 108.1 | 17.69 | −9.7% |
| UD-Q4_K_XL | 144.44 | 16.54 | −15.5% |
1 台の上限だった 3-bit(18.02)と、2 台でしか動かない 4-bit(16.54)の差は 8.2% です。8% ぶんの速度で量子化が一段上がる、という交換になります。
ところがここに投機デコードが乗ると話が変わります。llama.cpp 本体には 8 月 2 日に DSpark の投機デコードがマージされていました。1 台編を公開したのと同じ日です。あの記事には「本体には入っていません」と書いたので、公開した時点で古くなっていたことになりますね。
--spec-type draft-dspark で有効にすると、こうなりました。
| ctx | 投機なし | 投機あり | 差 |
|---|---|---|---|
| 2,048 | 16.54 | 20.03 | +21.1% |
| 8,192 | 16.37 | 17.80 | +8.7% |
| 32,768 | 15.39 | 18.19 | +18.2% |
4-bit に投機を乗せると 20.03 tok/s で、1 台の最速構成だった 2-bit の 20.13 とほぼ並びます。同じ速度のまま 2-bit が 4-bit になる、という見方ができます。
ただし正直に書いておくと、投機の効きは内容によってかなり振れます。ドラフトの採択率をログから拾うと 0.34 から 0.95 まで散らばっていて、平均の長さも 2.68 から 5.77 トークンの間を動きます。何回か回して中央値を取らないと、都合のいい数字を拾ってしまいそうです。
一方の vLLM は桁が違いました。
| プロンプト長 | TTFT | prefill tok/s | decode tok/s |
|---|---|---|---|
| 2,048 | 1.10s | 1,881.0 | 75.6 |
| 8,192 | 4.31s | 1,904.6 | 76.0 |
| 32,768 | 21.3s | 1,539.5 | 71.1 |
decode で 76 tok/s、prefill は 1,900 tok/s 前後です。llama.cpp の 4-bit に投機を乗せた 20.03 と比べると 3.8 倍になります。
76 tok/s がどのくらいかというと、日本語で読み上げるより明らかに速い速度です。生成が終わるのを待つ、という感覚がほとんどありません。284B のモデルをローカルで動かしてこの速度が出るのは、正直なところ想像していませんでした。
数字を並べるときに 1 つ注意があって、この 2 つは重みも量子化方式も違います。llama.cpp 側は 4-bit の K-quant で 144.44 GiB、vLLM 側は FP8 に MoE の FP4 が混ざった形式で 155.43 GiB です。投機の実装も別物で、vLLM のほうは MTP が既定で有効になっています。エンジンの優劣というより、スタックの選択でここまで変わる、と読むのが正しいと思っています。
長いコンテキストは TTFT だけが伸びる
vLLM で 1M を謳っているので、実際にどこまで通るか投げてみました。90 万トークンのプロンプトです。
| プロンプト長 | TTFT | prefill tok/s | decode tok/s |
|---|---|---|---|
| 2,048 | 1.10s | 1,881 | 75.6 |
| 8,192 | 4.31s | 1,905 | 76.0 |
| 32,768 | 21.3s | 1,540 | 71.1 |
| 131,072 | 77.6s | 1,690 | 64.8 |
| 900,020 | 863s | 1,043 | 69.04 |
プロンプトが 440 倍になっても decode はほとんど落ちません。2,048 の 75.6 に対して 900K で 69.04 なので、8.7% 減にとどまります。伸びるのは TTFT のほうで、90 万トークンだと最初の 1 文字まで 14 分半かかりました。

上が decode で、2K の 75.6 から 900K の 69.0 までほぼ水平のまま。下が TTFT で、両対数のグラフでほぼ直線になっている。つまりプロンプト長に比例して待ち時間だけが伸びる。
長文用途の制約は速度ではなく待ち時間だ、ということですね。リポジトリを丸ごと読ませて質問する、といった使い方なら、投げてお茶を淹れて戻ってくる感覚になります。走り出してからは速いので、体感の悪さは最初だけです。
なお、レシピの公称値では 90 万トークンの TTFT が 1,028 秒、prefill が 875 tok/s とされていました。手元では 863 秒の 1,043 tok/s だったので、公称よりやや速く出ています。
llama.cpp 側は 32,768 までしか測っていません。こちらもコンテキストを伸ばしたときの decode の落ち方は 2 台のほうが緩やか(0.98 倍を維持)でしたが、1M クラスは試していないので、長文なら vLLM という整理にしています。
同時アクセスは 12 人でも頭打ちしない
チームで 1 セット共有する、という使い方を想定して同時リクエストを増やしてみました。llama.cpp の 4-bit で、スロットを 12 個用意した構成です。
| C | 合計 tok/s | 1 人あたり tok/s |
|---|---|---|
| 1 | 14.95 | 14.95 |
| 2 | 24.80 | 12.45 |
| 4 | 36.17 | 9.06 |
| 8 | 46.40 | 5.81 |
| 12 | 61.17 | 5.11 |
12 並列まで全リクエストが成功し、合計スループットはまだ伸びていました。1 台編では 8 並列の 57.93 tok/s が天井で、12 並列では 56.89 と下がっていたので、そこは対照的です。ただしエンジンも量子化も違うので、数字そのものを引き算しないでください。
1 人あたりで見ると 12 人で 5.11 tok/s まで落ちます。読んでいる間に次の行が出てくる、くらいの速度なので、待てるかどうかは用途次第ですね。
vLLM 側も 6 並列まで測りました。短いプロンプトなら合計 210.8 tok/s まで出ます。
| プロンプト長 | C | 合計 tok/s | 1 人あたり tok/s |
|---|---|---|---|
| 256 | 6 | 210.8 | 39.0 |
| 2,048 | 6 | 151.6 | 34.9 |
| 8,192 | 6 | 81.3 | 25.7 |
| 32,768 | 6 | 27.6 | 10.3 |
短い問い合わせを何人かで叩く用途に強く、コンテキストが伸びると並列の旨みが消えていきます。32,768 まで来ると 6 並列の合計 27.6 tok/s が単発の 18.0 とほとんど変わりません。長文と並列は KV を食い合うので、どちらかに寄せる設計になります。

どちらも並列を増やすほど合計が伸び、頭打ちの気配がない。vLLM はプロンプト 2,048 の行、llama.cpp は 4-bit GGUF の測定で、重みもエンジンも違うため水準の比較には使えない。
品質はスコアでは差が出なかった
量子化を上げた価値を見たかったので、1 台編と同じ品質ハーネスを両方に当てました。5 課題の機械判定、ツール呼び出し、そして 3 か所にバグを仕込んだ小さな Python リポジトリをテストが通るまで直させるタスクです。
| ハーネス | llama.cpp UD-Q4_K_XL | vLLM 公式 FP8 |
|---|---|---|
| smoke(5 課題) | 5/5 | 5/5 |
| ツール呼び出し | 6/6 | 6/6 |
| エージェント動作 | 解決、5 ターン | 解決、4 ターン |
| コード修正 | 5/5、71.5秒 | 5/5、18.3秒 |
スコアはすべて同じでした。正直なところ、このハーネスでは「量子化を上げた価値」を示せていません。1 台編の 3-bit も同じく満点だったので、両方満点では差がつかないわけです。壊れていないことの確認にはなりますが、それ以上のことは言えません。エージェント動作のターン数が 5 と 4 で分かれてはいますが、どちらも 1 回ずつしか回していないので、ここから優劣を読むのは無理があります。
差が出たのは所要時間のほうで、コード修正タスクの実時間が 3.9 倍違いました。これは decode 速度がそのまま出たもので、何ターンも往復するエージェント的な使い方だと待ち時間が 4 分の 1 になります。同じ結論にたどり着くとしても、体感はかなり変わりそうですね。
用途別にどれを選ぶか
ここまでの実測をまとめると、選び方はこうなります。
| 用途 | 構成 | 根拠 |
|---|---|---|
| 単発の速さ | vLLM + 公式 FP8 | decode 76 tok/s |
| 長文を丸ごと読ませる | vLLM + 公式 FP8 | 90 万トークンが通り、decode は 69 維持 |
| 短文を何人かで叩く | vLLM + 公式 FP8 | 6 並列で合計 210.8 tok/s |
| 長めの入力を共有する | llama.cpp + GGUF | 12 並列で合計 61.17 tok/s、頭打ちなし |
| 量子化を選びたい | llama.cpp + GGUF | 2-bit から 4-bit まで差し替え可 |
| 手軽に立てたい | llama.cpp + GGUF | バイナリと GGUF だけ、1 台目のみに配置 |
| まず 1 台で試す | llama.cpp + UD-IQ2_M を 1 台 | 20.13 tok/s。2-bit なら 1 台で足りる |
個人的には、常用するなら vLLM のほうかなと思っています。速度も長文も並列も上で、投機デコードが最初から効いています。ただしセットアップは重く、167 GB を両ノードに置いて Docker で立てる前提です。
llama.cpp は逆に、軽さと差し替えやすさが持ち味です。量子化を落として速度を取るか上げて品質を取るかを自分で決められて、モデルはクライアント側にあれば足ります。試している最中や、いろいろな量子化を比べたい段階ではこちらが向いていそうです。
どちらを選ぶにしても、手応えとして残ったのは「284B がローカルで実務に耐える」ことでした。ツール呼び出しが 6/6 通り、テストが落ちる Python リポジトリを 5 ターンで直しきり、リポジトリ 1 個ぶんに相当する 90 万トークンを読ませても答えが返ってきます。これがネットワークの向こうではなく、電源とケーブルが見える範囲で動いているのは、扱うデータによってはかなり効いてくるはずです。
まとめ
DGX Spark 2 台で DeepSeek V4 Flash-0731 を動かし、llama.cpp と vLLM の 2 つの構成を比べました。
284B のモデルが、机の上の 2 台で実用速度になりました。公式 FP8 を vLLM で動かすと decode 76 tok/s、90 万トークンのプロンプトが通り、6 人で同時に叩いても合計 210 tok/s です。品質のハーネスもすべて通りました。1 台では 3-bit で止まっていたところが、4-bit と公式 FP8 まで届きます。同じモデルを 2 台に分けるコスト自体は decode で 2% ほどで、思ったより小さいものでした。
できなかったことも書いておきます。llama.cpp 側は 32,768 までしかコンテキストを伸ばしておらず、1M クラスは未検証です。品質は 4 つのハーネスすべてで満点が並んでしまい、量子化の差を測れませんでした。もっと難しいタスクを用意しないと、この軸は埋まらなそうです。あと -sm tensor を RPC 越しに使う実装が PR #26610 で来ているのですが、今回のビルドでは動かせませんでした。これが本体に入ると 2 台の速度の話が変わるかもしれません。
参考リンク
- unsloth/DeepSeek-V4-Flash-0731-GGUF
- deepseek-ai/DeepSeek-V4-Flash-0731
- MiaAI-Lab/DeepSeek-v4-Flash-DSpark-2x-DGX-Spark — DGX Spark 2 台向けの vLLM レシピ
- Anemll/dspark-vllm-gx10 — GB10 向けの vLLM ポート
- llama.cpp PR #26500 — 複数ワーカーでのバッファ参照の修正
- llama.cpp Issue #26820 — 同じ症状の報告
- llama.cpp Issue #26529 —
--cache-ram 0の話 - DeepSeek V4 Flash-0731 を llama.cpp で DGX Spark 1 台に載せてみた(2026-08-02 公開)
- DGX Spark 2 台をクラスタケーブルでつないでみた(2026-02 公開)







