⚙️

推論エンジンとモデルの関係を整理する|llama.cpp・vLLM・TensorRT-LLMの使い分け

に公開

はじめに

前回、社内知恵袋(ShineosQA)をOllama + Open WebUIからllama.cpp直接実行へ全面書き直した話を書きました。その反響といっしょに、こんな質問を社内外からいただくようになりました。

  • 「なぜllama.cppなんですか?サーバで動かすならvLLMの方が速いのでは?」
  • 「TensorRT-LLMというNVIDIA公式のものもありますが、あれはどんなときに使うんですか?」
  • 「そもそも“推論エンジン”と“モデル”って、何が違うんですか?」

ちょうど社内の技術共有会でこのテーマを話す機会があったので、その内容を記事として整理したのが本記事です。 「モデルとエンジンの関係」「3つのエンジンのアーキテクチャ上の違い」「どう選ぶか」 の3点を、図と表で説明します。エンジン選びは一度決めると構成全体に影響するので、コードを書き始める前に押さえておきたい話です。

前提:モデルと推論エンジンは「別物」である

モデルとは「重みの塊」で、単体では何もできない

LLMの中身を突き詰めると、学習で確定した膨大な数値(重み)の集合です。Transformerアーキテクチャという「設計図」に沿った層の数やAttentionの構造、語彙数といった構造情報(config)、テキストを数値の列に変換するトークナイザ、そして重み——この3点セットになって初めて「モデル」として扱えます。

ただし、モデルはそれ単体では何もしてくれません。Excelファイルを開くアプリがないとただのデータであるのと同じで、重みをメモリにロードして「次の1トークンを予測する行列計算」をひたすら実行してくれる装置が別に必要です。それが 推論エンジン(推論ランタイム) です。

たとえばChatGPTのようなサービスは、大雑把に書くと次の積み重ねでできています。

つまり「どのモデルを使うか」と「どのエンジンで動かすか」は独立した選択で、その2つをつなぐのがモデル形式(と、モデルのアーキテクチャへの対応)です。ここが今回の主題です。

音楽にたとえると分かりやすいです。モデルは「マスターデータ(楽曲)」で、エンジンは「再生装置」。同じ曲でも、CDプレーヤーで聴くならCD-Rに焼く必要があるし、スマホに入れるならファイル形式を合わせる必要がある。再生装置が違えば、求められる媒体の形式も違う——これが、llama.cppにはGGUF、vLLMやTensorRT-LLMにはsafetensors(HF形式)と「エンジンごとに渡すモデルの形式が違う」ように見える正体です。なお、vLLMとTensorRT-LLMは同じsafetensorsを使い、TensorRT-LLMはそれをGPU向けにビルドする点だけが異なります。

KVキャッシュ:エンジンの腕の見せどころ

エンジンごとの違いを理解する鍵がKVキャッシュです。LLMはテキストを1トークンずつ生成しますが、そのたびに「ここまでの文脈」をAttention計算用に保持しています。これがKVキャッシュで、性質として、

  • サイズがコンテキスト長に比例して大きくなる(層数・ヘッド数にも比例)
  • 同時アクセスが増えると、リクエスト数ぶんだけKVキャッシュが必要になる

というものがあります。つまりエンジンの個性とは、 「限られたGPUメモリにKVキャッシュをどう詰め込むか」「待ち時間をどう減らして複数リクエストを1つのバッチでさばくか」 の設計に集約されます。このあと出てくるPagedAttentionや継続バッチングは、すべてこの2つの問いへの答えです。

3つのエンジン:アーキテクチャで見ると何が違うか

llama.cpp:「どこでも動く」単体ランタイム

  • C/C++だけで書かれた、依存の少ない単体の推論エンジン
  • 動く場所が広い:CPU(x86/ARMのSIMD最適化)、Apple Silicon(Metal)、NVIDIA/AMD GPU(CUDA/Vulkan/ROCm)
  • モデル形式はGGUF。重み・トークナイザ・設定を1ファイルに同梱し、量子化済みで配布される
  • llama-serverというOpenAI互換のHTTPサーバを同梱(ShineosQA v2はこれを子プロセスとして実行)
  • 量子化の種類が非常に豊富(Q4_K_M、IQ4_XSなど)で、少ないメモリに収める工夫が随所にある

