+ 作る
図を読み込んでいます…
1 / 18
GPUとLLM:グラフィックボードはなぜAIを動かせるのか / 全5章

第5章 フロンティアモデルの工夫:メモリと待ち時間を削る

発行
かえで
版
第3版
改訂
分量
18コマ・6,276字

GPUの演算器は速いのに、LLMはメモリの読み書きと待ち時間で遅くなる。FlashAttention、GQA・MQA・MLA、スライディング窓、PagedAttention、連続バッチング、MoE、投機的デコーディングが、それぞれ「何を減らしているのか」を、図を動かしながら整理します。『GPUとLLM』第5章(最終章)。

フロンティアモデルの工夫:メモリと待ち時間を削る

『GPUとLLM』の最終章です。第3章では、GPUの演算器はとても速いのに、LLMの推論、とくに1トークンずつ生成する decode では、HBM からデータを読む時間と待ち時間のほうが壁になることを見ました。第4章では、それでもモデルを載せるための量子化と並列化を扱いました。

この章では、大規模モデルの設計と運用がその壁をどう削っているかを見ていきます。図の4本のバーが削る対象です。HBMとの往復、KVキャッシュの量、1トークンあたりの計算、そして逐次の待ち。薄い部分が削った量のイメージで、右にそれぞれを削る手法を並べました。以降のページでは、タイトルの下の色付きの札で、いまどれを削っているかを示します。

  • 『GPUとLLM』第5章
  • フロンティアモデルの工夫:メモリと待ち時間を削る
  • 演算器は速い。だから、読み書きと待ち時間のほうを削る
  • HBMとの往復
  • FlashAttention
  • KVキャッシュの量
  • GQA・MQA・MLA・スライディング窓・PagedAttention
  • 1トークンの計算
  • MoE(混合エキスパート)
  • 逐次の待ち
  • 連続バッチング・投機的デコーディング
  • 第3章の結論:GPUの演算器は速いが、壁になるのはメモリの読み書きと待ち時間

FlashAttention:T×T の表を HBM に書かない

まずは HBM との往復です。第2章で見た Attention は、Q と K の積でスコアの表 S を作り、softmax で確率の表 P にしてから V を掛けます。S と P はどちらも T×T(T は文脈の長さ)の大きさです。素直に実装すると、図の下の段の赤い正方形のように、この表をいったん HBM に書き出し、softmax のためにまた読み、P を書いて、V を掛けるためにまた読みます。

T=8,192 なら、表のマスは約6,710万個。2バイトで持つと1ヘッド・1層だけで約134MB になり、これをヘッドと層の数だけ往復させます。掛け算そのものより読み書きに時間がかかる、第3章で見た「メモリ律速」の典型です。上の段の共有メモリは速いのですが、SM ごとに数百KBしかないので、表全体は入りません。

  • FlashAttention:T×T の表を HBM に書かない
  • 減らすもの:HBMとの往復
  • GPUチップの中:共有メモリ(SRAM)は速いが、SMごとに数百KBしかない
  • T×T の表全体は、ここには入らない
  • 演算器 (Tensor Core)
  • S を書く → 読んで softmax → P を書く → 読んで ×V T×T の表で HBM を4回往復する
  • T=8,192 トークンなら T² ≈ 6,710万個 × 2バイト ≈ 134MB(1ヘッド・1層ぶん)
  • S・P T×T
  • これをヘッドの数 × 層の数だけ、何度も書いて読む
  • Q
  • K
  • V
  • HBM:大きいが、チップの外にあって遠い

タイルに分けて、共有メモリの中で片づける

FlashAttention(Dao ら, 2022)は、表全体を作るのをやめます。Q・K・V を行ごとの小さなブロックに分け、図のように Q のブロックと、K・V のブロックを1つずつ共有メモリに読み込みます。その組み合わせで計算できるのは、表 S のうちの小さなタイル1枚ぶんだけです。

