3行でいうと

  • 目安は「重み+KVキャッシュ+余裕」です。重みは、パラメータ数×1つあたりのバイト数です。
  • KVキャッシュは、1トークンあたり「2×層数×KVヘッド数×ヘッド次元×バイト数」で、会話の長さと同時利用者に比例します。
  • Qwen3-8Bは、BF16の重みが約16.4GB、1トークンのKVが約144KiB(32,768トークンで約4.8GB)です。
  • Hugging Faceの文書は、推論ではモデルのサイズに最大で約20%の上乗せがあるとしています。

この記事は、実際に使って確かめた記録ではありません。この記事は公式の文書や論文を読んでまとめたものです。計算例の数字は、設定ファイルの値から僕らが計算したものです。

先に結論

GPUのメモリ(VRAM、グラフィックス用のメモリ)に必要な量の目安は、次の式です。

必要な量 ≒ 重みの大きさ × 1.0〜1.2 + KVキャッシュ × 同時に扱う会話の数

見立てです。「モデルが載るか」と「長い文脈や複数人で使えるか」は別の問題です。重みだけなら載っても、KVキャッシュで足りなくなることが、長い文脈や同時利用ではよく起きると思います。

前提:用語

式を一つずつ見る

1. 重み

重みの大きさは、パラメータ数×バイト数です。EleutherAIの解説は、int8が1バイト、fp16とbf16が2バイト、fp32が4バイトと書いています。

量子化したときのバイト数は、形式ごとに違います。llama.cppのREADMEが示すLlama-3.1-8Bでは、Q8_0が1重みあたり8.5008ビット、Q4_K_Mが4.8944ビットです(形式の詳細は「量子化の形式を比べる」の記事にあります)。この記事の計算例では、この2つの値を他のモデルにも流用しました。実際のファイルでは少し違うので、確実なのはファイルの大きさです。

2. KVキャッシュ

1トークンあたりの要素数は、2(KeyとValue)×層数×KVヘッド数×ヘッド次元です。これに、1要素のバイト数(BF16なら2)を掛けます。

必要な数字は、モデルのconfig.jsonにあります。今回読んだ3つのモデルの値です。

モデル 層数 KVヘッド数 ヘッド次元 パラメータ数 出典
Qwen3-8B 36 8 128 約81.9億 Qwen公式のconfig.jsonとHugging Faceの情報
Qwen3-32B 64 8 128 約327.6億 同上
Llama 3.1 70B 80 8 128 約705.5億 層数・KVヘッド数はLlama 3の論文(表3)。パラメータ数はHugging Face上の複製の情報

Llama 3の論文の表3では、70Bの層数が80、注意ヘッドが64、KV/ヘッドが8、モデルの次元が8,192です。ヘッド次元は8,192÷64で128になります(僕らの計算です)。

僕らの計算です。

モデル 1トークンあたり(BF16) 4,096トークン 32,768トークン 131,072トークン
Qwen3-8B 147,456バイト(144KiB) 0.60GB 4.83GB 19.33GB
Qwen3-32B 262,144バイト(256KiB) 1.07GB 8.59GB 34.36GB
Llama 3.1 70B 327,680バイト(320KiB) 1.34GB 10.74GB 42.95GB

GBは10の9乗バイトです。GiB(2の30乗バイト)では、約7%小さい数字になります。

GQAの効果も計算できます。Qwen3-8Bは、注意ヘッドが32、KVヘッドが8です。もしKVヘッドが32あれば、1トークンあたり576KiBで、実際の144KiBの4倍です(僕らの計算です)。

3. 余裕(上乗せ)

Hugging Faceのaccelerateの文書は、「推論では、最大で約20%の追加を見込める」とEleutherAIを引いて書いています。EleutherAIの解説は、推論時のメモリを「モデルのメモリ×1.2」程度とする経験則を示しています。ただし、accelerateの文書は、この計算機が測るのは「モデルを読み込むのに必要なメモリ」で、推論を実行するための量ではない、とも書いています。

つまり、1.2は重みへの上乗せの目安で、KVキャッシュは別に足す必要があります。

計算例:32,768トークンの会話を1つ扱う場合

僕らの計算です。重み×1.2+KVキャッシュ(BF16)を「安全側」の列にしました。