強みはポータビリティです。GPUがなくても動くので、「支給PCの8GBメモリで動かしたい」「アプリに同梱して配布したい」「CIでも動かしたい」という用途では最有力です。半面、GPUサーバで大人数の同時リクエストをさばく用途では、後述のvLLMなどにスループットで及ばないことが多い(バッチングの設計思想が違う)です。

vLLM:「サーバでさばく」ためのエンジン

  • 研究機関発祥のOSSで、現在はコミュニティ主体で活発に開発。Python(PyTorch)ベース
  • 動く場所はNVIDIA GPUが中心(AMDやTPU、CPUなども対応範囲を広げている)
  • モデル形式はHugging Face形式(safetensors)をほぼそのままロード。AWQ/GPTQ/FP8などの量子化版もそのまま使える
  • キーとなる技術が2つ:
    • PagedAttention:KVキャッシュを、OSの仮想メモリがページ単位で管理するのと同じ発想で細かく分割・再利用する。断片化によるメモリの無駄を潰し、同一GPUに収められる同時リクエスト数を大きく増やす
    • 継続バッチング(continuous batching):生成の完了したリクエストをバッチから抜けさせ、新しいリクエストを都度参加させる。バッチを固定して回す方式と比べ、GPUの稼働率が下がらない
  • OpenAI互換APIサーバ(vllm serve)を内蔵

「1台のGPUサーバに、社内の何十人もが同時に質問してくる」構成で真価を出します。金融業の社内マニュアルAIの記事では、Qwen3-14B(AWQ 4bit)をvLLMで運用しました。

TensorRT-LLM:「そのGPUのための専用機」をビルドする

  • NVIDIA公式のLLM推論最適化ライブラリ
  • 最大の特徴は、モデルをそのまま実行せず、対象のGPUアーキテクチャ向けに最適化した実行形式(TensorRT engine)にビルド(コンパイル)して使うこと。演算の融合(カーネル融合)、FP8/INT4といった低精度フォーマットへの変換、GPUのメモリ階層に合わせた配置まで、ビルド時に決め打ちで行う
  • 継続バッチング(NVIDIAの呼び方ではin-flight batching)やPagedAttention相当のKVキャッシュ管理も備えており、手法レベルではvLLMと重なる。違いは「特定ベンダーのハードに固定して、限界まで最適化するか」
  • サービングはTriton Inference Serverと組み合わせるのが定番で、OpenAI互換サーバ(trtllm-serve)も同梱されている

同一ハードウェアなら3者の中で最も速いことが多い一方、NVIDIA GPU専用で、モデルやGPU構成を変えるたびにビルドが絡み、バージョン管理も重くなります。「環境を固定できる・性能を限界まで絞りたい・それに見合う運用工数をかけられる」場合の選択肢です。

比較表

観点 llama.cpp vLLM TensorRT-LLM
開発主体 OSSコミュニティ 研究発祥のOSSコミュニティ NVIDIA(公式)
実装 C/C++単体 Python(PyTorchベース) NVIDIA最適化ライブラリ
モデル形式 GGUF(1ファイル・量子化済み) safetensors(HF形式) HF形式をGPU向けにビルド
動く環境 CPU・Mac・GPUと広い GPUサーバ中心 NVIDIA GPU専用
得意なこと ポータビリティ・量子化の豊富さ 同時多数アクセスのスループット 固定環境での最高性能
運用の重さ ほぼゼロ依存・軽い Python環境の管理が必要 ビルドとバージョン固定が重い
向くシーン デスクトップ常駐・エッジ配布 社内APIサーバ・本番サービス 性能上限を絞り切る専門環境

使い分け:何を軸に決めるか

軸は4つ

  1. どこで動かすか:利用者のPC・エッジ・Macならllama.cppにほぼ収束。GPUサーバならvLLMかTensorRT-LLM
  2. 同時リクエスト数:1人〜数人ならllama.cppで十分。数十〜数百ならPagedAttentionと継続バッチングが効く領域
  3. レイテンシか、スループットか:1リクエストの体感速度なら「小さいモデル+llama.cpp」でも戦える。総さばき数ならサーバ向けエンジン
  4. 運用コスト:llama.cppは依存がほぼゼロ。vLLMはPython環境の管理。TensorRT-LLMはビルドとバージョン固定まで含めた専門運用