タイルのスコアはその場で softmax の途中計算に使い、すぐ V のブロックと掛けて出力 O に足し込みます。用が済んだタイルは HBM に書かずに捨てます。下の段の S が白く抜けたのは、T×T の表がもうどこにも置かれないことを表しています。赤い枠は「いまどのタイルを計算しているか」の目印です。HBM に書き戻すのは、最後にできあがる O(T×d)だけです。

  • タイルに分けて、共有メモリの中で片づける
  • 減らすもの:HBMとの往復
  • GPUチップの中:共有メモリ(SRAM)は速いが、SMごとに数百KBしかない
  • Q・K・V のブロック
  • スコアのタイル
  • 出力 O
  • O
  • 演算器 (Tensor Core)
  • ① Q・K・V を、行ごとの小さなブロックに分ける ② ブロックを共有メモリに読み、タイル1枚ぶんを計算 ③ すぐ V と掛けて O に足し込み、タイルは捨てる ④ 次の K・V ブロックへ進む(タイルが右へ流れる)
  • T×T の表は 作らない
  • HBM に書き戻すのは、最後にできる O(T×d)だけ
  • Q
  • K
  • V
  • HBM:大きいが、チップの外にあって遠い

オンライン softmax:最大値と和を持ち歩く

softmax は、行全体の最大値と和が分からないと計算できません。そこで行ごとに「ここまでの最大値 m」と「ここまでの指数の和 ℓ」だけを持ち歩き、新しいタイルが来るたびに右の式で更新します。最大値が大きくなったら、それまでの和と出力に exp(m − m新) を掛けて縮め直すのがポイントです。最後に O を ℓ で割れば、表全体で計算したのと同じ答えになり、近似ではありません。

図では赤いタイルが右へ流れ、K・V のブロックも下へ進んでいます。持ち歩くのは O と m、ℓ だけなので、余分なメモリは O(T²) から O(T) になります。論文は、HBM の読み書きが Θ(T·d + T²) から Θ(T²·d²÷M)(M は共有メモリの大きさ)に減ることを示しています。

  • オンライン softmax:最大値と和を持ち歩く
  • 減らすもの:HBMとの往復
  • GPUチップの中:共有メモリ(SRAM)は速いが、SMごとに数百KBしかない
  • Q・K・V のブロック
  • スコアのタイル
  • 出力 O
  • O
  • m:最大値 ℓ:指数の和
  • 演算器 (Tensor Core)
  • 新しいタイルのスコア s が来るたびに:
  • m新 = max(m, s の最大値)
  • ℓ新 = ℓ × exp(m − m新) + Σ exp(s − m新)
  • T×T の表は 作らない
  • O新 = O × exp(m − m新) + Σ exp(s − m新) × v
  • 最後に O ÷ ℓ で、表全体の softmax と同じ答え
  • Q
  • K
  • V
  • 余分なメモリ:O(T²) → O(T)
  • HBM:大きいが、チップの外にあって遠い

KVキャッシュの式:どの項を減らすか

次は KVキャッシュです。第2章で見たとおり、その大きさは上の掛け算で決まります。2 は K と V の2つぶん、L は層数、H_kv は K・V のヘッド数、d はヘッドの次元、T は文脈の長さ、最後が1つの数のバイト数です。ここからの手法は、それぞれこのどれかの項を小さくします。

ふつうの MHA(Multi-Head Attention)では、Q のヘッド1本ごとに専用の K・V ヘッドがあり、中段の模式図では8本ずつが1対1でつながっています。下のバーは、Qヘッド128本・ヘッド次元128・60層(DeepSeek-V2 と同じ大きさ)で、1層・1トークンあたりに保存する数です。MHA なら 2×128×128=32,768個。BF16 なら1トークン約3.9MB、12.8万トークンの文脈で約515GB になります。

  • KVキャッシュの式:どの項を減らすか
  • 減らすもの:KVキャッシュの量
  • KVキャッシュ = 2 ×
  • 層数 L
  • ×
  • KVヘッド数 H_kv
  • ×
  • ヘッド次元 d
  • ×
  • 文脈長 T
  • ×
  • バイト数 b
  • Q ヘッド (図は8本)
  • K・V ヘッド (保存する)
  • 1層・1トークンあたりに保存する数(Qヘッド128本・ヘッド次元128の場合)
  • MHA:2 × 128 × 128 = 32,768個
  • 60層・BF16 なら1トークン約3.9MB → 12.8万トークンの文脈で約515GB

GQA:何本かの Q で K・V を共有する

