RTX3090(VRAM 24GB)で Qwen3.8-27B を動かしながら、推論エンジン(学習済みモデルを実際に動かして応答を出すソフト)を llama.cpp と EXL3 で同じ条件に揃えて測り直した。
先に言っておくと、この記事は「どれが速いか」の話じゃない。測ってみたら負荷の形で勝ち負けが入れ替わったので、「どの使い方なら、どれが勝つか」の話になった。
先に結論だけ
- 1本のリクエストを最速で回したいなら llama.cpp。 prefill が +17%、decode も +17% 速い。素の速度は llama.cpp が勝つ
- 並列処理を優先するなら EXL3。 メイン処理とサブ処理を同時に2つ走らせると 、1つの処理で2段階分けた5.2秒 → 2.4秒 で 2.2倍。素の速度で負けているのに分割作業だと速度は逆転する
- 逆転の原因は KVキャッシュの配り方ひとつ。 llama.cpp は並列数で固定分割する。(例:262Kなら2並列なら131Kと131Kに分かれる。)、1本しか走っていなくても残り半分が使えない。EXL3 は共有プールから必要な分だけ取る。(例:262Kを実際の利用状況に応じて共有プールの考えで配って使える。lamma.cppにも–kv-unifiedで共有プールあるが罠がある)
- llama.cpp の
--kv-unifiedは罠。 共有プールで柔軟にはなるがPrefill Cacheが無効になるのでエージェント用途などだと毎回プロンプトを全文読み直すことになり、スロット同士がキャッシュを追い出し合って、短い応答のスループットが 146.4 → 39.9 req/分(3.7倍の劣化)まで落ちた - 並列にしても速くならないこともある。prefill が支配しているとき。 長文プロンプトだと 4並列で 0.66倍、つまり遅くなる。エンジンの問題ではないので、エンジンを替えても直らない。なるべく作業を小分けすることで、無理にQwenなどが262K上限だからと長文になるほど処理速度と品質は落ちる。
- RTX 40xx やRTX50xxを持っているなら vLLM を見た方がいい。 ただし40xx は FP8、50xx が NVFP4。50xxの方がコンテクスト(KV)の圧縮つまり量子化がFP4まで使えるのでKVをかなり有利に使える。RTX3090でvLLMを使わない、、使えない??並列処理もしたいからEXL3を試している理由はそこ。。RTX3090が2枚あるひとはvLLMを使っている例はあります。自分は1枚しかないのでそれをどう活用するかの話です
数字は全部この構成での自前実測で、n=1・単一GPU。環境が違えば当然変わる。
その前に、3つがどういうものか
いきなり数字を並べる前に、そもそもこの3つが何者なのかを短く。作っているところも、狙っている場所も、完成度もバラバラで、それが後半の結果にそのまま出てくる。
| llama.cpp | EXL3(ExLlamaV3) | vLLM | |
|---|---|---|---|
| 作っているのは | ggml-org Georgi Gerganov が始めたプロジェクト | turboderp-org 個人開発 | UC バークレー発 現在は PyTorch Foundation 傘下 |
| ライセンス | MIT | MIT | Apache-2.0 |
| 狙っている場所 | とにかく幅広いハードで動かす | 消費者向けGPUに絞る | 本番のサービング |
| 成熟度 | 枯れている | 開発途上を公言 | 商用で使われている |
llama.cpp ── 動かないハードを探すほうが難しい
「最小限のセットアップで、幅広いハードウェア上で最先端の性能を出す」ことを目標に掲げているC/C++のプロジェクト。掲げているだけじゃなく実際そうなっていて、Apple Silicon(Metal)、NVIDIA(CUDA)、AMD(HIP)、Intel(SYCL)、汎用の Vulkan、さらに RISC-V まで対応している。
量子化(モデルの数値の精度を落として軽くすること)は1.5bitから8bitまで。GGUFという配布形式はここ発で、いまローカルLLMの世界で一番よく見るファイル形式になっている。Ollama や LM Studio のような「簡単に使えるアプリ」も、中身はこれを使っていることが多い。
迷ったらここから始めていい。枯れているし、情報も一番多い。
EXL3(ExLlamaV3)── 消費者向けGPUだけに全振りしている
公式の説明が「モダンな消費者向けGPUでローカルLLMを動かすための推論ライブラリ」で、最初から手元のゲーミングGPUしか見ていない。サーバー向けの都合を切り捨てているぶん、24GBに何をどう詰めるかという設計が素直に効いてくる。
EXL3という独自の量子化形式を持っていて、これは Cornell RelaxML の QTIP を元にしたもの。ヘシアン(モデルの重みの効き具合を表す行列)をその場で計算する方式で、1ステップでモデルを変換できるのが売り。
ただし、ここは正直に書いておきたい。作者自身がREADMEで開発途上だと明記している。「最初のうちは多少壊れているものがあると思ってほしい」と書いてあるし、もっと重要なのが次の一文。
it still needs some work to achieve the same efficiency on Ampere GPUs
ExLlamaV3 README(Ampere = RTX 30xx 世代)
この記事で使っている3090は、まさにその Ampere。後半で「素の速度は llama.cpp が17%速い」という結果が出るけど、その一部はここで説明が付くと思っている。40xx以降で測ったら差が縮む可能性がある、ということは頭に置いておいてほしい。
vLLM ── 本番でリクエストをさばくために作られている
UCバークレーの Sky Computing Lab で生まれて、2025年5月に PyTorch Foundation のホステッドプロジェクトになった。個人や一研究室のものから、中立なガバナンスの下に移ったということ。コントリビューターは1000人を超えている。
中核が PagedAttention。KVキャッシュ(AIが会話の途中経過を覚えておくメモリ)をOSの仮想メモリみたいにページ単位で管理する仕組みで、これが後半で出てくる「KVをどう配るか」の話とまっすぐつながっている。ほかにも連続バッチ処理、プレフィックスキャッシングと、同時に大量のリクエストをさばくための機能が揃っている。
要するに「1人で使う」ではなく「サービスとして提供する」ための道具。ただ、後半の世代の話で書くけど、この強さを引き出せるかどうかは手元のGPUの世代でかなり変わる。
なお今回 vLLM は測っていない。手元が3090と3060なので、条件を揃えた比較ができなかった。この記事の実測は llama.cpp と EXL3 の2つ。
何を測ったのか
- GPU:RTX3090 24GB(サブで RTX3060 12GB)
- モデル:Qwen3.8-27B(3060 側は Qwen3.5-9B)
- エンジン:llama.cpp と EXL3(ExLlamaV3。消費者向けGPU向けの推論エンジン)
- 量子化ビット数は両者で揃えた
用語だけ先に。prefill は送った文章を読み込む工程、decode はそこから1文字ずつ生成していく工程。この2つは性質が全然違うので、分けて測らないと話が噛み合わない。
素の速度は llama.cpp が速い。それでも EXL3 に移した
| 項目 | llama.cpp | EXL3 |
|---|---|---|
| prefill (tok/s) | 1,160 | 995 |
| decode 単発 (tok/s) | 59.3 | 63.1 |
| decode 4並列 (tok/s) | 142.2 | 121.8 |
| 1本の最大文脈 | 131,072(硬い上限) | 190,000 |
| メイン+サブ同時 | 5.2 s | 2.4 s |
| vision 4並列 (req/分) | 32.7 | 42.6 |
prefill も 4並列 decode も llama.cpp が 17% 速い。それでも自分は EXL3 に移した。差の 17% を捨ててでも取る価値があったのが、次の話。
分かれ目は KVキャッシュの配り方だった
KVキャッシュは、AIが会話の途中経過を覚えておくためのメモリ。文脈が長いほど食う。24GB しかないので、これをどう配るかが全部を決める。
llama.cpp は並列数で固定分割する
--parallel 2 で 262,144 を分割
[ 131,072 ][ 131,072 ]
1本しか走っていなくても、もう半分は使えない
2本ぶんに割ったら、1本しか動いていない時間帯でも残り半分は遊んだままになる。エージェントは「メインが長い調査をしている間、サブがちょこちょこ動く」みたいな偏った使い方をするので、この固定分割と相性が悪い。
--kv-unified は柔軟になるが、キャッシュを壊す
llama.cpp にも共有にするオプションがある。試したら柔軟にはなった。ただしスロット同士が prefix cache(前回と同じ前置きを使い回す仕組み)を追い出し合う。
TTFT(最初の1文字が返るまでの時間) 0.25s → 4.8〜5.5s
短い応答のスループット 146.4 → 39.9 req/分(3.7倍の劣化)
エージェントは system プロンプトとツール定義という同じ前置きを毎回送る。そこが使い回せないと、毎回ゼロから読み直しになる。3.7倍遅くなったのはそれが理由で、これは致命傷だった。
EXL3 は共有プールから必要な分だけ取る
1本だけ走るとき ████████████████████░ 190,000 tok まで使える
3本走るとき ████████░███░██░░░░░░ 必要な分だけ取る(均等割りではない)
超過したとき ████████████████████ エラーにならず順番待ちになる
超過したときの挙動も測った。4本 × 80,016 トークン = 320,064(プールを超える量)を同時に投げて 4本とも成功。落ちずに順番待ちになる。
そして共有プールなのに prefix cache が壊れない。 ここが llama.cpp との決定的な差だった。
| main TTFT | sub TTFT | 合計 | |
|---|---|---|---|
| llama.cpp 分割131K×2 | 1.03s | 1.03s | 5.2s |
| EXL3 共有262Kプール | 0.47s | 0.47s | 2.4s |

