実験日: 2026-08-24
GPU: NVIDIA GeForce RTX 5070 Ti 16GB / WSL2 Ubuntu / Ollama 0.32.15
「VRAM 16GBなら何BのLLMまで動かせるのか」を、モデルファイルの容量だけで判断するのは危険です。実行時にはweight以外にもKV cacheやbufferが必要で、速度にはmodel family、量子化、context長、GPUへのoffload率も影響します。
12Bが16GBへ載るかだけでなく、待ち時間を含めて実用になるかを分けて測ります。
そこで同じPC上でgemma3:4b、qwen3:8b、gemma3:12bを実際に動かしました。全モデルをQ4_K_M、context 4,096、出力256 tokenへ揃え、モデルを一度unloadした後のload時間、温間の生成速度、GPU memoryを測りました。
3モデルとも16GB VRAMへ全層を載せられました。温間生成速度の中央値は4Bが179.5 tok/s、8Bが127.8 tok/s、12Bが84.2 tok/sです。ピークのGPU使用量は約4.8、6.4、9.7GiBでした。
4B・8B・12Bを載せた結果
速度と待ち時間
| model | cold reload | warm TTFC | warm生成速度 |
|---|---|---|---|
| Gemma 3 4B | 2.06秒 | 65.7ms | 179.5 tok/s |
| Qwen 3 8B | 1.48秒 | 44.7ms | 127.8 tok/s |
| Gemma 3 12B | 4.80秒 | 126.2ms | 84.2 tok/s |
規模とメモリ
| model | 実parameter | model file | peak GPU used |
|---|---|---|---|
| Gemma 3 4B | 4.3B | 3.1GiB | 4.8GiB |
| Qwen 3 8B | 8.2B | 4.9GiB | 6.4GiB |
| Gemma 3 12B | 12.2B | 7.6GiB | 9.7GiB |
このPCでの実用上の選び方です。
- 応答速度と余裕を優先するなら4B
- 速度と規模の中間を試すなら8B
- 16GB内でより大きいmodelを全GPU offloadしたいなら12B
- 長いcontextを使う場合は、この表だけで判断せずKV cache込みで再測定する
重要な注意があります。4Bと12BはGemma 3ですが、8BだけQwen 3です。したがって8Bの差にはparameter数だけでなく、architecture、tokenizer、学習dataなどの違いが混ざります。「8Bだからこの速度」と一般化できる比較ではありません。