GQA(Grouped-Query Attention, Ainslie ら 2023)は、Q のヘッドをいくつかの組に分け、組ごとに1組の K・V を共有させます。図では、薄いオレンジの枠で囲んだ 4本ずつの Q が1組の K・V を使うように、下の段の箱が寄り集まりました。式の中で小さくなるのは、オレンジに光った H_kv の項だけです。

バーは K・V ヘッドを8本にした場合で、2×8×128=2,048個、MHA の16分の1です。12.8万トークンでも約32GB に収まります。Q のヘッド数はそのままなので、問いかけの多様さは残ります。公開されている設定では、Llama 2 70B が Q 64本に対して K・V 8本、Mistral 7B が Q 32本に対して K・V 8本という GQA の構成です。

  • GQA:何本かの Q で K・V を共有する
  • 減らすもの:KVキャッシュの量
  • KVキャッシュ = 2 ×
  • 層数 L
  • ×
  • KVヘッド数 H_kv
  • ×
  • ヘッド次元 d
  • ×
  • 文脈長 T
  • ×
  • バイト数 b
  • Q ヘッド (図は8本)
  • K・V ヘッド (組ごとに1つ)
  • 1層・1トークンあたりに保存する数(Qヘッド128本・ヘッド次元128の場合)
  • GQA(K・V ヘッド8本):2 × 8 × 128 = 2,048個(1/16)
  • 1トークン約0.25MB → 12.8万トークンの文脈で約32GB

MQA:K・V を1組だけにする

共有をとことん進めると、すべての Q ヘッドが1組の K・V を使う形になります。これが MQA(Multi-Query Attention, Shazeer 2019)です。図では2つの組がさらに1つにまとまり、K・V の箱が1つだけ残りました。GQA は、組の数を変えることで MHA(組の数=ヘッド数)と MQA(組の数=1)のあいだをつなぐ方式とも言えます。

バーはほとんど見えないほど短くなり、1層・1トークンあたり256個、MHA の128分の1です。ただし GQA の論文は、MQA では品質が落ちることがあると指摘しています。すべての Q が同じ K・V を見るので、表現の幅が狭くなるからです。そのため、品質と節約のバランスをとった GQA を採用する公開モデルが多くあります。

  • MQA:K・V を1組だけにする
  • 減らすもの:KVキャッシュの量
  • KVキャッシュ = 2 ×
  • 層数 L
  • ×
  • KVヘッド数 H_kv
  • ×
  • ヘッド次元 d
  • ×
  • 文脈長 T
  • ×
  • バイト数 b
  • Q ヘッド (図は8本)
  • K・V ヘッド (全体で1つ)
  • 1層・1トークンあたりに保存する数(Qヘッド128本・ヘッド次元128の場合)
  • MQA(K・V ヘッド1本):2 × 1 × 128 = 256個(1/128)
  • 1トークン約31KB → 12.8万トークンで約4GB。ただし品質が落ちることがある

MLA:K・V を小さな潜在ベクトルに圧縮する

DeepSeek-V2(2024)で報告された MLA(Multi-head Latent Attention)は、「ヘッド数 × ヘッド次元」の部分を別の方法で小さくします。K・V をヘッドごとに保存する代わりに、それらを作るもとになる低次元の潜在ベクトル c だけを保存します。図の紫の帯がそれで、DeepSeek-V2 では c の512次元に、位置情報(RoPE)用の64次元を足した576個です。各ヘッドの K・V は、c に行列を掛ければ復元できます。

576個は MHA の約57分の1で、論文は「グループ数2.25の GQA と同じ量」と書いています。MQA より大きいものの、MHA より良い性能だったと報告されている点が特徴です。60層・BF16 なら1トークン約69KB、12.8万トークンで約9GB です。

  • MLA:K・V を小さな潜在ベクトルに圧縮する
  • 減らすもの:KVキャッシュの量
  • KVキャッシュ = 2 ×
  • 層数 L
  • ×
  • KVヘッド数 H_kv
  • ×
  • ヘッド次元 d
  • ×
  • 文脈長 T
  • ×
  • バイト数 b
  • Q ヘッド (図は8本)
  • 保存するのは 潜在ベクトル c
  • 潜在ベクトル c:512 + 位置用 64
  • 各ヘッドの K・V は c から行列で復元できる
  • 1層・1トークンあたりに保存する数(Qヘッド128本・ヘッド次元128の場合)
  • MLA(DeepSeek-V2):512 + 64 = 576個(約1/57)
  • 1トークン約69KB → 12.8万トークンで約9GB(論文:GQA 2.25組ぶんと同じ量)

