RTX 3060 Ti、VRAM 8 GB で ollama を動かしています。最初はパラメータ数と量子化から必要な VRAM を見積もってモデルを選んでいました。それでは足りませんでした。
境目で 4 倍から 10 倍変わる
同じプロンプトを ctx 8k で流した実測です。
| モデル | tok/s | GPU 常駐 |
|---|---|---|
| gemma3:4b | 111 | 100% |
| qwen2.5:7b | 83 | 100% |
| granite3.3:8b | 73 | 100% |
| gemma3:12b | 18 | 74% |
| gpt-oss:20b | 11 | 50% |
| phi4 (14B) | 6.9 | 64% |
全部載る側は 73〜113 tok/s に収まり、1 層でもはみ出した側は 7〜18 tok/s へ落ちます。中間がありません。「少しはみ出したので少し遅い」にはならない。
gpt-oss:20b が phi4 14B より速いのは MoE だからです。トークンごとに使う重みが一部なので、CPU 側へ置かれた層に当たる確率がその分下がります。
どちら側になるかは KV キャッシュが決める
コンテキスト長だけ変えて測り直すと、順位が入れ替わります。
| モデル | ctx 8k | ctx 32k |
|---|---|---|
| gemma3:4b | 111 tok/s · 4.43 GB | 113 tok/s · 4.95 GB |
| qwen2.5:7b | 83 tok/s · 5.34 GB | 21 tok/s · 8.68 GB |
| granite3.3:8b | 73 tok/s · 7.18 GB | 7.8 tok/s · 13.89 GB |
granite3.3 は 8B ですが 32k で 13.9 GB まで膨らみ、半分が CPU へ落ちます。gemma3 は 4B で 0.5 GB しか増えません。
Gemma 3 は注意層の大半をスライディングウィンドウにして、全トークンを見る層を数層おきにしか置いていません。KV キャッシュはウィンドウ幅ぶんしか要らないので、コンテキストを 4 倍にしても伸びない。granite3.3 は全層がグローバルなので、長さに比例して伸びます。
重みの大きさだけを見ると外します。 32k を扱うなら、8B より 4B のほうが速くて確実です。
長い文脈に強いほうは、ツールを呼べない
Dify のようなエージェント基盤は、モデルが構造化された tool_calls を返すことを前提にします。同じ関数定義を投げて確かめました。
| モデル | 結果 |
|---|---|
| qwen2.5:7b | tool_calls を返す |
| granite3.3:8b | tool_calls を返す |
| gemma3:4b | ollama が拒否(does not support tools) |
| gemma3-tools:4b | ```tool_call のテキストを返すだけ |
| qwen2.5-coder:7b / 3b | 返さない |
名前に tools と付いた派生も、構造化された形では返しません。テキストを自分でパースすることになります。コード特化の派生も同じで、コードを書きながらツールも叩くエージェントは、coder では組めません。
つまり 32k を 113 tok/s で回せるモデルはツールを呼べず、ツールを呼べるモデルは 32k で崩れます。8 GB では両方は載りません。
結果として 4 本
| 用途 | モデル | ctx 16k での実測 |
|---|---|---|
| エージェント・ツール呼び出し | qwen2.5:7b | 83 tok/s · 6.30 GB |
| RAG の生成 | gemma3:4b | 113 tok/s · 4.60 GB |
| コード(長い文脈) | qwen2.5-coder:3b | 160 tok/s · 3.11 GB |
| コード(品質優先) | qwen2.5-coder:7b | 83 tok/s · 6.30 GB |
どれも 100% GPU 常駐です。1 本で足りることにはなりませんでした。
測るまでは 8B か 12B を 1 本置くつもりでいて、実際に置くと 18 tok/s の待ち時間になります。見積もりではなく、使うコンテキスト長で /api/ps の size_vram を読むのが早いです。