Q3. 推論レイテンシの改善
ユーザーから『応答が遅い』と指摘されたとき、prefillとdecodeのどちらがボトルネックか、どう切り分けて改善していますか? 実際に試した対策を教えてください。
出典: @voidwarriorchan の投稿(2026-08-25)
- LLM(大規模言語モデル)の応答生成が「読み込み(prefill)」「書き出し(decode)」という性質の違う2段階でできていること
- 「遅い」を測る3つの物差し — TTFT・ITL・e2e — の意味と、どちらの段階を映すか
- 「最初の1文字が遅い」のか「1文字ずつのテンポが遅い」のかを見分ける手順と、API利用・自前ホスティングそれぞれの対策
- 面接でどう答えれば「本番でLLMを動かした経験がある」と伝わるか
この質問は何を聞いているのか
質問文の「prefill」(プリフィル、読み込み段階)と「decode」(デコード、書き出し段階)は、LLMが文章を生成する際に必ず通る2つの処理段階の名前だ。詳細は次節で仕組みから説明するが、まず言葉の意味だけ押さえておくと、prefillは質問文を読み込む作業、decodeは答えを1トークン(モデルが文章を扱う最小単位。日本語ならおおむね1〜2文字分)ずつ書き出す作業だ。
つまり、この質問は「応答が遅い」という漠然としたクレームを1つの数字として扱わず、原因の異なる2つの症状に分解して考えられるかを測っている。両者では効く対策がまったく違うため、切り分けずに「とりあえずプロンプトを短くする」「とりあえずキャッシュを入れる」と勘で打っていないかが問われる。
推論は「読み込み」と「書き出し」の二段階でできている
LLMが文章を生成する処理は、性質がまったく異なる2つの段階からできている。1つ目が読み込み段階(prefill)だ。ユーザーが送った質問文(プロンプト)全体を一度に読み込み、最初の1トークンを生成する。入力の全体像が最初から分かっているためこの計算は「行列×行列」(多数のトークン分の計算を1回にまとめて行う形)のかたちになり、GPU(並列計算に特化したチップ)の計算資源をほぼ使い切る。演算量が処理時間を決める「compute-bound(計算律速。律速=速さの上限を決めている要因)」な段階と呼ばれる。
2つ目が書き出し段階(decode)だ。最初のトークンが出たあとは、そこから先を1トークンずつ順番に生成する。1トークンごとに直前までの全トークンの情報を参照するが、1回の計算で新しく処理するのは常に「1トークン分」でしかない。これは「行列×ベクトル」(1トークン分だけを計算する形)の計算になり、GPUの計算能力の大部分を使わないまま終わる。処理時間を決めるのは計算の速さではなくモデルの重み(学習済みパラメータ)をメモリからGPUへ運ぶ速さで、「memory-bound(メモリ帯域律速。メモリ帯域=メモリからデータを運び出せる1秒あたりの量)」と呼ばれる。
このdecodeを成立させるのが「KVキャッシュ」(key-valueキャッシュ。読み込んだトークンごとの計算結果〈keyとvalueと呼ぶ中間データ〉をGPUメモリに取り置き、次のトークンを作るたびに計算し直さない仕組み)だ。無ければ毎回全トークン分を計算し直し、コストは二乗で膨らむが、キャッシュがあれば一次関数的にしか増えない。ただしメモリは線形に食いつぶし、NVIDIAの計算例では70億パラメータのLlama 2(16bit〈1つの重みを16ビットの精度で表す〉・文脈4,096トークン)でKVキャッシュだけ約2GBを要する。この非対称性を端的に示す実測もある。Sarathi-Serve論文(Mistral-7B・A100実測)は、decode 1トークン分の線形層(重みを掛け算する層)コストがprefill 128トークン分とほぼ同じだと報告する。
遅さを測る物差しと、原因の切り分け
「遅い」を具体的に議論するには物差しが要る。実務で使う指標は主に3つ。TTFT(Time To First Token、最初のトークンが出るまでの時間)は「待ち行列で順番待ちする時間」「prefillの処理時間」「ネットワークの往復時間」を合わせたもので、プロンプトが長いほど伸びる。ITL(Inter-Token Latency、トークン間隔)は生成された1トークンと次の間隔で、decodeの速さそのものを表す。TPOT(Time Per Output Token)とほぼ同じ意味で使われる(後述のspeculative decoding使用時は両者の値がずれることがある)。e2e(end-to-end)レイテンシは、送信から最後のトークンまでの全時間で「e2e = TTFT + decode全体の時間」という式で表せる。
この3つのどれが悪化しているかで、疑うべき原因はまったく違う。TTFTだけが悪ければ入力が長すぎるか待ち行列ができているか、単純にネットワークが遅い。ITLが悪ければGPUのメモリ帯域の上限に近づいているか、他のリクエストのprefill処理が割り込んで生成を一時停止させている(generation stall、生成の停滞)。e2eだけ悪くTTFTとITLが正常なら、出力トークンの数が多いだけだ。
自前でモデルをホスティングしている場合は、この切り分けをさらに機械的に行える。推論エンジンのvLLM(オープンソースのLLM推論サーバー)は「待ち行列に入った時刻」「実行開始時刻」「新トークン出力時刻」をイベントとして記録し、待ち行列・prefill・decode・トークン間隔それぞれの所要時間を別の指標として取り出せる。どの区間が長いかで、体感の「遅い」を数値で裏付けられる。
実務では何をするのか
対策は常に「読み込み側(TTFT)か書き出し側(ITL・総時間)か」で意識する。対策の多くは片側にしか効かない(プロンプトキャッシュはTTFTだけ、speculative decodingはITL・総時間だけ)。モデルを小さく速いものへ変えるように両方に効く手もあるが、まずどちらの症状かを特定してから選ぶ。
読み込み(TTFT)を速くする
第一に入力トークンを減らすことだ。TTFTは入力の長さに比例して伸びる(NVIDIA)ので「最初の1文字が遅い」症状には直接効く。ただし応答全体の時間に対する効果は小さく、OpenAIの公式ガイドは「出力を50%減らすと総レイテンシもおよそ50%減るが、入力を50%減らしても総レイテンシの改善は1〜5%程度」と述べる。巨大な文脈を扱う場合を除き、総時間を縮める最優先の対策にはならない。
第二にプロンプトキャッシュ(プレフィックスキャッシュ。共通する入力先頭部分のKVキャッシュを保存し使い回す仕組み)だ。指示文やシステムプロンプトを先頭に置けば読み込み計算を省けるが、TTFTにしか効かずdecodeには影響しない。Anthropic APIの有効期限(TTL、Time To Live。キャッシュが生きている時間)は既定5分、最小長はモデルにより512〜4,096トークン(2026-08時点)で、満たなければ無音でキャッシュされない。vLLMの自動プレフィックスキャッシュも同様に読み込みの時間だけを削る。
第三に自前ホスティング限定でchunked prefill(読み込みの分割処理)がある。これはTTFTを直接縮める手段というより、長いプロンプトの読み込みが他リクエストの書き出しを止める(generation stall)のを防ぎ、ITLを守る仕組みだ。長いプロンプトの読み込みを小さな塊(チャンク)に分割し、稼働中リクエストの書き出し1回分と同じバッチ(GPUが1回の計算でまとめて処理するリクエストの束)に相乗りさせる。書き出しは計算に余裕がある処理(memory-bound)なので、チャンクを同乗させても1回の処理時間はわずかしか伸びない(Sarathi-Serve論文 Takeaway-2)。vLLM(V1)は書き出し中のリクエストを先に処理してから残りの枠に読み込みチャンクを載せる(decode優先スケジューリング)方式を、可能な限り既定で有効にしている。処理トークン数の上限(max_num_batched_tokens)はITLとTTFTの両方向に振れるダイヤルで、小さくすると書き出しを妨げるプレフィルが減ってITLが改善し、大きくすると1回のバッチで処理できるプレフィルトークンが増えてTTFT側が改善する。
書き出し(ITL・総時間)を速くする
書き出し側の対策は総時間への効きが大きい。最も効くのは出力トークンを減らすことだ。前述のとおり出力を50%減らせばレイテンシもおよそ半分になる。Anthropicの公式ガイドは「文や段落の数で制限するほうが語数指定より効果的」と述べる(モデルは単語でなくトークンを数えるため)。max_tokensで強制的に打ち切る手もあるが、文の途中でも容赦なく切れる鈍い手段だ。
次に有効なのがspeculative decoding(投機的デコーディング)だ。小さな「ドラフトモデル」に複数トークン先読みさせ、本命モデルが1回の計算でまとめて検証・的中分を採用する仕組みで、出力の確率分布は理論上変えない(lossless)。vLLMの公式ドキュメントは、メモリ帯域が律速になる「medium-to-low QPS(1秒あたりのリクエスト数が中〜低い状態)」でITL(トークン間隔)を縮める手法と位置づける。原論文も、メモリ帯域が律速で計算資源が余っている状況を前提にした手法だと述べる。負荷が高くGPUの計算資源に余裕がなくなると効果は薄れ、ドラフトの採用率=「受理率」の監視が要る。ここで計測ツールの定義には注意が要る。vllm bench serveは1回のストリーム出力に複数トークンが乗る場合でも「出力チャンク間の間隔」としてITLを集計するため複数トークン分を1回としか数えず、トークン当たりに割ったTPOT(Time Per Output Token)のほうが小さく出る(公式ドキュメントの例: ITL 40ms・TPOT 20ms/token)。指標の名前ではなく、どこを計測点にしているかで比べる必要がある。vLLMでは--speculative-configにJSONでドラフトモデルと先読みトークン数を指定する。
{
"method": "draft_model",
"model": "<draft-model>",
"num_speculative_tokens": 5
}
この他、軽量で高速なモデルへ変える(Anthropicは速度重視の用途にHaiku 4.5を推奨。2026-08時点)、拡張思考(extended thinking。思考トークンも出力として課金・生成されるため使うほど伸びる)を絞る、といった選択肢もある。総時間は変えないが「待たされ感」を変えるのがストリーミングで、最後まで待たず最初の文字から読み始められる。
| 症状 | 主因 | API利用者の対策 | 自前ホスティングの対策 |
|---|---|---|---|
| TTFTが大きい | 入力が長い | 入力削減・プロンプトキャッシュ | 自動プレフィックスキャッシュ・max_num_batched_tokensを大きく |
| TTFTが大きい | 待ち行列に並ぶ | リクエスト削減・並列化・軽量モデル | レプリカ(同じモデルを載せたサーバーの複製)追加・同時実行数の調整 |
| ITL・TPOTが大きい | メモリ帯域の限界・割り込み | 軽量で高速なモデル | speculative decoding・decode優先スケジューリング |
| e2eだけ大きい | 出力トークン数が多い | 出力短縮・max_tokens・思考量を絞る | 同左+speculative decoding |
回答を見極めるポイント
- prefill(行列×行列・compute-bound)とdecode(行列×ベクトル・memory-bound)を区別できる
- TTFT=待ち行列+読み込み+ネットワーク、e2e=TTFT+decode全体、入力→TTFT・出力→ITLという因果で語れる
- 出力削減は総時間に対して最も効く(50%削減≈50%改善)、入力削減は総時間に対しては限定的(同1〜5%)という定量感がある
- プロンプトキャッシュが読み込みにしか効かず、最小トークン数や有効期限(TTL)など具体的な設定名を挙げられる
- speculative decodingは低〜中負荷でだけ効き、出力分布を変えない(lossless)ことを知っている
- 「レイテンシ」を単一の数字として語り、TTFTとITLを区別しない
- 「プロンプトを短くすれば速くなる」を主対策に挙げる(総時間への効果は1〜5%程度と小さい)
- 「GPUの計算が足りないから遅い」と一括りにし、decodeがmemory-boundであることを説明できない
- speculative decodingを「出力品質を犠牲にして速くする手法」と誤解している
深掘り質問の例
- TTFTとITLを実際にどう計測しましたか? クライアント側とサーバー側のどちらで測りましたか?
- プロンプトキャッシュを入れて効果が出なかった経験はありますか? 原因は何でしたか?
- speculative decodingを試した場合、ドラフトの受理率はどのくらいでしたか?
つまずきポイント
「プロンプトを短くすればなんでも速くなる」と思い込んでいる。実際は出力削減(50%削減≈50%改善)のほうがずっと大きく効く。
「キャッシュを入れれば1文字ごとの生成も速くなる」と誤解している。プロンプトキャッシュが省くのは読み込みの計算だけで、書き出しには作用しない。
「同時にまとめて処理するリクエスト(バッチ)を増やせば1人あたりの応答も速くなる」と誤解している。システム全体のスループット(単位時間に捌ける処理量)は上がるが、1リクエストあたりの体感速度はむしろ下がる、トレードオフの関係にある。
理解度チェック
Q1. prefillとdecode、GPUの計算資源を使い切れないのはどちらですか? なぜですか?
decode。「行列×ベクトル」の演算になり、GPUの計算能力より「重みをメモリから読み出す速度」がボトルネックになる(memory-bound)ため。
Q2. TTFTを構成する3つの要素は何ですか?
待ち行列で順番待ちする時間・読み込み(prefill)の処理時間・ネットワークの往復時間の3つ。
Q3. プロンプトキャッシュを入れても1文字ずつの生成テンポ(ITL)は速くなりません。なぜですか?
プロンプトキャッシュは入力先頭の読み込み計算を省略する仕組みで、decodeには作用しないため。
Q4. speculative decodingがうまく機能しにくいのはどんな状況ですか?
リクエストが集中しGPUの計算資源に余裕がない、高負荷な状況。メモリ帯域が律速で計算に余裕があるときに効く手法なので、負荷が高いと効果が薄れる。
まとめ
- LLMの推論は「読み込み(prefill・行列×行列・compute-bound)」と「書き出し(decode・行列×ベクトル・memory-bound)」の2段階でできている
- 「遅い」はTTFT(最初の文字まで)・ITL(トークン間隔)・e2e(全体)の3物差しに分解して初めて対策できる
- 入力が長い→TTFT、出力が長い→ITL・総時間、負荷が高い→待ち行列でTTFT、という因果で対策を読み込み側・書き出し側に分ける
- 読み込み側にはプロンプトキャッシュ、書き出し側には出力削減やspeculative decoding、両者のバランスを取るのがchunked prefill(
max_num_batched_tokens)。多くの対策は片側にしか効かない - 出力削減が最も効き、入力削減は限定的という定量感を持つこと自体が、本番運用の経験を裏付ける
次章では、モデルの重みを軽量化して同じメモリ帯域の制約に別の角度から挑む「量子化」を取り上げる。
参考リンク
- NVIDIA — Mastering LLM Techniques: Inference Optimization
- NVIDIA — LLM Benchmarking: Fundamental Concepts
- vLLM — Optimization and Tuning
- vLLM — Automatic Prefix Caching
- vLLM — Speculative Decoding
- vLLM — Benchmark Suites (vllm bench serve)
- Anthropic — Reducing Latency
- OpenAI — Latency Optimization
- Agrawal et al. — Sarathi-Serve(arXiv:2403.02310)