スライディングウィンドウ:遠い過去を保存しない

スライディングウィンドウ注意は、式の T の項に手をつけます。各層が見るのを直近の W トークンに限れば、それより古い K・V は捨てられるので、キャッシュは T ではなく min(T, W) に比例します。図の上の段では、オレンジの窓の中だけがキャッシュに残ります。

下のグラフでは、青い線(全部を見る)が文脈とともに伸び続けるのに対し、オレンジの線(窓を使う)は W を超えると増えなくなります。Mistral 7B は W=4,096 で、3.2万トークンの列ではキャッシュが8分の1になると報告しています。層を重ねると情報は窓の外へも少しずつ伝わるので、遠い過去が完全に消えるわけではありません。Gemma 2 のように、窓の層と全体を見る層を1層おきに並べる設計もあります。

  • スライディングウィンドウ:遠い過去を保存しない
  • 減らすもの:KVキャッシュの量
  • KVキャッシュ = 2 ×
  • 層数 L
  • ×
  • KVヘッド数 H_kv
  • ×
  • ヘッド次元 d
  • ×
  • min(T,W)
  • ×
  • バイト数 b
  • トークン列 (窓 W=4 の例)
  • 窓の外:K・V は捨てる(場所は上書きして使い回す)
  • キャッシュに残る W 個
  • 今
  • ↑ KVキャッシュの量
  • Mistral 7B:W=4,096 3.2万トークンでキャッシュ 1/8
  • 全部を見る:T に比例
  • 層を重ねると、届く範囲は 理論上 W × 層数 まで広がる
  • 窓を使う:W で頭打ち
  • Gemma 2:窓 4,096 の層と 全体を見る層を1層おきに
  • W
  • 文脈長 T →

PagedAttention(1):置き方の無駄

KVキャッシュには、大きさとは別の問題もあります。置き方です。リクエストが最終的に何トークン生成するかは、終わるまで分かりません。そこで従来の推論サーバーは、図のようにリクエストごとに最大長ぶんの連続した領域を前もって予約していました。濃い色のブロックが実際に使っている部分、薄い色が予約したまま空いている部分です。

こうなると、新しいリクエスト C は入る場所がなく待たされます。vLLM の論文(Kwon ら, SOSP 2023)は、既存のシステムで KVキャッシュ用のメモリのうち実際のトークンが入っていたのは20.4〜38.2%だけだったと測定しています。下のバーの赤い部分が、予約の空きと断片化で失われていた量です。第3章で見たとおり decode は一度にまとめる数が多いほど効率が上がるので、この無駄はそのまま速さの損になります。

  • PagedAttention(1):置き方の無駄
  • 減らすもの:KVキャッシュの量
  • GPU メモリ (KVキャッシュ用)
  • A0
  • A1
  • A2
  • A3
  • A 用に最大長ぶんを予約(使っているのは4つ)
  • B0
  • B1
  • B2
  • B 用に最大長ぶんを予約(使っているのは3つ)
  • 入れずに 待つ C
  • C0
  • C1
  • C2
  • C3
  • KVキャッシュ用に確保したメモリのうち、実際のトークンが入っている割合
  • 従来のシステム:20.4〜38.2%(vLLM 論文の測定)
  • 何トークン生成するかは終わるまで分からないので、最大長ぶんを連続で予約していた 空きはあるのに、新しいリクエスト C が入れない

PagedAttention(2):固定サイズのページで管理する

PagedAttention は、OS の仮想メモリと同じ考え方を使います。KVキャッシュを固定サイズのブロック(vLLM の既定では16トークンぶん)に区切り、必要になったときに空いているブロックを1つずつ割り当てます。ブロックは連続している必要がなく、どこにあるかはブロック表で覚えておきます。

