GQA(Grouped-Query Attention、Query headをgroup化してK/Vを共有するAttention)とMQA(Multi-Query Attention、すべてのQuery headで1組のK/Vを共有するAttention)は、Query headの多様性を残しながらKV head数を減らす設計です。KV Cacheの容量とdecode時に読み出すK/Vのbyte数を抑えることが主な狙いです。
「Attention headを減らす」とだけ覚えると正確ではありません。複数のQuery headは維持し、減らすのはKey/Value headです。またKV Cache部分が4分の1になっても、model weightやactivationを含む総VRAMが4分の1になるわけではありません。

- 3文要約
- 代表的な論文
- MHAを基準にhead構成を整理する
- MQAはK/Vを1組へ共有する
- GQAはMHAとMQAの中間を選べる
- 同じK/Vを使っても出力は同じにならない
- KV Cache容量はKV head数に比例する
- 32層・8192 tokenで容量を計算する
- K/V projection parameterも減る
- 品質・速度・容量のtrade-off
- MHA checkpointは設定変更だけでGQAにならない
- model configで方式を確認する
- PyTorch SDPAでshapeを確認する
- KV Cache・FlashAttention・量子化との違い
- 導入・model選択のチェックリスト
- よくある質問
- まとめ
- 参考文献
3文要約
- MHAはQueryと同数のK/V headを持ち、MQAはK/Vを1組へ共有し、GQAは複数のQuery head groupごとに1組のK/Vを共有します。
- 他の条件が同じなら、KV Cache payloadとdecode時のK/V読出し量はKV head数に比例するため、MHAに対する比率は\(H_{kv}/H_q\)で概算できます。
- K/V共有を強くすると容量と帯域を減らせる一方、品質、kernel対応、checkpoint変換がtrade-offになるため、model configと実測結果を確認します。
代表的な論文
MQAの代表資料は、Noam ShazeerのFast Transformer Decoding: One Write-Head is All You Needです。incremental decode(生成時に1 tokenずつ順番に計算する処理)では、過去のK/V tensorを各stepで読み出すmemory bandwidthがbottleneckになり得ると分析し、複数のQuery headでK/Vを共有するMQAを提案しました。
GQAの代表資料は、Joshua AinslieらのGQA: Training Generalized Multi-Query Transformer Models from Multi-Head Checkpointsです。K/Vを1組まで集約するMQAと、headごとにK/Vを持つMHAの間として、複数groupのK/V headを使うGQAを導入しました。同論文は既存のMHA checkpointからK/V projectionをmean poolingし、追加pretrainingで適応させるuptrainingも扱っています。
MHAを基準にhead構成を整理する
MHA(Multi-Head Attention、複数headで異なる表現へ注目するAttention)では、各headがそれぞれQuery、Key、Valueを持ちます。Attention Is All You Needで導入された基本形です。
batch sizeを\(B\)、系列長を\(N\)、Query head数を\(H_q\)、KV head数を\(H_{kv}\)、1 headの次元を\(d_h\)とします。tensor shapeは次のように書けます。
MHAでは\(H_q=H_{kv}\)です。たとえばQuery headが8個なら、Key headも8個、Value headも8個あります。各head \(i\)は自分に対応する\(Q_i\)、\(K_i\)、\(V_i\)でAttentionを計算します。
各headの出力を連結してoutput projectionへ渡すため、複数の視点を保てます。一方、decode中のKV CacheにもheadごとのK/Vを保存するため、KV head数が多いほどcacheは大きくなります。Self-Attentionの式を先に確認したい場合は、Self-AttentionとScaled Dot-Product Attentionの解説を参照してください。
MQAはK/Vを1組へ共有する
MQAではQuery headを複数残したまま、Key headとValue headをそれぞれ1個にします。
各Query headは独自の\(Q_i\)を持ちますが、全headが共通の\(K_0\)と\(V_0\)を参照します。
この変更により、過去tokenごとに保存するK/Vは1組で済みます。Query headが32個なら、MHAの32組に対してMQAは1組です。他条件が同じK/V payloadだけを比べれば、容量と読出し量はMHAの1/32になります。
ただし、Query headが1個になるわけではありません。Query projection、headごとのscore、softmax weight、出力は残ります。MQAは「single-head Attentionへ戻す方式」ではなく、「Multi-Query、single-KV」の設計です。
GQAはMHAとMQAの中間を選べる
MQAはK/V共有を最も強くするため、KV Cacheと帯域を大きく減らせます。一方、K/V表現の多様性も1組へ集約します。GQAはQuery headを複数groupへ分け、groupごとに1組のK/V headを持たせます。
Query head数を\(H_q\)、KV head数を\(H_{kv}\)とすると、一般的なGQAは次の範囲です。
1個のKV headを共有するQuery head数、つまりgroup size \(s\)は次の式です。
| 方式 | Query head数 | KV head数 | 共有範囲 | KV Cache payload |
|---|---|---|---|---|
| MHA | \(H_q\) | \(H_q\) | headごとに専用 | 基準 |
| GQA | \(H_q\) | \(1より多くH_q未満\) | Query groupごとに共有 | 中間 |
| MQA | \(H_q\) | 1 | 全Query headで共有 | 最小 |
GQAのgroup数が1ならMQA、group数がQuery head数と等しければMHAです。つまりMQAとMHAはGQAの両端として表せます。