「4B」「8B」は何を表すのか
Bはbillion、10億です。4B modelならparameterがおよそ40億あります。parameterは学習で得たweightで、入力tokenから次のtokenの確率を計算するために使われます。
ただしmodel名の丸めと実値は一致しません。Ollamaの/api/showで今回のGGUF metadataを読むと、実値は次の通りでした。
gemma3:4b 4.3B parameters
qwen3:8b 8.2B parameters
gemma3:12b 12.2B parameters
parameter数が増えると一般には表現力が増える可能性がありますが、品質はparameter数だけでは決まりません。学習data、学習方法、architecture、量子化、promptとの相性も効きます。
Ollama公式libraryではGemma 3に4B・12Bなど、Qwen 3に8Bなどのvariantが用意されています。公式ページ上の配布容量はGemma 3 4Bが3.3GB、Qwen 3 8Bが5.2GB、Gemma 3 12Bが8.1GBです。
なぜ12Bが約7.6GiBのファイルになるのか
12.2B個のparameterをFP32、つまり1個4 byteで保存すると、概算は約45.4GiBです。
12.2 × 10^9 parameters × 4 bytes ≒ 48.8 GB ≒ 45.4 GiB
しかし今回の12B model fileは約7.6GiBです。理由はQ4_K_M量子化です。weightを平均4 bit程度の低いbit幅へ圧縮し、blockごとのscaleなどを追加して保存します。
実際のmetadataは全モデルで次の値でした。
format: gguf
quantization_level: Q4_K_M
「4 bitだからFP32の厳密に8分の1」とはなりません。scale、metadata、一部の高精度tensorなどのoverheadがあるためです。また、これは主にweightの話です。実行時VRAMはmodel fileより大きくなります。
実行時VRAMはmodel fileより大きい
今回のmodel fileとピークGPU使用量です。
model file peak GPU used 差
Gemma 3 4B 3.1 GiB 4.8 GiB +1.7 GiB
Qwen 3 8B 4.9 GiB 6.4 GiB +1.5 GiB
Gemma 3 12B 7.6 GiB 9.7 GiB +2.1 GiB
実行時には少なくともweightに加えて次が必要です。
- 入出力tensorと各層の作業buffer
- attentionのKV cache
- Ollama/CUDA runtimeが確保する領域
- desktop表示など、別processが使うGPU memory
ここで測ったpeak GPU usedはnvidia-smiが返すGPU全体の使用量です。Ollama processだけの割当量ではありません。一方、Ollamaの/api/psでは全モデルが100% GPUへ載ったことを確認しました。
12Bのピークは9,909MiBで、GPU総量16,303MiBに対して約6.2GiB残りました。ただし「残りで128K contextも必ず動く」という意味ではありません。KV cacheはcontext長、layer数、head構成、cache量子化によって増えます。この記事では比較を揃えるためnum_ctx=4096に固定しています。
実験環境
OS Windows 11 + WSL2 Ubuntu
GPU NVIDIA GeForce RTX 5070 Ti
VRAM 16,303 MiB
driver 595.71
Ollama 0.32.15(WSL側)
model format GGUF
quantization Q4_K_M
モデルはWSLで取得しました。
ollama pull gemma3:4b
ollama pull qwen3:8b
ollama pull gemma3:12b
ollama list
取得後のollama listです。
NAME SIZE
gemma3:4b 3.3 GB
qwen3:8b 5.2 GB
gemma3:12b 8.1 GB
条件を固定する
速度比較に使ったpromptの主要要件です。完全な入力はraw JSONに保存しています。
勾配降下法で学習率が大きすぎると学習が不安定になる理由を説明してください。
損失曲面、更新式、発散の兆候、
切り分け手順、改善策の5項目を見出し付きで扱い、具体例を含めて700字以上で書いてください。
API optionを揃えました。
payload = {
"model": model,
"prompt": prompt,
"stream": True,
"think": False,
"keep_alive": "10m",
"options": {
"temperature": 0,
"seed": 42,
"num_ctx": 4096,
"num_predict": 256,
},
}
temperature=0と固定seedでsamplingの揺れを抑えました。Qwen 3のthinking tokenが速度へ混ざらないようthink=falseです。全モデルがnum_predict=256へ達したので、出力token数も揃っています。
Ollama Generate APIはstreaming responseの最後にload_duration、prompt_eval_count、prompt_eval_duration、eval_count、eval_durationをnanosecond単位で返します。生成速度は次で計算しました。
tokens_per_second = eval_count / (eval_duration / 10^9)
coldとwarmを分ける
modelがGPUに残っているかで待ち時間が変わります。
cold: keep_alive=0でunload → 次のgenerateで再ロード
warm: 直前と同じmodelをGPUへ残したままgenerate
各modelでcold→warmを3 cycle行いました。streamで最初の本文が届くまでをTTFC(time to first content)としてwall clockでも測っています。同時に50ms間隔でnvidia-smiを呼び、GPU memoryとutilizationを記録しました。
ここでいうcoldは「OSを再起動し、disk cacheも空にした完全cold」ではありません。modelをOllamaからunloadした再ロードです。普段modelを切り替えたときの待ち時間に近い指標です。
温間では4Bが179.5 tok/s、12Bが84.2 tok/s
温間生成速度の3回の範囲です。
Gemma 3 4B 179.2 ~ 180.2 tok/s 中央値 179.5
Qwen 3 8B 127.3 ~ 127.9 tok/s 中央値 127.8
Gemma 3 12B 83.4 ~ 84.5 tok/s 中央値 84.2
12Bは4Bの約46.9%の速度です。それでも84 tok/sなら、対話用途では人の読書速度より十分速く出力が流れます。短いcode補完を繰り返す用途では4Bの低latencyが効き、長めの回答を待てる用途では12Bも現実的です。
warm TTFCは4B 65.7ms、8B 44.7ms、12B 126.2msでした。この値はstream上の最初の本文chunkであり、network越しのcloud APIにおけるTTFTと完全に同じ定義ではありません。
再ロード時間はmodel sizeと単純比例しなかった
cold reloadのload_duration中央値です。
Gemma 3 4B 2.06 s (2.03 ~ 3.22)
Qwen 3 8B 1.48 s (1.45 ~ 2.98)
Gemma 3 12B 4.80 s (3.21 ~ 5.32)
8Bが4Bより速いので、model file sizeだけの順位になっていません。OS page cache、memory allocation、runnerの準備、model family差が混ざります。3回という小標本でも範囲が広く、reload速度をmodelの能力差として解釈してはいけません。
さらに、Qwen 3 8Bをdownload直後に初めて実行した1回だけはTTFC 17.54秒、API上のload 12.01秒でした。その後のreloadではTTFC中央値1.58秒です。初回固有の準備costを、毎回発生する待ち時間と混同しないため、正式表から分離しました。
実際にQwen 3 8Bをstream生成した
ベンチマークscriptだけでなく、同じOllama APIへ接続するローカル画面を作り、browserでstream出力を確認しました。外部APIには送っていません。