図では予約の帯が消え、A と B のブロックが飛び飛びの場所に移り、待っていた C も空いた場所に入りました。無駄になるのは各リクエストの最後の1ブロックの中だけ(半端な A3 がそれです)で、vLLM のブログでは4%未満と説明されています。より多くのリクエストを同時に載せられるので、論文では同じ待ち時間で2〜4倍のスループットが報告されています。

  • PagedAttention(2):固定サイズのページで管理する
  • 減らすもの:KVキャッシュの量
  • GPU メモリ (KVキャッシュ用)
  • B0
  • A0
  • C1
  • B2
  • A2
  • C3
  • A3
  • C0
  • A1
  • B1
  • C2
  • ブロック表で 場所を記録
  • 例:A の表 A0→上段3番目 A1→下段6番目 A2→上段10番目 A3→下段1番目
  • KVキャッシュ用に確保したメモリのうち、実際のトークンが入っている割合
  • PagedAttention:無駄は最後の1ブロックの中だけ(4%未満と報告)
  • 1ブロック=16トークンぶん(vLLM の既定)。必要になったら空いているブロックを1つずつ割り当てる 空いた分で同時に処理できるリクエストが増える(論文ではスループット2〜4倍)

連続バッチング(1):まとめて始めると席が空く

第3章で見たとおり、decode はメモリ律速なので、多くのリクエストをまとめて(バッチで)処理するほど、重みを1回読むあいだにできる仕事が増えます。問題は、リクエストごとに生成する長さがばらばらなことです。

図は、同時に処理できる4つの「席」を時間の流れに沿って描いたものです。リクエスト単位でバッチを組む素朴な方式では、短い返事が先に終わっても、一番長い依頼4が終わるまで次のバッチを始められません。赤い部分は、席が空いたまま GPU が働いていない時間です。下の段では、次の依頼たちが、席が空いているのに待たされています。この図では、席が埋まっているのは全体の約59%だけです。

  • 連続バッチング(1):まとめて始めると席が空く
  • 減らすもの:逐次の待ち
  • 席1
  • 依頼1
  • 空いたまま(GPU が遊ぶ)
  • ここでやっと 次のバッチ
  • 席2
  • 依頼2
  • 席3
  • 依頼3
  • 席4
  • 依頼4
  • 時間(decode のステップ)→
  • 待っている 依頼
  • 依頼5
  • 依頼6
  • 依頼7
  • 席が実際に埋まっている割合:約59%(この図の場合)

連続バッチング(2):空いた席にすぐ次を入れる

Orca(Yu ら, OSDI 2022)は、スケジュールの単位をリクエスト全体から1ステップ(1トークンの生成)に変えました。毎ステップ、終わったリクエストを外し、待っているリクエストを空いた席に入れます。図では赤い空き時間が消え、依頼5〜7がすぐ席に入りました。論文は GPT-3 175B で、同じ待ち時間のまま最大36.9倍のスループットを報告しています。

下の図は、さらに一歩進んだ運用です。prefill は計算律速、decode はメモリ律速と性質が違うので、同じ GPU で混ぜると互いの足を引っぱります。そこで2つを別の GPU 群に分け、KVキャッシュを受け渡す方法が提案されています(DistServe など。DeepSeek-V3 の技術報告も、2つの段階を分けて配置しています)。

  • 連続バッチング(2):空いた席にすぐ次を入れる
  • 減らすもの:逐次の待ち
  • 席1
  • 依頼1
  • 依頼5
  • 依頼8
  • 席2
  • 依頼2
  • 依頼7
  • 席3
  • 依頼3
  • 依頼6
  • 依頼9
  • 席4
  • 依頼4
  • 依頼10
  • 時間(decode のステップ)→
  • さらに: 段階で分ける
  • prefill 用の GPU 群 計算律速:まとめて読む
  • KVキャッシュを渡す
  • decode 用の GPU 群 メモリ律速:1つずつ進む
  • 混ぜると互いの足を引っぱるので、別の GPU 群で動かす(DistServe など)
  • 席が埋まっている割合:ほぼ100%(終わった席にすぐ次が入る)

MoE(1):ルーターが上位 k 人の専門家を選ぶ

3つ目は、1トークンあたりの計算です。MoE(Mixture of Experts, 混合エキスパート)では、層の中の FFN を、専門家と呼ぶ小さな FFN の集まりに置き換えます。トークンが来ると、ルーターが専門家それぞれに点数をつけ、上位 k 人だけにそのトークンを計算させます。出力は、選ばれた専門家の出力を点数で重みづけして足したもの(Σ)です。