モデル 重みの形式 重み KV(32,768) 合計 安全側(重み×1.2+KV)
Qwen3-8B BF16 16.4GB 4.8GB 21.2GB 24.5GB
Qwen3-8B Q8_0相当 8.7GB 4.8GB 13.5GB 15.3GB
Qwen3-8B Q4_K_M相当 5.0GB 4.8GB 9.8GB 10.8GB
Qwen3-32B BF16 65.5GB 8.6GB 74.1GB 87.2GB
Qwen3-32B Q8_0相当 34.8GB 8.6GB 43.4GB 50.4GB
Qwen3-32B Q4_K_M相当 20.0GB 8.6GB 28.6GB 32.6GB
Llama 3.1 70B BF16 141.1GB 10.7GB 151.8GB 180.1GB
Llama 3.1 70B Q8_0相当 75.0GB 10.7GB 85.7GB 100.7GB
Llama 3.1 70B Q4_K_M相当 43.2GB 10.7GB 53.9GB 62.5GB

見立てです。この表を見ると、4ビット相当にしても、70Bモデルは24GBのGPU1枚には載りません。32Bモデルは、4ビット相当で重みが約20GBなので、24GBのGPUでは、KVキャッシュの余地がほとんど残らないと思います。8Bモデルなら、4ビット相当で10GB前後に収まります。

同時利用者が増えるとどうなるか、FP8のKVキャッシュ、計算の式

同時利用者

KVキャッシュは会話ごとに別なので、人数に比例して増えます。僕らの計算です。Qwen3-8B(BF16のKV)で、8,192トークンの会話を10人分同時に持つと、147,456バイト×8,192×10で約12.1GBです。重みの16.4GBとは別に必要です。

KVキャッシュを小さくする

vLLMの文書によると、--kv-cache-dtype fp8でKVキャッシュをFP8にでき、「メモリを大きく減らせる」と書かれています。具体的な割合は文書にありませんでした。僕らの計算では、BF16(2バイト)からFP8(1バイト)に半減するはずです(Qwen3-8Bの32,768トークンで4.83GBから2.42GB)。精度の影響は、文書に数値の測定結果がありませんでした。Hugging Faceのtransformersの文書にも、量子化したキャッシュ(int2、int4、int8)の説明があります。短い文脈では遅くなることもある、と注意書きがあります。

vLLMのメモリの割り当て

vLLMのソースコード(cache.py)では、gpu_memory_utilizationの既定値が0.92で、「モデル実行に使うGPUメモリの割合」です。残りの領域から、重みと一時領域を引いた分がKVキャッシュに回ります。僕らの計算です。80GBのGPUでQwen3-8BをBF16で動かす場合、0.92×80=73.6GB、重み16.4GBを引くと、KVに使える上限は約57GBです(一時領域の分は、さらに引かれます)。1トークンあたり147,456バイトなので、約38.8万トークン分の目安です。

計算の式(Python、僕らが書いた式)

def kv_bytes_per_token(layers, kv_heads, head_dim, bytes_per=2):
    return 2 * layers * kv_heads * head_dim * bytes_per

def need_gb(params, bits, layers, kv_heads, head_dim, ctx, users=1):
    w = params * bits / 8
    kv = kv_bytes_per_token(layers, kv_heads, head_dim) * ctx * users
    return (1.2 * w + kv) / 1e9

print(need_gb(8.19e9, 16, 36, 8, 128, 32768))  # 約24.5

実測との突き合わせ

Appleの機械学習研究の記事(2025年11月19日)の表に、Qwen3-8B(BF16)のメモリが17.46GBとあります。条件は、入力4,096トークン+生成128トークンです。

僕らの計算です。重み16.38GBに、4,224トークン分のKV(約0.62GB)を足すと約17.0GBで、近い値です。ただし、記事の「Memory (GB)」が何を測ったものか(GBかGiBか、一時領域を含むか)は読んだ範囲で確認できていません。偶然の一致かもしれないので、傍証程度に見てください。

判断の基準

見立てです。

  1. まず重みを計算する。載らなければ、より小さい量子化か、複数のGPUか、より小さいモデルへ。
  2. 次に、使いたい最大の文脈長と同時利用者数で、KVキャッシュを足す。
  3. 足りなければ、文脈長を短くする、同時数を減らす、KVキャッシュをFP8にする、GPUを増やす(vLLMの文書は、tensor_parallel_sizeでモデルを複数のGPUに分けられる、と案内しています)。
  4. ぎりぎりに詰めず、余裕を残す。

よくあるつまずき

気をつけること

出典

更新履歴