この実行では256 tokenを2.16秒、127.6 tok/sで生成しました。画面の文字は保存済みtextを貼ったものではなく、stream=trueで到着したresponse fragmentを順番にDOMへ追加したものです。
出力を人間が読むと問題も見える
速度だけなら成功ですが、回答品質を読むと少なくとも2つ注意点があります。
1つ目は、3モデルすべてが256 tokenで回答途中に切れたことです。promptでは700字以上を要求しましたが、num_predict=256という生成上限が優先されました。長い回答が必要なら上限を増やす必要があります。その代わり待ち時間とKV cache使用量も増えます。
2つ目は、もっともらしい説明にも検証が必要なことです。今回の4B出力には「平坦な領域は損失が小さい」と読める説明がありましたが、平坦さはgradientの小ささであって、損失値の低さを保証しません。8B出力の「大きい学習率だと局所最小値や鞍点に捕らわれやすい」という説明も、発散の中心理由としては不正確です。
1次元二次関数なら、overshootを式で確認できます。
L(w) = 1/2 × a × w²
gradient = a × w
w_(t+1) = w_t - ηa w_t
= (1 - ηa) w_t
収束には概ね|1 - ηa| < 1、つまり0 < ηa < 2が必要です。ηa > 2では絶対値が1を超え、符号を反転しながら原点から離れます。「stepが大きすぎて谷を飛び越え、振幅が増える」が核心です。
LLMの規模を選ぶときはtok/sだけでなく、別に正答率・引用・code testなどのtask評価が必要です。この記事の1 promptは品質benchmarkではありません。
自分のPCで再現する
実験scriptはPython標準libraryだけで動きます。
cd /mnt/c/Users/user/Documents/Codex/2026-08-24/ko
python3 work/ai_lab/experiment_ollama_model_sizes.py
主な処理です。
for model in ["gemma3:4b", "qwen3:8b", "gemma3:12b"]:
for repeat in range(1, 4):
unload(model) # keep_alive=0
run_streamed(model, "cold")
run_streamed(model, "warm")
結果はJSONへ保存します。
work/ai_lab/results/ollama_model_sizes.json
最低限確認するfieldです。
load_duration_s: model loadtime_to_first_content_s: stream先頭本文までeval_count: output token数eval_duration_s: token生成時間tokens_per_s: output速度gpu_peak_used_mib: request中の総GPU使用量peakresponse: 実際の出力全文
この結果から選ぶなら
4Bは高速な対話、promptの試行錯誤、IDE補助のように何度も短い応答を求める用途へ向きます。約4.8GiBのGPU使用量なので、ほかのGPU処理と併用する余地も大きいです。
8Bは今回127.8 tok/sで、速度とmodel規模の中間でした。ただしQwen 3はGemma 3と別familyです。4Bと12Bの直線補間として扱わず、実taskで選びます。
12Bは約9.7GiBで16GB内に収まり、全GPU offloadできました。84.2 tok/sも対話には十分です。ただし同じGemma 3の4Bより約2.13倍遅く、長contextではmemory余裕が減ります。
実務的には、まず4Bでworkflowを組み、品質不足が測定で確認できたtaskだけ12Bへ上げる方法が効率的です。「大きい方が安心」ではなく、latency、memory、task scoreの3軸で決めます。
今回わからないこと
- 4B・8B・12Bの正答率やhallucination率
- Q4_K_MとQ8・FP16の品質差
- 4Kより長いcontextでのKV cache増加
- prompt ingestion速度が長文でどう変わるか
- 複数user・並列request時のthroughput
- 27BをCPU offload混在で動かす実用性
同じmodelでQ4とQ8を比較すると、量子化による保存容量、VRAM、速度、出力一致の変化を測れます。contextを4K・8K・16Kへ増やす比較は、16GB GPUの実用上限を切り分ける材料になります。
まとめ
- RTX 5070 Ti 16GBでQ4_K_Mの4.3B・8.2B・12.2Bを100% GPU実行できた
- peak GPU usedは約4.8・6.4・9.7GiB
- warm生成速度中央値は179.5・127.8・84.2 tok/s
- model fileより実行時VRAMは約1.5~2.1GiB大きかった
- download直後の初回と、通常のreloadは分けて測るべき
- 256 token上限により全回答が途中で切れ、速度測定だけでは品質を判断できない
- 8Bだけ別familyなのでparameter数の因果比較ではない
「動くか」だけなら12Bまで余裕がありました。ただし選定には、同じtaskで品質差を数値化し、追加の待ち時間とmemoryに見合うかを判断する必要があります。