図は Mixtral 8x7B と同じ「8人から2人」の模式図で、点数のバーが長い2人だけが紫に光っています。誰が選ばれるかは、トークンごと・層ごとに変わります。もっと大きな実例には、DeepSeek-V3(256人から8人+全員が通る共通の1人)や Muse Spark Open(256人から8人、共通の専門家なし)があります。

  • MoE(1):ルーターが上位 k 人の専門家を選ぶ
  • 減らすもの:1トークンの計算
  • 点数
  • 専門家(8人)
  • 専門家1
  • 上位 k=2 人だけが このトークンを計算する
  • 専門家2
  • 専門家3
  • トークン
  • ルーター 点数をつける
  • 専門家4
  • Σ
  • 出力
  • 専門家5
  • 専門家6
  • 出力 = Σ(点数 × 専門家の出力) 和をとるのは選ばれた k 人だけ
  • 専門家7
  • 図は「8人から2人」の模式図 (Mixtral 8x7B と同じ k=2)
  • 専門家8

MoE(2):計算は活性パラメータ、メモリは総パラメータ

MoE には大きさを表す数が2つあります。全体の重みの数(総パラメータ)と、1トークンの計算で実際に使う重みの数(活性パラメータ)です。Mixtral 8x7B では、それぞれ約47B と約13B と報告されています。図では専門家が横一列に並んで上のバーになり、選ばれた2人が下の段へ降りてきました。

重み1個につき掛け算と足し算を1回ずつするので、1トークンの計算 ≈ 2 × 活性パラメータ FLOPs です。一方、誰が呼ばれるかは前もって分からないので、メモリには全員分を置く必要があり、ここで第4章の低精度化が効きます。DeepSeek-V3 は FP8 での学習を大規模に検証したと報告し、gpt-oss-120b は MoE の重みを4ビット(MXFP4)にして80GB の GPU 1枚に収めています。

  • MoE(2):計算は活性パラメータ、メモリは総パラメータ
  • 減らすもの:1トークンの計算
  • メモリに置く重み:総パラメータ(全員分)
  • 専門家1
  • 専門家2
  • 専門家3
  • 専門家4
  • 専門家5
  • 専門家6
  • 専門家7
  • 専門家8
  • 合計 47B
  • 青:Attention など全員が使う共通部分 紫:専門家(バーの長さはパラメータ数に比例)
  • 1トークンが使う重み:活性パラメータ(共通部分+選ばれた2人)
  • 専門家2
  • 専門家5
  • 合計 13B ← 1トークンが通るのはここだけ
  • 計算:1トークン ≈ 2 × 活性パラメータ = 2 × 13B ≈ 26 GFLOP
  • 重み1個につき掛け算と足し算が1回ずつ。同じ大きさの密なモデル(2 × 47B ≈ 94 GFLOP)の約3.6分の1
  • メモリ:重みは全員分。だから低精度化が効く(第4章)
  • BF16(2バイト):47B × 2 ≈ 94GB
  • FP8(1バイト):約47GB
  • 4ビット形式(NVFP4 は16個ごとに倍率を共有し、実質約4.5ビット):約26GB

投機的デコーディング(1):小さいモデルが先に下書きする

最後は逐次の待ちです。decode では、1トークン進むたびに大きなモデルの重みを HBM から読み直します(第3章)。次のトークンは前のトークンが決まらないと作れないので、この読み込みを1つずつ順番に待つしかありません。

投機的デコーディング(Leviathan ら, ICML 2023 など)は、小さくて速い下書きモデルに、先の k トークンを書かせます。図では k=4 で、緑の4つが下書きです。下書きモデルは軽いので、4回呼んでもすぐ終わります。そのあいだ大きなモデルはまだ何もしていません。下の段のように、ふつうなら大きなモデルの重みを5回読むところを、うまくいけば1回の読み込みで済ませるのが狙いです。

  • 投機的デコーディング(1):小さいモデルが先に下書きする
  • 減らすもの:逐次の待ち
  • 文章
  • 今日
  • は
  • とても
  • いい
  • 天気
  • だ
  • 下書きモデル(小)
  • 1つずつ 4回書く(k=4)。軽いのですぐ終わる
  • 本番モデル(大)
  • まだ待っている(重みを読むのは、あとで検証するときの1回だけ)
  • 大きいモデルの重みを HBM から読む回数(5トークン進めるには)
  • ふつうの decode
  • 5回、順番に読む
  • 投機的デコーディング
  • 大きいモデルは1回(+小さいモデル4回)
  • 全部受理されれば、1回の読み込みで最大5トークン進める