ShineosQAでの判断を振り返ると

この軸に当てはめると、ShineosQAがllama.cppだった理由が整理できます。

  • 動かす場所は「非エンジニアの支給PC」。GPUなし・メモリ8〜16GBが前提 → llama.cpp
  • 同時アクセスは「そのPCを使っている1人」 → PagedAttentionも継続バッチングも不要
  • 要求は「CPUでも数秒で最初の1文字」 → モデルを大きくするより、量子化とプロンプトキャッシュの効くllama.cpp
  • 配布要件は「ダブルクリックで入る・インストーラ約200MB」 → Pythonランタイムごと同梱する構成は厳しく、C/C++単体が合致

逆に、「社内のGPUサーバ1台を、100人の部署で共有する」なら答えは変わります。この構成ならvLLMが第一候補になり、「サーバがNVIDIA GPUで固定できる・レイテンシ要求がシビア」ならTensorRT-LLMを検討、です。エンジンに優劣はなく、どこで・誰が・どう使うかで答えが変わる——これが本記事で一番伝えたいことです。

Ollama・LM Studioの位置づけ

補足として。OllamaやLM Studioは、実体はllama.cppベースの 「モデル管理・配布の便利ツール」です。llama.cppの前に立って、モデルのダウンロード管理やAPIの形を整えている仲介層で、ShineosQA初代(v1)がOllamaを使っていたのはこのおかげです。そしてv2で「仲介層のやることは自前で書けるから、llama.cppに直行した」というのが前回の記事の話でした。つまり「Ollama vs llama.cpp」はエンジン同士の比較ではなく、「エンジン+管理ツール」か「エンジン素」か の比較です。

成長パスとして考える

  • 第1段階:デスクトップ・少人数 → llama.cpp。既存PCのまま始められる
  • 第2段階:利用が回り、同時アクセスが増えた → GPUサーバ+vLLM
  • 第3段階:ボトルネックがGPU性能そのものになった → TensorRT-LLMで最適化

「最初から最強の構成」を目指さなくても、モデルは同じものを使い回しながら、エンジンだけ載せ替えていくのが現実的な成長パスです。形式の壁(GGUFかsafetensorsか)さえ意識しておけば、モデル選びの検証資産は引き継げます。

補足:Hugging Faceからモデルを入手する

ここからは補足です。上の話を実践するとき、モデルの入手元になるのがHugging Face Hubです。GitHubのモデル版のような場所で、モデルカード(用途・ライセンス・ベンチマーク)と、重み・トークナイザのファイル一式が公開されています。ShineosQAで使っているQwen3もbge-m3も、ここから取得しています。

形式の見分け方

形式 中身 主に使うエンジン 量子化
safetensors(HF形式) 重み(fp16/bf16中心)+config.json・tokenizer.jsonなどのファイル群 vLLM、TensorRT-LLM そのまま、またはAWQ/GPTQ/FP8版
GGUF 重み+トークナイザ+設定を1ファイルに同梱 llama.cpp(Ollama・LM Studioも) Q4_K_M・IQ4_XSなど豊富

モデルページの「Files and versions」を見ると形式はすぐ分かります。

  • *.safetensors+config.json+tokenizer.jsonが並んでいたらsafetensors(HF形式)。vLLM・TensorRT-LLM向け
  • *.ggufが量子化レベルごとに並んでいたらGGUF。llama.cpp向け
  • リポジトリ名やファイル名にAWQ/GPTQ/FP8が付いていたら、量子化済みHF形式。vLLMでそのまま動く

GGUFのファイル名(Q4_K_M、IQ4_XSなど)は量子化レベルの表記で、数字はビット幅を表し、小さいほど圧縮率が高くサイズが小さい反面、品質が落ちるリスクが上がると読みます。ただし_S/_M/_Lの違いや、重要度を考慮するIQ系では同じビット幅でも品質が変わるため、数字だけで単純比較はできません。実用上はQ4_K_Mあたりが定番のバランスポイントで、ShineosQAでもIQ4_XSを採用する前に複数構成で品質検証をしました。