メイン(23,342トークンの前置き)とサブが同時に来る、という実際に一番よくある形。ここで 2.2倍 ついた。素の速度で 17% 負けているエンジンが、実運用の形では 2.2倍勝つ。これが「どっちが速いか」を単独で聞いても答えが出ない理由。
並列にしても速くならないのは、prefill が支配しているとき
「並列にしたのに速くならない」はよく聞く。3つの違う負荷で測ったら、原因がはっきり分かれた。
decode律速(短いprompt・長い生成) 4並列で 2.34倍 ← ちゃんと伸びる
vision(画像1枚+短いJSON) 4並列で 1.19倍 ← ほぼ伸びない
長文prompt(8,000トークン) 4並列で 0.66倍 ← むしろ遅くなる
※ここの 2.34倍は「EXL3 が llama.cpp より速い」ではなく「1並列から4並列にしたときの伸び」。前章の 2.2倍とは別の数字なので混同しないでほしい。
GPU は prefill の時点で既に振り切れている。だから並列にしても仕事を分け合うだけで、総量は増えない。長文で 0.66倍まで落ちるのが決定的で、分け合う調整のぶんだけ損をしている。
写真判定VLM用途(画像1枚がだいたい1,100トークンの prefill、出力は50トークン程度)は完全にこの形。読む量が圧倒的に多くて書く量が少ないので、並列にしても効かない。MTP のせいではないし、エンジンを替えても直らない。
MTP は並列でも切らない方がよかった
MTP(投機デコード)は、小さいモデルに先に何文字か予想させて、本体がまとめて答え合わせする高速化の仕組み。並列だとこの下書き生成が足枷になるはず、と予想して測った。
| 1並列 | 2並列 | 4並列 | |
|---|---|---|---|
| decode ON / OFF | 57.7 / 42.8(1.35倍) | 71.9 / 70.3(1.02倍) | 135.6 / 95.1(1.43倍) |
| vision ON / OFF | 2.11 / 2.62s(1.24倍) | 2.03 / 2.26s(1.11倍) | 1.77 / 2.04s(1.15倍) |
予想が外れて、全部の並列度で ON の方が速かった。2並列だけほぼ差が消えるが、遅くはならない。VRAM は下書きモデルのぶん 4.4GB 増えるが、それを惜しんで切る理由は見つからなかった。
※この ON/OFF 比較は前掲の対決表とは別の測定なので、素の数字を横に並べて比べないでほしい。見るのは ON と OFF の比。
測り方で、数字は簡単に嘘をつく
同じ画像・同じプロンプトを2回投げてはいけない
これは自分が実際に踏んだ。並列度を上げながら同じ12枚を回して「並列4で2.7倍」という気持ちのいい数字が出た。
プロンプトキャッシュが効いていただけだった。初見の画像で測り直したら 1.25倍。本番は全部が初見なので、正しいのは後者。2倍以上盛れてしまうので、ここは疑ってかかった方がいい。
prefill は TTFT で測る
APIが返す usage.prompt_tokens ÷ 経過秒 で prefill 速度を出すと、decode の時間が混ざって過小評価になる。ストリーミングで最初の1文字が返るまで(TTFT)が prefill の実測値。
画像の処理が実はllama.cppとEXL3で違った
llamaは7MB でも 19.8MB でも、画素数が同じならトークン数は同じになる。そしてエンジンによって既定の上限が違う。ここを揃えないと比較が成立しない。
llama.cpp 既定で 4,038 トークンに縮小する(1024pxぐらいに縮小してみる)
EXL3 既定 16.7MP=実質無制限 → 7MBの写真が 16,191 トークンになる(4倍の仕事)
最初これに気づかず「EXL3 は大きい画像でメモリ不足になる」と結論しかけた。4倍の仕事をさせていただけだった。揃えたら 4,036 トークン・処理時間 28.5秒 → 5.4秒。危なかった。
画質はどこまで必要か
同じ写真に大・中・小の文字を焼き込んで、画素数の上限を変えながら読ませた。
| 上限 | トークン | 時間 | 小さい文字(電話番号) |
|---|---|---|---|
| 4 MP | 4,047 | 5.9s | tel 0980-52-1234 正確 |
| 2 MP(フルHD) | 1,970 | 3.2s | tel 0380-52-1234 1桁誤読 |
| 1 MP | 1,004 | 2.4s | tel 0200-52-1234 2桁誤読・記号も崩れる |
大きい文字と中くらいの文字は、どの設定でも正確に読めた。差が出たのは小さい文字だけ。
だから用途で決めればいい。写真の風景や状況を理解させたいだけならllamaが1024pxに縮小してみるが十分。早い。exl3もフルHDに設定して 1.8倍速い。ただしHermes Agentなどと組み合わせて「VLMとChromeブラウザ使って、企業サイトのスクショから電話番号(画像になってること多い)を拾う、経理系のアプリを作るときにレシートの金額をVLMで読む、みたいな用途があるなら 4MP 以上をVLMに出す。ここをケチると静かに数字を1桁だけ間違えたりするので、ケチらない方がよい。そして無理に24GBのVRAMをギリギリまで使わずに19GBだけ使って5GBは高画質の写真を同時に4枚見ても落ちないみたいな設定が安定する。。。用途次第でVRAMをどこまで確保するかを考える部分が悩ましいですね。
RTX3060の12GBのGPUの使い道も、予想以上だった
サブのエージェントを小さいGPUに逃がせるかを測ったら、想像より良かった。
| RTX3090 / 27B | RTX3060 / 9B | |
|---|---|---|
| prefill (tok/s) | 1,160 | 1,221 |
| decode 4並列 (tok/s) | 142.2 | 161.0 |
| エージェント短応答 (req/分) | 137.0 | 179.4 |
| ツール呼び出し | 3/3 | 3/3 |
| 小さい文字の読み取り | 正確 | 正確 |
モデルが3分の1なので prefill が速いのは当たり前ではある。ただエージェントの仕事は「長い指示を読んで短く返す」形が多いので、prefill の速さがそのまま効く。ツール呼び出しの精度も、簡単なケースなら 27B と差が出なかった。
12GB でも 9B なら 524,288トークンの共有プール + 4並列 + vision が載る(VRAM 10.2 / 12.3GB)。27Bに比べると生成する内容は正直ビジネスには使えないかも。。。というレベルだが。メインは27Bで動かして、並列処理のHermesのサブエージェント用(Hermesだとdelegateの設定というキーワードになります)として、余っている 3060 は普通に戦力になる。
24GBでの EXL3 + vision は、余裕が薄い
いいところばかり書いてもフェアじゃないので限界も。
15万トークンの文脈を1本走らせながら 7MB の写真を3枚同時に投げると、プロセスごと落ちた(torch.OutOfMemoryError)。リクエストが失敗するだけじゃなくサーバが死ぬ。llama.cpp は同じ条件で落ちなかった。
ただし実運用に近い混在負荷(メイン + サブ2本 + 3秒ごとに写真)を4分流したときは 330件すべて成功・VRAMピーク 22,168MiB で安定していた。通常の使い方では起きない。それでも落ちたら再起動する見張りは要る、という前提で組んだ方がいい。
ここは訂正しておきたい ── NVFP4 は Blackwell 専用
「40xx / 50xx なら NVFP4 が使える」という説明をたまに見るが、これは不正確。
NVIDIA の TensorRT-LLM のドキュメントに対応表があって、そこを見ると NVFP4 は Blackwell(SM100 / SM120)だけ。Hopper も Ada も対象外。FP8 は Ada Lovelace 以降で、Ampere は入っていない。
| 世代 | NVFP4 | FP8 | 現実的なエンジン |
|---|---|---|---|
| Ampere(RTX 30xx) | ✗ | ✗ | llama.cpp か EXL3 |
| Ada(RTX 40xx) | ✗ | ✓ | vLLM が素直 |
| Blackwell(RTX 50xx) | ✓ | ✓ | vLLM でいい |
FP8 も NVFP4 も、数字の精度を落として容量と速度を稼ぐ形式。これを計算する専用回路(テンソルコア)がハードに載っているかどうかで、実用になるかが変わる。
3090(Ampere)に FP8 のテンソルコアは無い。KVキャッシュを FP8 で「置く」ことはできても計算は速くならないので、容量は減るが見返りが薄い。Ampere で llama.cpp と EXL3 を細かく比べる羽目になるのは、そもそも FP8 という逃げ道が無いからだった。40xx 以降ならこの悩みが1つ消えて、vLLM が素直な選択肢になる。
断っておくと、vLLM は今回測っていない。手元が 3090 と 3060 なので27Bをメインとする時点で候補から泣く泣く外した。この章はハードの仕様から言えることだけで、実測ではない。
まとめ
- 1本を最速で回すなら llama.cpp。 prefill も 4並列 decode も 17% 速い。単発のチャット用途ならこれで困らない
- エージェントを並列で回すなら EXL3。 メイン+サブ同時で 2.2倍。素の速度の 17% を捨ててでも、KVを融通し合える方が効く
- llama.cpp で共有KVにするなら
--kv-unifiedの副作用を先に測る。 同じ前置きを繰り返し送る使い方だと 3.7倍遅くなる可能性がある - 並列で速くならないときは、まず prefill か decode かを見る。 prefill 支配ならエンジンを替えても直らないので、送る量を減らす方に手を入れる
- MTP は入れておく。 4.4GB 払う価値はあった
- ベンチは初見データで測る。 同じ入力を2回投げると 2倍以上盛れる
- 40xx / 50xx を持っているなら vLLM を検討する。 ただし NVFP4 が使えるのは 50xx だけで、40xx は FP8
「どの推論エンジンがいいか」は、世代とワークロードの2つが決まらないと答えが出ない。単独で聞いても答えようがない、というのが全部測ったあとの結論。
24時間回すなら、あると詰まらない安いもの10個
※この章にはアフィリエイトリンク(PR)を含みます。価格と在庫は変わるので、リンク先で確認してほしい。
ここまで測ってきて分かったのは、ローカルLLMは「動かす」より「動かし続ける」ほうが難しいということ。24時間エージェントを回すと、単発でベンチを取っていたときには出てこなかった問題が出てくる。熱、ホコリ、電気代、そして落ちたときの復旧。
どれも数百円〜数千円で片がつくものばかりなので、自分の環境で効いた順に並べておく。全部買う必要はなくて、上から3つで十分効く。
まず測る
- ワットモニター(サンワサプライ) ── コンセントに挟むだけで消費電力と積算電力量が出る。これが1個目でいい。3090を24時間回すと電気代がいくらになるのか、体感ではなく数字で分かる。自分の場合、これを見てから「常時起動」と「使うときだけ起動」の判断が変わった
- デジタル温湿度計 ── PCの隣に置いて室温を見る。GPUの温度はソフトで見られるが、室温が上がっていることには気づきにくい。夏場にサーマルスロットリング(熱で自動的に性能を落とす動作)が出たときの原因切り分けが速くなる
熱をどうにかする
- 12cmケースファン(SCYTHE Wonder Snail PWM) ── 推論中はケース内の空気が動かないと詰まる。PWM対応なら負荷に応じて回転数が変わるので、アイドル時は静かなまま。1個1,000円前後で足せる
- サーマルパッド(1mm / 12.8W/mK) ── 3090はVRAMの温度が上がりやすいことで知られている。中古で買った個体だと経年でパッドが硬化していることがあるので、開けるついでに換えると効く。分解は保証が飛ぶので、そこは承知のうえで
- M.2 SSD用ヒートシンク(オウルテック) ── モデルファイルは1本で数十GB。読み込みのたびにNVMeが熱を持つ。ヒートシンクが付いていないSSDを使っているなら500円で保険になる
- 電動エアダスター(エレコム) ── 24時間ファンを回すとホコリの溜まる速度が段違い。スプレー缶と違って充電式なので、詰まるたびに買い足さなくていい。熱の問題の何割かは、単にホコリ
物理的に支える・つなぐ
- GPUサポートステー(高さ調整可) ── 3090クラスは重い。挿しっぱなしで何ヶ月も経つとスロット側にじわじわ負荷がかかる。数百円で止められるなら入れておいていい
- 個別スイッチ付き電源タップ(雷ガード付き) ── 常時通電の機材が増えると、1台だけ落としたいときに全部抜くことになる。個別スイッチがあるとそれをやらずに済む。雷ガードは24時間つなぎっぱなしなら普通に効く
- CAT6A フラットLANケーブル 0.5m ── 推論サーバを別マシンにすると、ルータ経由じゃなく直結したくなる。短いのを1本持っておくと配線が一気に楽になる
- USB切替器(2台・手動) ── メインPCと推論サーバでキーボードとマウスを共有する。KVM(画面ごと切り替える装置)ほど大げさじゃなくていいなら、これで足りる
優先順位をつけるなら、ワットモニター → エアダスター → ケースファンの3つ。この順番で効いた。
この記事、GPUを何日か占有して測った内容で、正直そこそこ電気を食っている。もし何か買うものがあるときに、この記事のリンクから入ってもらえると、コーヒー代くらいにはなる。それが次の検証の燃料になるので、気が向いたらお願いします。
エンジンの種類そのものの話はローカルLLMの推論エンジン、結局どれ使う?──Ollama・vLLM・exl3を実際に触って選んだ話に書いてある。Mac と GPU のどちらで組むかで迷っているならローカルLLMはMacとGPUどっちで動かす?の方が近い。