投機的デコーディング(2):まとめて検証する

大きなモデルは、下書きの位置を1回の順伝播でまとめて計算します。これは prefill と同じ形で、重みを1回読むあいだに複数トークンぶん計算できるので、第3章でいう算術強度が上がります。図では3つが受理され、4つ目は却下されて、大きなモデル自身の答え「です」が入りました。受理の規則は、出力の分布が大きなモデル単独のときと変わらないように作られています。

下書き1つが確率 α で受理されるとすると、1回の検証で進むトークン数の期待値は (1 − α^(k+1)) ÷ (1 − α) です。全部受理されれば k+1 個進みます。下のバーは k=4 の場合で、α が高いほど上限に近づきます。論文は T5-XXL で、出力を変えずに2〜3倍速くなったと報告しています。

  • 投機的デコーディング(2):まとめて検証する
  • 減らすもの:逐次の待ち
  • チェック
  • チェック
  • チェック
  • バツ
  • 文章
  • 今日
  • は
  • とても
  • いい
  • 天気
  • だ
  • です
  • 大きいモデルの答え
  • 下書きモデル(小)
  • 下書き済み(4つ)
  • 本番モデル(大)
  • 1回の順伝播で5か所をまとめて計算(prefill と同じ形)
  • 1回の検証で進むトークン数の期待値 ≈ (1 − α^(k+1)) ÷ (1 − α)
  • α:下書き1つが受理される確率(毎回同じと近似) k:下書きの数(ここでは4)
  • α=0.5
  • 約1.9 トークン
  • α=0.7
  • 約2.8 トークン
  • α=0.9
  • 約4.1
  • 上限 k+1 = 5

まとめ:『GPUとLLM』の5章をつなぐ

第1章では、GPU が数千のコアと Tensor Core、そして共有メモリから HBM へと続くメモリの階層でできていることを見ました。第2章では、LLM の計算のほとんどが行列積であること、第3章では、その行列積でも decode のように同じデータを使い回せない場面では、演算器ではなくメモリの帯域が速さを決めることを見ました。

第4章は、1枚に載らないモデルを量子化と並列化で載せる工夫、そしてこの第5章は、HBM との往復・KVキャッシュ・1トークンの計算・逐次の待ちを削る工夫でした。図の5つの小さな絵を左から右へたどると、フロンティアモデルの工夫の多くが「演算器を待たせないように、データの置き方と動かし方を設計する」ことだと分かります。新しい手法に出会ったら、まず「これは何を減らしているのか」を問うと、位置づけが見えやすくなります。

  • まとめ:『GPUとLLM』の5章をつなぐ
  • 第1章
  • 第2章
  • 第3章
  • 第4章
  • 第5章
  • GPUの構造
  • ほとんど行列積
  • メモリが壁
  • 載せる工夫
  • 削る工夫
  • GPUチップとHBM
  • 行列の掛け算
  • ルーフライン
  • 量子化と並列化
  • 削られた4本のバー
  • HBM
  • 数千のコアと Tensor Core。 速いメモリは小さく、 大きい HBM は遠い
  • LLM の計算の ほとんどは行列積。 過去の K・V は キャッシュに残す
  • 演算器は速い。 decode では メモリの帯域が 速さを決める
  • 量子化で小さく、 並列化で分けて、 1枚に載らない モデルを動かす
  • HBM往復・KV・ 計算・待ちを削る。 FlashAttention・ GQA/MLA・MoE・ 投機的デコーディング
  • フロンティアモデルの工夫の多くは、「演算器を待たせないように、 データの置き方と動かし方を設計する」こと

0 件のコメント

読み込み中…

権利侵害・不適切な内容の連絡: [email protected]