「group数」と「group size」を分ける
用語を逆に読むと設定を間違えます。
- group数: KV head数\(H_{kv}\)と同じ
- group size: 1個のKV headを共有するQuery head数\(H_q/H_{kv}\)
たとえば\(H_q=32\)、\(H_{kv}=8\)なら、group数は8、group sizeは4です。Query head indexを0から数える場合、対応は次のようになります。
| KV head | 共有するQuery head |
|---|---|
| 0 | 0、1、2、3 |
| 1 | 4、5、6、7 |
| 2 | 8、9、10、11 |
| … | … |
| 7 | 28、29、30、31 |
連続したgroupへ均等に割り当てるなら、Query head \(i\)が使うKV head index \(g(i)\)は次の式です。
この構成では\(H_q\)が\(H_{kv}\)で割り切れる必要があります。現行PyTorchのGQA機能も、この割り切りを制約にしています。

同じK/Vを使っても出力は同じにならない
GQAやMQAでは複数のQuery headが同じK/Vを参照します。それでも、各headの出力が同じになるわけではありません。
同じgroupに属するQuery head \(i\)と\(j\)を考えます。両者は同じ\(K_g\)、\(V_g\)を使いますが、\(Q_i\)と\(Q_j\)は別のprojectionから得られます。
\(Q_i\neq Q_j\)なら、通常はscoreとattention weight \(A_i,A_j\)も異なります。その結果、同じ\(V_g\)に対するweighted sumも異なります。
共有するのはK/Vという参照対象です。「どの過去tokenへ、どの強さで注目するか」はQueryごとに変わります。

KV Cache容量はKV head数に比例する
DecoderのKV Cacheが保存する生のK/V payloadを概算します。layer数を\(L\)、batch sizeを\(B\)、保存token数を\(N\)、KV head数を\(H_{kv}\)、head dimensionを\(d_h\)、1要素のbyte数を\(b\)とすると、容量は次の式です。
先頭の2はKeyとValueの2 tensorを表します。
Queryは次のtokenを計算するたびに新しく作るため、通常のKV Cacheへ過去Queryを保存しません。GQA/MQAが減らすのは式中の\(H_{kv}\)です。
MHAに対するKV Cache比は、他条件が同じなら次の値になります。
decodeの各stepでは、現在のQueryから過去すべてのK/Vを参照します。そのためK/V読出しbyte数も、同じ実装条件のHkvに比例する部分があります。これはKV Cacheを保存して再計算を避ける仕組みとは別の層です。基礎はKV Cacheの記事で説明しています。

32層・8192 tokenで容量を計算する
次の条件で、1 requestのK/V payloadを比較します。
- layer数\(L=32\)
- batch size\(B=1\)
- 保存token数\(N=8,192\)
- Query head数\(H_q=32\)
- head dimension\(d_h=128\)
- dtypeはBF16、1要素\(b=2\) bytes
MHAは4 GiB
MHAでは\(H_{kv}=32\)です。
GQAは1 GiB
\(H_{kv}=8\)のGQAでは、group sizeは4です。
MHAに対してKV Cache payloadは1/4です。
MQAは128 MiB
MQAでは\(H_{kv}=1\)です。
MHAに対して1/32です。
| 方式 | \(H_q\) | \(H_{kv}\) | group size | K/V payload |
|---|---|---|---|---|
| MHA | 32 | 32 | 1 | 4 GiB |
| GQA | 32 | 8 | 4 | 1 GiB |
| MQA | 32 | 1 | 32 | 128 MiB |

