「AI 開発してます」を見極める 10 の質問 — 素人のための解説|2026-08 版
第 5 章Q3

Q3 推論レイテンシの改善

「遅い」には 2 種類ある — 最初の 1 文字が出るまでと、その後の 1 文字ごと

Q3. 推論レイテンシの改善

ユーザーから『応答が遅い』と指摘されたとき、prefillとdecodeのどちらがボトルネックか、どう切り分けて改善していますか? 実際に試した対策を教えてください。

出典: @voidwarriorchan の投稿(2026-08-25)
この章で分かること

この質問は何を聞いているのか

質問文の「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トークン分とほぼ同じだと報告する。

読み込み(prefill) 行列 × 行列 入力(複数トークン) メモリから読み出す 重み GPU計算を飽和 → compute-bound 書き出し(decode) 行列 × ベクトル 入力(トークン1個) メモリから読み出す 重み 入力を掛ける 入力を掛ける 重み読み出しが律速 → memory-bound
図 5-1 同じ「重み」を使うのに、prefillはトークンをまとめて処理でき、decodeは1個ずつしか処理できない。読み出した1バイトあたりの演算数(算術強度)がdecodeでは極端に低くなる。

遅さを測る物差しと、原因の切り分け

「遅い」を具体的に議論するには物差しが要る。実務で使う指標は主に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全体の時間」という式で表せる。

待ち行列 読み込み(prefill) 書き出し(decode)— 1トークンずつ TTFT(最初の文字まで) e2e = TTFT + decode 全体 decode を拡大 — トークンとトークンの間隔 ITL(トークン間隔)
図 5-2 TTFTは最初の文字が出るまで、ITLはトークン同士の間隔、e2eはTTFTとdecode全体の合計(ネットワーク往復は省いて描いている。クライアント側で測るTTFT〈NVIDIAの定義〉は待ち行列・読み込み・ネットワークまで含み、vLLMが返すリクエスト単位のTTFTはスケジュール後から数えるため待ち行列を含まない。どこから測った値かを確認してから比べること)。

この3つのどれが悪化しているかで、疑うべき原因はまったく違う。TTFTだけが悪ければ入力が長すぎるか待ち行列ができているか、単純にネットワークが遅い。ITLが悪ければGPUのメモリ帯域の上限に近づいているか、他のリクエストのprefill処理が割り込んで生成を一時停止させている(generation stall、生成の停滞)。e2eだけ悪くTTFTとITLが正常なら、出力トークンの数が多いだけだ。

『応答が遅い』という指摘 最初の1文字が遅い 1文字ごとが遅い 全体だけ長い TTFTが大きい ITL・TPOTが大きい e2eだけ大きい 原因 入力が長い・待ち行列 対策 入力削減・キャッシュ 原因 メモリ帯域の限界・割り込み 対策 軽量モデル・speculative decoding 原因 出力トークン数が多い 対策 出力短縮・思考量を絞る
図 5-3 「遅い」を3系統に分けると、疑うべき原因と打つべき対策が変わる。1つの数字として一括りにしないことが切り分けの出発点になる。

自前でモデルをホスティングしている場合は、この切り分けをさらに機械的に行える。推論エンジンのvLLM(オープンソースのLLM推論サーバー)は「待ち行列に入った時刻」「実行開始時刻」「新トークン出力時刻」をイベントとして記録し、待ち行列・prefill・decode・トークン間隔それぞれの所要時間を別の指標として取り出せる。どの区間が長いかで、体感の「遅い」を数値で裏付けられる。

実務では何をするのか

対策は常に「読み込み側(TTFT)か書き出し側(ITL・総時間)か」で意識する。対策の多くは片側にしか効かない(プロンプトキャッシュはTTFTだけ、speculative decodingはITL・総時間だけ)。モデルを小さく速いものへ変えるように両方に効く手もあるが、まずどちらの症状かを特定してから選ぶ。

同じ「速くする」でも、効く場所は違う 処理の流れ 待ち行列 読み込み 書き出し 読み込みを省く 書き出しを加速 プロンプトキャッシュ・入力削減 → TTFTだけを縮める speculative decoding → ITL・総時間を縮める
図 5-4 プロンプトキャッシュは「読み込み」の計算を省くので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側が改善する。

チャンク化なし:長いprefillが割り込む decodeが止まる(generation stall) チャンク化あり:Cのチャンクを Aのdecode と同じバッチに載せる A C A C A C A C A C AのdecodeとCのチャンクが同じバッチに同居 1回に処理するトークン数の上限(max_num_batched_tokens)がITLとTTFTのダイヤル
図 5-5 濃い箱は稼働中リクエストAのdecode、枠だけの箱は新規リクエストCのprefillチャンク。チャンク化すると、Cの読み込みを小分けにしてAのdecodeと同じバッチに乗せられる。

書き出し(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

回答を見極めるポイント

良い回答に含まれる要素
弱い回答のサイン

深掘り質問の例

つまずきポイント

「プロンプトを短くすればなんでも速くなる」と思い込んでいる。実際は出力削減(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の計算資源に余裕がない、高負荷な状況。メモリ帯域が律速で計算に余裕があるときに効く手法なので、負荷が高いと効果が薄れる。

まとめ

次章では、モデルの重みを軽量化して同じメモリ帯域の制約に別の角度から挑む「量子化」を取り上げる。

参考リンク