9月21日、Bala Priya Cが「The Roadmap to Mastering LLM Inference Optimization」と題した記事を公開した。LLM推論の本番運用では、モデルの精度だけでなく推論コストとレイテンシが事業の持続性を左右する。クラウドAPIのコストが予算を圧迫し、スループット不足でSLAを守れない——そうした課題が急増する中、再学習なしに同一モデルのパフォーマンスを引き上げる手法への関心が高まっている。本記事はその全体像を、KVキャッシュ・PagedAttention・プレフィックスキャッシュ・連続バッチング・FlashAttention/モデル圧縮・投機的デコーディング・マルチGPU並列化という7つの柱で体系的に整理したものだ。
LLMを本番環境で動かすとき、「正しい出力が得られる」は出発点に過ぎない。リクエストキューが増えた瞬間にレイテンシ目標を外し、バッチサイズやコンテキスト長が伸びるにつれてコストが想定を上回る——そういう場面で問題になるのが推論効率だ。
以下では7つの手法を順に解説する。
前提:Prefill と Decode の非対称性
すべての最適化の前提として、LLM推論が 2つの異なるフェーズ で構成されることを理解する必要がある。
Prefill フェーズは、入力トークン全体を並列処理して最初の出力トークンを生成する段階だ。全入力が既知なのでGPUを並列に使い切れる。ボトルネックはコンピュート(演算)にある。
Decode フェーズは、その後のトークンを1つずつ自己回帰的に生成する段階だ。前のトークンへの依存があるため並列化できない。GPUは演算よりもメモリからのデータ転送待ちに時間を使う。ボトルネックはメモリ帯域幅にある。
この非対称性が、最適化手法の選択を根本的に規定する。よく使われる指標でいえば、TTFT(Time to First Token)はPrefillの性能を、TPS(Tokens per Second)はDecodeの性能を反映している。どちらかを改善してももう一方が改善するとは限らず、ユースケースがどちらを重視するかで取るべき手法が変わる。
手法①:KVキャッシュ — Decodeフェーズの基本最適化
Decodeフェーズの基本最適化が KVキャッシュ だ。各ステップで全トークンのKey・Valueテンソルを再計算する代わりに、計算済みのテンソルをGPUメモリに保持して再利用する。演算コストをメモリに置き換えるトレードオフだ。
問題は、KVキャッシュのメモリ使用量がバッチサイズとシーケンス長の両方に比例して増加することにある。7Bパラメータのモデルを16bit精度で動かす場合、中程度のシーケンス長でもリクエストあたり数GBを消費する。長文脈や大バッチではメモリが並列処理数の上限を決める主因になる。
加えて、素朴な実装では最大シーケンス長分をあらかじめ確保するため、内部フラグメンテーションが深刻になる。
手法②:PagedAttention — メモリ断片化の解消
KVキャッシュのフラグメンテーション問題を解決するのが PagedAttention(vLLMがデフォルトで採用)だ。OSの仮想メモリのページング概念を転用し、KVキャッシュを固定サイズのブロックに分割して非連続に確保する。トークン生成に応じてブロックを動的に追加し、事前予約を排除することでメモリ浪費を大幅に削減——同一ハードウェアでのバッチサイズ拡大とスループット向上に直結する。
手法③:プレフィックスキャッシュ — 共有プロンプトの重複計算排除
プレフィックスキャッシュはさらに一歩進む。システムプロンプトや数ショット例など複数リクエストで共有されるプレフィックスのKVキャッシュを一度計算して使い回す。RAGパイプラインや長いシステムプロンプトを持つアプリケーションでは、冗長な計算の大部分を排除できる。
手法④:連続バッチング — GPU稼働率をどう上げるか
1リクエストずつ処理するとGPUはほとんど遊ぶ。モデルの重みはバッチサイズによらず毎回ロードされるため、バッチサイズを増やすほど重みのコストが分散されてスループットが上がる。
- 静的バッチング:固定数のリクエストを揃えてから処理。出力長のばらつきにより、短いリクエストが長いリクエストの終了を待つ無駄が生じる。
- 動的バッチング:一定時間内に到着したリクエストをまとめて処理。タイムアウトとバッチ上限のトレードオフがある。ただし一度バッチが始まると進行は同期される。
- 連続バッチング(in-flight batching):シーケンスが完了した瞬間にそのスロットへ新リクエストを投入する。バッチ境界を持たず常にGPUを満たす設計で、出力長の分散が大きい環境でも高稼働率を維持する。vLLMやTensorRT-LLMのデフォルト戦略。
手法⑤:アテンション最適化とモデル圧縮
アテンション最適化では、Multi-Query Attention(MQA) や Grouped-Query Attention(GQA) がDecodeフェーズのメモリ転送量を削減する。一方、FlashAttention はアーキテクチャを変えず、中間値(アテンション行列)をGPUのグローバルメモリではなく高速なオンチップSRAMに収めるよう計算順序を変えることで、再学習不要でメモリトラフィックを大幅削減できる。
モデル圧縮では、量子化が実用的な選択肢だ。FP16で約14GBかかる7Bモデルが、INT4では約3.5GBになる。GPTQやAWQといった量子化手法が品質劣化を抑えながら4bit量子化を実用的にした。構造化プルーニング(NVIDIAのAmpere以降がサポートする2:4スパーシティ)は対応演算で最大2倍の高速化をソフトウェア追加なしに提供する。知識蒸留は大モデルの振る舞いを小モデルに移す手法で、レイテンシが最優先の場面では圧縮より良い結果を出すことが多い。
手法⑥:投機的デコーディング — 自己回帰の制約を迂回する
投機的デコーディングは自己回帰の制約そのものを迂回する手法だ。小型の「ドラフトモデル」が数トークンの候補列を生成し、本体モデルがそれらを並列に検証する。一致したトークンはそのまま採用し、最初の不一致以降を棄却して続行する。受け入れられたトークンは本体モデルが単独で生成したものと数学的に同一——出力品質の劣化がない。ドラフトモデルの一致率が高いほど1回の本体モデル呼び出しで多くのトークンが確定するため速い。インタラクティブなチャットなどシングルリクエストのレイテンシが重要な場面で最も効果が出る。
手法⑦:マルチGPU並列化とPrefill-Decode分離
モデルが単一GPUのメモリに収まらない場合や、スループット目標が1デバイスの上限を超える場合は並列化が必要になる。
- テンソル並列:各レイヤーの重み行列を複数GPUに分割。低レイテンシ推論向き。
- パイプライン並列:連続するレイヤー群を別々のGPUに割り当て。大モデル・高スループット向きだが「パイプラインバブル」(GPU待ち時間)が課題。
- Prefill-Decode分離:PrefillとDecodeを異なるハードウェアプールに割り当てる新しいパターン。演算バウンドとメモリ帯域幅バウンドという異なる特性に最適化されたハードウェアを当てられる。コンテキスト長が伸びるにつれて実用的な選択肢になっている。
Prefill-Decode分離は比較的新しいアーキテクチャパターンであり、ByteDanceのMooncakeやPrincetonのDistServeといった研究実装がその有効性を示している。いずれも、2つのフェーズをリソース特性に合わせて独立にスケールさせることで、全体のコスト効率とレイテンシを改善するアプローチを取っている。
詳細はThe Roadmap to Mastering LLM Inference Optimizationを参照していただきたい。