これはK/V要素を一度ずつ数えた生payloadです。model weight、activation、Attention workspace、allocatorの予約・断片化、padding、cache metadataは含みません。したがってGQAでK/V payloadが1/4になっても、総VRAMが1/4になるとは限りません。
K/V projection parameterも減る
GQA/MQAでは、cacheだけでなくK/Vを生成するprojection matrixも狭くなります。hidden sizeを\(d_{model}\)とすると、biasを除くshapeは次のとおりです。
\(H_q\)を維持して\(H_{kv}\)だけを減らすため、\(W_Q\)とoutput projectionは同条件なら維持され、\(W_K\)と\(W_V\)が小さくなります。
\(d_{model}=4096\)、\(H_q=32\)、\(d_h=128\)の1 Attention layerで、K/V projection parameterを合計すると次の値です。
| 方式 | \(H_{kv}\) | K/V projection parameter |
|---|---|---|
| MHA | 32 | 33,554,432 |
| GQA | 8 | 8,388,608 |
| MQA | 1 | 1,048,576 |
これはmodel全parameterの比較ではありません。MLP、embedding、Q projection、output projectionなどは残るため、model file全体が同じ比率で小さくなるわけではありません。

品質・速度・容量のtrade-off
KV head数を減らすと、cache容量と読出し量を減らせます。一方、複数Query headが利用できるK/V表現の種類も減ります。
| 比較軸 | MHA | GQA | MQA |
|---|---|---|---|
| K/V表現の数 | 多い | 中間 | 1組 |
| KV Cache | 大きい | group数に応じて削減 | 最小 |
| decodeのK/V読出し | 多い | 中間 | 少ない |
| 品質の余地 | K/V headごとに独立 | 共有と多様性の折衷 | 共有が最も強い |
| kernel実装 | 広く対応 | group mapping対応が必要 | 共有K/V対応が必要 |
MQA原論文は、WMT14翻訳とBillion Word language modelingの実験で、baselineに対する品質差を小さく抑えつつincremental decodeを高速化できたと報告しています。ただし、当時のmodel、TPU、系列長、batch、実装における結果です。
GQA論文は、uptrained GQAがMHAに近い品質とMQAに近い速度を得たと報告しています。これも論文のmodelと評価条件での結果であり、「GQAなら常に品質低下なし」「MQAと同じ速度」とは一般化できません。
実際の選択では、KV head数だけでなく次を同条件で測ります。
- task別のloss、perplexity、生成品質
- prefill latencyとdecode latency
- inter-token latencyとthroughput
- request数、context長ごとのpeak memory
- runtimeが選んだAttention kernel
MHA checkpointは設定変更だけでGQAにならない
既存MHA modelのnum_key_value_headsだけを書き換えても、K/V projectionのshapeが合いません。さらに、異なるK/V headを共有表現へまとめるため、modelが新しい構造へ適応する必要があります。
GQA論文のuptrainingは、概念的に次の2段階です。
- 同じgroupに入るMHAのK/V projection headをmean poolingし、少数のK/V headへ変換する
- 変換したcheckpointを元のpretraining recipeの一部で追加学習する
MQAへ変換する場合は、全K/V headを1組へmean poolingします。GQAならgroup内だけを平均します。論文は元のpretraining computeの5%を用いたrecipeを評価しましたが、この5%はすべてのmodelに必要十分な値ではありません。