ダウンロードの方法

方法は大きく3つあります。

1. ブラウザでダウンロード:モデルページのFilesから個別に取得。手軽ですが、大きなモデルや多数のファイルには不向きです。

2. HF公式CLI(hfコマンド):実務ではこれが定番です。レジュームにも対応しています。

pip install -U "huggingface_hub[cli]"

# GGUFを量子化レベルで絞って取得(llama.cpp向け)
hf download Qwen/Qwen3-4B-GGUF --include "*Q4_K_M*.gguf" --local-dir ./models

# HF形式をリポジトリごと取得(vLLM向け)
hf download Qwen/Qwen3-4B --local-dir ./models/qwen3-4b

(huggingface-cli downloadという旧コマンド名も同じものです。)

3. エンジン側の自動ダウンロード:vLLMはHugging FaceのリポジトリIDを指定すると、初回に自動でダウンロードしてキャッシュします。llama.cppはGGUFファイルを直接指定する方式なので、この指定方法の違いがちょうど「エンジンと形式の関係」そのものです。

# 同じQwen3-4Bでも、エンジンによって"指定するもの"が違う
llama-server -m ./models/Qwen3-4B-Q4_K_M.gguf --port 8080   # llama.cpp: GGUFファイルのパス
vllm serve Qwen/Qwen3-4B --port 8000                        # vLLM: Hugging FaceのリポジトリID

なお、vLLMもvllm serve ./models/qwen3-4bのようにローカルパスを指定できます。上で--local-dirに落としたものをそのまま使いたい場合は、この形でパスを渡します。

--local-dirを付けない場合、ダウンロードしたモデルはローカルキャッシュ(~/.cache/huggingface/hub。Windowsでもユーザーディレクトリ以下)に蓄積され、2回目以降は通信なしで起動できます。逆にキャッシュが肥大化しやすいので、上の例のように--local-dirで配置先を明示して管理するのがおすすめです(--local-dir指定時はキャッシュを経由せず、指定したディレクトリへ直接配置されます)。

入手時に確認したい4つのこと

  1. ライセンス:モデルカードに必ず書かれています。Apache-2.0やMITのような緩いものから、商用利用に条件が付くものまであるので、社内利用や製品組込みの前に確認を
  2. 量子化レベル:GGUFならどの量子化にするか。迷ったらQ4_K_Mから始めて、品質が気になったら1段上げる
  3. 対応アーキテクチャ:モデルが新しすぎると、エンジン側の対応がまだのことがある。「どのバージョンから対応」は各エンジンのリリースノートで確認
  4. 同一性の検証:配布物が意図したものかの確認として、ShineosQAの初回起動DLウィザードでもSHA256検証を入れています。特に「自社アプリに同梱して配布する」場合はやっておいて損がありません

まとめ

  • モデルは重みの塊、推論エンジンはそれを実行する装置。2つをつなぐのはモデル形式(GGUF / safetensors)とアーキテクチャ対応
  • llama.cppは「どこでも動く」単体ランタイム。クライアントPC・エッジ・配布アプリに強い
  • vLLMは「サーバでさばく」エンジン。PagedAttentionと継続バッチングで同時アクセスのスループットを出す
  • TensorRT-LLMは「NVIDIA GPU固定で限界まで最適化」。最速を狙える代わりに、ビルドと運用が重い
  • 使い分けの軸は「どこで・何人が・どんな性能を・どれだけの運用コストで」
  • モデルの入手はHugging Faceから。形式の読み方・ライセンス・量子化・検証の4点に注意
  • エンジンに優劣はない。ShineosQAがllama.cppなのは、要件に対する答えがそうだったから。GPUサーバ×多数アクセスなら、答えはvLLMになる

前回のShineosQA記事を読んで「なぜllama.cppなのか」が気になった人の疑問が、この記事で整理できていたら嬉しいです。同じモデルでもエンジンを変えられますし、逆にエンジンを決めたら形式も合わせて決める必要があります。「モデル選び」と「エンジン選び」をセットで考えるのが、ローカルLLM運用の第一歩です。


💡 社内Q&A・ローカルLLM導入のご相談は、以下よりお気軽にお問い合わせください。

https://shineos.com/contact/


参考

Discussion