modelを新規学習する場合は、初めからGQA/MQAのprojection shapeで学習できます。既存checkpointを変換する場合は、weight変換、追加学習、品質評価を一つの工程として扱います。
model configで方式を確認する
Hugging Face Transformersの現行LlamaConfig documentでは、num_attention_headsとnum_key_value_headsから方式を区別できます。
| config条件 | 方式 |
|---|---|
num_key_value_heads == num_attention_heads |
MHA |
1 < num_key_value_heads < num_attention_heads |
GQA |
num_key_value_heads == 1 |
MQA |
configを確認する最小例です。
from transformers import AutoConfig
model_id = "your-model-id"
config = AutoConfig.from_pretrained(model_id)
query_heads = config.num_attention_heads
kv_heads = getattr(config, "num_key_value_heads", None) or query_heads
# headの対応を曖昧にしないため、group sizeを出す前に割り切りを検証します。
if query_heads % kv_heads != 0:
raise ValueError(
"num_attention_heads must be divisible by num_key_value_heads"
)
if kv_heads == query_heads:
attention_type = "MHA"
elif kv_heads == 1:
attention_type = "MQA"
else:
attention_type = "GQA"
group_size = query_heads // kv_heads
print(
f"type={attention_type}, Hq={query_heads}, "
f"Hkv={kv_heads}, group_size={group_size}"
)
古いconfigや別architectureではfield名・意味が異なる可能性があるため、対象modelの公式documentと実装も確認してください。
PyTorch SDPAでshapeを確認する
現行PyTorchのscaled_dot_product_attentionはenable_gqa=Trueを提供しています。QueryとK/Vのhead数を別shapeで渡します。
import torch
import torch.nn.functional as F
batch_size = 2
query_heads = 32
kv_heads = 8
sequence_length = 1024
head_dimension = 128
query = torch.randn(
batch_size,
query_heads,
sequence_length,
head_dimension,
device="cuda",
dtype=torch.float16,
)
key = torch.randn(
batch_size,
kv_heads,
sequence_length,
head_dimension,
device="cuda",
dtype=torch.float16,
)
value = torch.randn_like(key)
# K/Vを手動複製せず、GQA対応backendへhead mappingを伝えるために有効化します。
output = F.scaled_dot_product_attention(
query,
key,
value,
dropout_p=0.0,
is_causal=True,
enable_gqa=True,
)
公式documentが示す主なhead条件は次のとおりです。
enable_gqaはexperimental機能で、backend、device、Nested Tensorなどの対応条件はversionにより変わります。reference実装の説明にK/Vのrepeat_interleaveが現れても、cacheを物理的にHq個へ恒久複製することがGQAの目的ではありません。実際のfused kernelが使われたか、fallbackや一時的な展開がないかをprofilerとmemory計測で確認します。
KV Cache・FlashAttention・量子化との違い
| 技術 | 変える対象 | 主に減らすもの |
|---|---|---|
| KV Cache | 過去K/Vを保存して再利用 | decode時のK/V再計算 |
| GQA/MQA | Query headに対するKV head数 | KV Cache payloadとK/V読出し |
| FlashAttention | Attention内部の計算順序とdata movement | N×N中間値とHBM IO |
| 量子化 | weight、activation、KV Cache等のbit幅 | 要素あたりのbyte数 |
これらは排他的ではありません。GQA modelでKV Cacheを使い、対応kernelでFlashAttentionを実行し、weightやcacheを量子化する構成もあり得ます。
FlashAttentionの記事では、KV head数ではなくN×N中間値をHBMへ保存しない計算順序を扱っています。量子化の記事では、head数ではなく値のbit幅を減らします。
導入・model選択のチェックリスト
num_attention_headsとnum_key_value_headsを確認する- \(H_q/H_{kv}\)からgroup sizeを計算し、割り切れることを確認する
- KV Cacheのdtype、layer数、context長を含めてpayloadを概算する
- 総VRAMとKV Cache部分の削減率を分ける
- training、prefill、decodeを分けてlatencyとmemoryを測る
- runtimeとAttention kernelが対象GQA/MQA shapeへ対応するか確認する
- fallbackやK/Vの物理複製が起きていないかprofilerで確認する
- perplexityだけでなく、実運用taskの生成品質を比較する
- MHA checkpoint変換ではweight変換と追加学習を計画する
KV head数の少なさだけで方式を選ばず、品質条件と同時request数、context長、hardware、runtimeを同じ測定条件へ揃えます。
よくある質問
GQAではQuery headも減りますか
通常は減らしません。Query head数\(H_q\)を維持し、Key/Value head数\(H_{kv}\)を減らします。そのため各Query headは別のQとattention weightを持てます。
GQAのgroup数はどう決まりますか
group数はKV head数と同じです。\(H_q=32\)、\(H_{kv}=8\)なら8 groupで、1 groupのQuery head数は4です。最適値はmodelの学習・品質・推論条件に依存します。
GQAにするとAttention計算も4分の1になりますか
KV CacheとK/V読出し、K/V projectionには\(H_{kv}\)削減の効果があります。一方、Query head数と各Queryのscore・weighted sumは残るため、Attention全体のFLOPsやlatencyが同じ比率で減るとは限りません。
既存MHA modelのconfigだけ変更できますか
できません。K/V projection weightのshapeが変わります。GQA論文のようにgroup内headをmean poolingしてcheckpointを変換し、追加学習で適応させる方法がありますが、必要な学習量と品質はmodelごとに評価します。
MQAとGQAはKV Cacheの代わりですか
いいえ。KV Cacheを使う前提で、cacheに保存するK/V head数を減らします。過去K/Vを保存しない場合、decode時の再計算を避けるというKV Cacheの利点は得られません。
まとめ
GQAとMQAは、複数のQuery headを残しながらK/V headを共有し、KV Cacheとdecode時のK/V読出しを減らすAttention改良です。MHAは\(H_{kv}=H_q\)、MQAは\(H_{kv}=1\)、GQAはその中間に位置します。
理解の要点は、group数\(H_{kv}\)とgroup size\(H_q/H_{kv}\)を分けることです。KV Cacheの削減比は\(H_{kv}/H_q\)で概算できますが、総VRAM、Attention全体のFLOPs、latency、品質は同じ比率では変わりません。
model configではQuery/KV head数を確認し、runtimeでは対応kernelとfallbackを確認します。既存MHA checkpointを変換する場合は、projectionのmean poolingだけで終わらせず、追加学習とtask別品質評価まで含めて判断します。



コメント