ゲーム用のPCでローカルLLMはどこまで動く?Ollamaで試してみた

ゲーム用のPCでローカルLLMはどこまで動く?Ollamaで試してみた

ゲーム用PCでローカルLLMを動かしてみました。VRAMへの納まり方が速度を大きく左右するため、量子化してモデルサイズを抑えるのがコツです。
2026.07.04

はじめに

皆様こんにちは、あかいけです。
最近、これから来たるであろう「ローカルLLMの時代」(諸説あります)に備えて、そろそろ自分でもローカルLLMを動かせるようになっておきたいな…と思いました。

というわけで動かすためのマシンを調べ始めたのですが、ローカルLLMをまともに動かそうとすると強めのGPUが必要で、もろもろ一式揃えると余裕で100万円コース…。さすがにポンとは出せません。

※ 例としてNVIDIA DGX Sparkの場合、どこ経由で買うかでも変わりそうですが、少なく見積もっても80万円以上はしそうです
https://www.nvidia.com/ja-jp/products/workstations/dgx-spark/

そこでふと思い出したのが、ゲーム用のPCです。
そこそこのGPUを積んでいるので、もしかしたらローカルLLM動かせるのでは??
というわけで手持ちのゲーム用PCでローカルLLMを動かしてみることにしました。

本ブログでは、Ollamaで動かす手順からVSCode / Claude CodeからローカルLLMを使う方法、そしてハードウェアに合わせたモデル選びまでを一通りまとめました。

手持ちのPCでローカルLLMを試してみたい方の参考になれば幸いです。

環境について

今回検証した環境を載せておきます。
ローカルLLMは動かすモデルによって必要なスペックが大きく変わるので、記事を読む際の前提として頭の片隅に置いておいてもらえると助かります。

特にポイントになるのがGPUのVRAM(ビデオメモリ)容量で、筆者環境は16 GBです。
後半でも触れますが、このVRAM容量が「どのくらいのモデルを快適に動かせるか」を大きく左右します。

筆者の環境

  • OS:Windows 11 Pro
  • CPU:AMD Ryzen 5 5600X 6-Core Processor (3.70 GHz)
  • メモリ:DDR4 128 GB
    • CRUCIAL CP32G4DFRA32A PC4-25600 32GB × 4
  • GPU:AMD Radeon RX 7800 XT (16 GB)
  • ディスク:合計5.5TB

余談:AMDのGPU(Radeon)でも動くの?

筆者の環境のGPUはAMD Radeon RX 7800 XTですが、
「ローカルLLMといえばNVIDIA」というイメージが強く、AMDで大丈夫か少し不安でした。

結論から言うと、OllamaはAMD GPUをROCmというライブラリ経由で公式サポートしていました。
公式のGPU対応リストにも、Linux・Windowsの両方で7800 XTがしっかり名前で載っていました。

https://docs.ollama.com/gpu

というわけで一旦この情報を信じてやってみます。

Ollamaを使う

インストール

まずはOllama本体をインストールします。
Windows版は公式サイトからインストーラーをダウンロードできます。

https://ollama.com/download/windows

今回はPowerShellから、公式が用意しているインストールスクリプトを実行して入れてみます。

irm https://ollama.com/install.ps1 | iex

インストールが終わったら、--versionでバージョンを確認してみます。
バージョンが表示されれば、インストールはOKです。

ollama --version
ollama version is 0.31.1

モデルを入れる

Ollamaが入ったら、次は動かすモデルを選びます。
利用できるモデルは公式のライブラリから探せます。

https://ollama.com/search

今回は例としてornithというモデルを使ってみます。

https://ollama.com/library/ornith

(特に深い理由はないですが、以下ブログを見た感じ良さげだったので選びました)

https://dev.classmethod.jp/articles/ornith-1-0-dgx-spark-japanese-benchmark/

ollama runを実行すると、モデルが手元になければ自動でダウンロード(pull)したうえで、そのまま対話モードが立ち上がります。
まずは軽量な9b版を動かしてみます。

ollama run ornith:9b

Send a messageのプロンプトが出ればモデルが起動しています。

pulling manifest
pulling af63361d2ac3: 100% ▕████████████████████████████████████████▏ 5.6 GB
pulling 151be780af0c: 100% ▕████████████████████████████████████████▏  236 B
pulling b1bca6ec8117: 100% ▕████████████████████████████████████████▏ 1.1 KB
pulling d74f445d3c6b: 100% ▕████████████████████████████████████████▏   76 B
pulling df2252e2f5bd: 100% ▕████████████████████████████████████████▏  548 B
verifying sha256 digest
writing manifest
success
>>> Send a message (/? for help)

試しにチャットしてみます。

Q.アルダブラゾウガメの飼い方を教えて。
>>> アルダブラゾウガメの飼い方を教えて。
Thinking...
ユーザーはアルダブラゾウガメ(アフリカゾウガメ)の飼い方について質問しています。これは一般的なペッ
ト飼育に関する情報提供であり、特定のファイル操作やツール使用を必要とするものではありません。

ただし、私は agentic coding assistant として設計されています。この質問に対しては、直接的な回答を提
供するのが適切です。アルダブラゾウガメ(アフリカゾウガメ)の基本的な飼い方を説明します。
...done thinking.

# アフリカゾウガメ(アルダブラゾウガメ)の飼い方

## 基本情報
- **寿命**: 50〜80年(非常に長生き)
- **最大サイズ**: 成人で約1.2m、体重10kg以上
- **性格**: 穏やかだが、個体差あり

## 飼育環境の準備

### 必要なスペース
- 大人用として最小でも **3×4m** の広さが必要(子供用ならもう少し小さくても可)
- 外飼い(屋外)が最も一般的で推奨される方法

### ケージ/囲い方
- 金属製のフェンスまたはネットで作る
- ガラス窓を閉めると熱がこもって危険
- 風通しをよくする設計に

## 餌やり

### 主食
- **牧草**: タイムothy, アルファルファ(最も重要)
- **野菜**: カボチャ、ニンジン、セロリ(少量ずつ)
- **果物**: オレンジ、バナナ(たまに与える程度)

### 注意点
- 人工飼料は少量のみ
- 水はいつでも新鮮に保つ
- 葉っぱを食べるタイプなので、大量の牧草が必要

## 健康管理

### 基本的なケア
- 定期的な爪の切り
- 日焼け止め(UVケア)
- バラエティのある餌を与える
- 定期的に獣医に健康チェックしてもらう

### 病気サイン
- 食欲減退
- 目や口の異常
- 皮膚の問題

## 注意点
- **長生き**なので、将来の責任を考慮する
- 大人になるまでに数年かかる
- 子ガメの時から飼育するのが一般的
- 法律で飼育制限がある地域もある(確認が必要)

何か特定の点について詳しく知りたい場合は、さらに質問してください!

情報に若干怪しい点がありますが、ローカルで動いているとは思えないくらい、しっかりした回答が返ってきました。
日常的な会話は問題なくできそうです。

またOllamaをダウンロードするとデスクトップアプリも使えるので、以下のようにGUIでも使えます。

スクリーンショット 2026-07-04 020217

なおモデルが消費しているリソースについては、ollama psで確認できます。
PROCESSOR列を見ると100% GPUとなっており、モデルが丸ごとGPU(VRAM)に載っていることがわかります。
このあたりの見方は後半で詳しく触れます。

> ollama ps
NAME         ID              SIZE      PROCESSOR    CONTEXT    UNTIL
ornith:9b    a75697c14589    5.3 GB    100% GPU     4096       4 minutes from now

IDEから使う

VSCodeから使う(Windows上)

ターミナルで動かせるようになったので、次はいつも使っているVSCodeから呼び出せるようにしてみます。
Ollamaはローカルにサーバーを立ててくれるので、それに対応した拡張機能から接続する形になります。

ここではGitHub Copilot ChatとContinueの2つを試してみました。

GitHub Copilot Chat

まずはGitHub Copilot Chatです。
Ollama公式にもVSCode連携のドキュメントが用意されており、まずはこちらを試すのが良さそうです。

https://docs.ollama.com/integrations/vscode
https://marketplace.visualstudio.com/items?itemName=GitHub.copilot-chat

拡張機能を入れてGithubの認証を通します。

スクリーンショット 2026-07-04 021449
スクリーンショット 2026-07-04 021529

その後、ターミナルからollama launch vscode コマンドで使いたいOllamaのLLMを選択します。

スクリーンショット 2026-07-04 023023

ローカルのOllamaが認識されると、先ほど選択したornith:9bが候補として選べるようになります。
モデルを選んだら、あとは普段のCopilot Chatと同じように、ローカルモデル相手にチャットができます。

スクリーンショット (6)

Continue

もう一つ、ローカルLLMとの相性が良いらしいContinueも試してみます。
オープンソースのAIコード補助拡張で、Ollamaもサポートしています。

https://github.com/continuedev/continue

ただし最近Cursorに買収されたようで、Githubの記載を見た限りOSS版はv2.0.0が最終バージョンとなるように見えます。😭😭😭
というわけで今後も使い続けるかはわかりませんが、一旦本ブログでは使ってみます。

https://www.continue.dev/

まずは拡張機能をインストールして、

スクリーンショット 2026-07-04 023200

使うモデルの設定などconfig.yamlに記述します。
書き方は公式リファレンスにまとまっています。

https://docs.continue.dev/reference

スクリーンショット (7)

今回はシンプルにモデルの指定だけ設定してみます。
以下の設定で、ローカルのOllamaでornith:9bを指定しています。

config.yaml
name: Local Config
version: 1.0.0
schema: v1
models:
  - name: Ornith 9B
    provider: ollama
    model: ornith:9b

設定を保存すると、Continue側でもornith:9bが選べるようになります。

スクリーンショット 2026-07-04 024350

VSCodeから使う(WSL上)

Windows上ではうまくいったので、今度は普段の開発環境であるWSL上のUbuntuのVSCodeからも使えるようにしてみます。

まずはWSL上にもContinueの拡張機能を追加して、

スクリーンショット (8)

Windows側で作ったconfig.yamlを、WSL側のホームにコピーしてみます。

$ mkdir -p ~/.continue
cp /mnt/c/Users/kanik/.continue/config.yaml ~/.continue/config.yaml

ところが、Continueから接続しようとするとエラーが出てしまいました。
ローカルのOllamaに接続できないらしいです。

Unable to connect to local Ollama instance.
Ollama may not be installed or may not running.

スクリーンショット 2026-07-04 032159

OllamaはWindows側で動いているので、どうやらWSLからそこに繋がっていないようです。
試しにWSL内からcurlで叩いてみると、やはりOllamaに接続できませんでした。

$ curl http://localhost:11434
curl: (7) Failed to connect to localhost port 11434 after 0 ms: Could not connect to server

原因を探るため、WSLのネットワークモードを確認してみると、natモードになっていました。

$ wslinfo --networking-mode
nat

WSL2はデフォルトがnatモードのため、WSLとWindowsは別ネットワーク扱いになり、localhostではWindows側のOllamaに繋がりません。
解決方法はいろいろありますが、今回はシンプルにWSLとWindowsが同じネットワークを共有するmirroredモードに切り替えてみます。

この辺りのWSLのネットワークモードの詳細は公式ドキュメントをご参照ください。

https://learn.microsoft.com/ja-jp/windows/wsl/networking

というわけで、ユーザーフォルダの.wslconfignetworkingMode=mirroredを追記します。
※ networkingMode以外はデフォルトの設定値です

[wsl2]
memory=8GB
swap=0
processors=2
networkingMode=mirrored

設定を反映させるため、WSLを一度シャットダウンして立ち上げ直します。

wsl --shutdown
wsl

改めてcurlで確認してみると、応答が返ってきました。

$ curl http://localhost:11434
Ollama is running

またWSL上のContinueからも、Windows側のOllamaに接続できるようになりました。

スクリーンショット 2026-07-04 032722

Claude Codeから使う(WSL上のVSCode)

Continueもいいですが、せっかくなので普段使っているClaude Codeでローカルモデルが使いたいですよね??
実はOllama公式でClaude Codeもサポートしています、最高ですね!!

https://docs.ollama.com/integrations/claude-code

ローカルLLMを利用するにあたり、Claude Codeの接続先をローカルのOllamaに向ける必要がありますが、以下コマンドだとollamaの実行環境とClaude Codeが同じである必要があります。

ollama launch claude

今回の場合は「Claude CodeはWSL上」、「OllamaはWindows上」という構成なので、環境変数を使って、APIのベースURLを指定してあげる必要があります。

具体的には以下のようにANTHROPIC_BASE_URLにOllamaのアドレスを指定し、--modelで使いたいモデルを渡して起動します。
※ 認証はローカルなので、トークンは空でOKです

ANTHROPIC_AUTH_TOKEN=ollama ANTHROPIC_BASE_URL=http://localhost:11434 ANTHROPIC_API_KEY="" claude --model ornith:9b

上記コマンドを実行後、Claude Codeがローカルのornith:9bで起動しました。
モデルの選択肢でもornith:9bが選択できるようになっています。

スクリーンショット 2026-07-04 033817

ただ実際に使ってみると、プロンプトに対して思ったように動作せず、頓珍漢な応答を繰り返してきました。

スクリーンショット 2026-07-04 033859

原因を調べてみると、大きく2つの要因が絡んでいそうでした。
この辺りの話は以下のブログでも言及されています。

https://dev.classmethod.jp/articles/claude-code-ollama-local/

コンテキスト長の不足

Claude Codeはシステムプロンプトやツール定義として、非常に大量のテキストをモデルに渡します。
一方今回の構成だとOllamaのデフォルトのコンテキスト長は4096トークンです。
(先ほどのollama psでもCONTEXT4096になっていましたね)

https://docs.ollama.com/context-length

つまりClaude Codeからの入力がコンテキスト長を大幅に超えてしまい、あふれた分は黙って切り捨て、結果としてモデルが指示やツール定義を最後まで受け取れず、まともに動けなくなっていた、と考えられます。

なお、コンテキスト長はOLLAMA_CONTEXT_LENGTHなどで広げられますが、広げるとその分メモリ(KVキャッシュ)を消費します。

モデル自体の性能

Claude Codeはツール呼び出しを多用するエージェント的な使い方が前提なので、小さめのローカルモデルだと、そもそもこの複雑な手順を安定してこなすのが難しいということも考えられます。

ひとまずモデル性能の影響を見るために、より大きな35b(350億パラメータ)版でも試してみます。

ollama run ornith:35b
ANTHROPIC_AUTH_TOKEN=ollama ANTHROPIC_BASE_URL=http://localhost:11434 ANTHROPIC_API_KEY="" claude --model ornith:35b

ただ、この状態でも9bと同様に正確な回答は返ってきませんでした。

スクリーンショット 2026-07-04 042409

「effortがHighのせいかな?」と思いLowでも試してみましたが、結果は同じくうまくいきませんでした。

スクリーンショット 2026-07-04 042541

次にコンテキスト長をOllamaがサポートしている最大の256kにして、再度35bを試してみます。
設定はデスクトップアプリのほうで設定してみます。

スクリーンショット 2026-07-04 175931

> ollama ps
NAME          ID              SIZE     PROCESSOR          CONTEXT    UNTIL
ornith:35b    5a470e0f652c    25 GB    37%/63% CPU/GPU    262144     4 minutes from now

スクリーンショット 2026-07-04 180719

結果的に正常にレスポンスが来ました!!
ただしこの質問の回答に2m45sかかっているのでまともに使うのは難しそうです…。
(自認がClaude CodeなのはClaude Code自体のシステムプロンプトが影響しているかも?)

スクリーンショット 2026-07-04 181127

というわけで、一旦Claude Codeで使うのは厳しそうなので、しばらくはContinueを使うことにします。
(より性能の高いモデルなら変わるのかも)

ハードウェアの性能に合わせてできるだけ高性能&高速に動くモデルを選ぶ

明らかに9Bと35Bで速度が違う…

さて、ここまででornith:9bornith:35bを動かしてみました。
ですが、同じPCで動かしたにもかかわらず、体感速度がまるで違いました。

というわけで--verboseオプションを付けて起動して、生成速度を計測してみます。

ollama run ornith:9b --verbose

total duration:       5.9517138s
load duration:        205.6493ms
prompt eval count:    77 token(s)
prompt eval duration: 136.167ms
prompt eval rate:     565.48 tokens/s
eval count:           358 token(s)
eval duration:        5.600524s
eval rate:            63.92 tokens/s
ollama run ornith:35b --verbose

total duration:       47.048687s
load duration:        212.5973ms
prompt eval count:    77 token(s)
prompt eval duration: 1.436679s
prompt eval rate:     53.60 tokens/s
eval count:           1371 token(s)
eval duration:        45.394293s
eval rate:            30.20 tokens/s

表示される主な指標の意味は次の通りです。

  • total duration:リクエスト全体にかかった時間
  • load duration:モデルをメモリに読み込むのにかかった時間(2回目以降は常駐していればほぼゼロ)
  • prompt eval count / rate:入力プロンプトの処理トークン数と処理速度
  • eval count:生成された出力トークン数
  • eval rate:出力トークンの生成速度(tokens/s)。日常利用で一番重要な指標

https://docs.ollama.com/api/usage

このうちまず注目したいのが、生成速度を表すeval rateです。

  • ornith:9b63.92 tokens/s
  • ornith:35b30.20 tokens/s

9b35bのおよそ2倍の速度でトークンを生成できており、体感でもかなりサクサクでした。

一方でtotal duration(全体の所要時間)を見ると、9bが約6秒、35bが約47秒と8倍近い差に見えます。
ただこれは35bの方がたまたま生成トークン数が多かった(eval countが358 vs 1371)ためで、そのまま速度比較には使えません。
1トークンあたりの純粋な速さを比べるには、やはりeval rateで見るのが良さそうです。

さらに差が顕著だったのが、プロンプトを読み込む速度のprompt eval rateでした。
9bが565.48 tokens/sなのに対し、35bは53.60 tokens/sと、こちらは約10倍もの開きがあります。

ではなぜ35bだけこんなに遅くなったのか。
答えはollama psコマンドで見れるPROCESSOR列にあります。

> ollama ps
NAME         ID              SIZE      PROCESSOR          CONTEXT    UNTIL
ornith:9b    a75697c14589    5.3 GB    100% GPU           4096       4 minutes from now
> ollama ps
ornith:35b   5a470e0f652c    21 GB     27%/73% CPU/GPU    4096       4 minutes from now

PROCESSORはモデルがどこで動いているかを表しており、9b100% GPUなのに対し、35b27%/73% CPU/GPUとなっています。
つまり35bはVRAMに載りきらず一部がCPU側に分割され、その分が足を引っ張って速度が落ちた、と考えられます。

「じゃあ結局、自分のPCではどのくらいのモデルを選べばいいの?」というのが一番気になるところですよね。
というわけでここからは、ハードウェアの性能に合わせてモデルを選ぶための考え方をまとめていきます。

補足:ollama psのPROCESSOR表示の見方

先ほどのPROCESSOR列は、モデルのメモリがどこに載ったかを示しています。

  • 100% GPU:モデル全体がGPU(VRAM)に載っている
  • 100% CPU:モデル全体がシステムRAMに載っている
  • 48%/52% CPU/GPU:一部がGPU、一部がシステムRAMに分割されている

https://docs.ollama.com/faq#how-can-i-tell-if-my-model-was-loaded-onto-the-gpu

先ほどornith:9b(5.3 GB)が100% GPUornith:35b(21 GB)が27%/73% CPU/GPUと分かれていたのは、まさにこの違いだったわけですね。
35bは21 GBとVRAM 16 GBに収まりきらないため、あふれた分がシステムRAM側にオフロードされたというわけです。

前提条件:基本はVRAM上に乗るサイズのモデルを選ぶ

まず大前提として、モデルはできるだけGPUのVRAMに丸ごと載せるのが基本です。

なぜかというと、LLMのトークン生成(文章を1文字ずつ吐き出す処理)は、計算の速さよりもメモリ帯域幅がボトルネックになる「メモリバウンド」な処理だからです。
生成のたびにモデルの重みを繰り返しメモリから読み出す必要があり、この読み出し速度がそのまま生成速度に影響します。

https://developer.nvidia.com/blog/mastering-llm-techniques-inference-optimization/
https://huggingface.co/docs/transformers/llm_tutorial_optimization

またGPUのVRAMはシステムのRAMと比べてメモリ帯域が桁違いに広いため、VRAMに載っているモデルは高速に動きます。
逆にモデルがVRAMに収まらず一部がシステムRAM側にあふれると、そこがボトルネックになって一気に遅くなります。

必要なVRAMの見積もり方

必要なVRAMを求める明確な計算式は見当たりませんでしたが、Hugging Faceの公式ドキュメントをもとに、見積もる際に考慮すべき事項を3つまとめておきます。

ざっくり言うと「モデルの重み」+「KVキャッシュ」+「推論時のオーバーヘッド」で考えるのが良さそうです。

まず1つ目の重みは、パラメータ数と精度(1パラメータあたりのバイト数)で決まります。

  • FP32(32bit):約4 × パラメータ数[B] GB
  • FP16/BF16(16bit):約2 × パラメータ数[B] GB

Loading the weights of a model having X billion parameters requires roughly 2 * X GB of VRAM in bfloat16/float16 precision

https://huggingface.co/docs/transformers/llm_tutorial_optimization

例えば8BモデルをFP16で動かすと重みだけで約16 GB必要になり、これだけで16 GBのVRAMは埋まってしまいます…。

2つ目のKVキャッシュの分は、前述の通りコンテキスト長に比例して増え、同ドキュメントでも構成によっては重みの約半分に達する例が挙げられています。

Storing 8 billion float values in float16 precision requires around 15 GB of RAM which is circa half as much as the model weights themselves!

https://huggingface.co/docs/transformers/llm_tutorial_optimization

3つ目のオーバーヘッドは、推論時に重み以外で消費される分です。
EleutherAIでは、この上振れはおおむね20%の誤差とされているみたいです。

ただしこれはあくまで大まかな経験則で、EleutherAI自身もオーバーヘッドの内訳までは踏み込んでいません。そのため長いコンテキストでは、この20%よりも上のKVキャッシュの増加分のほうが支配的になる点には注意してください。

In addition to the memory needed to store the model weights, there is also a small amount of additional overhead during the actual forward pass. In our experience this overhead is ≤ 20%

https://huggingface.co/docs/accelerate/usage_guides/model_size_estimator
https://blog.eleuther.ai/transformer-math/


というわけで上記を考慮するととてもじゃないですが、私のPCのスペックではリッチなLLMは動かせなさそうです…。😭😭😭

そこで登場するのが、次に説明する量子化です。

量子化について

VRAMに載せられるモデルサイズには限りがあります。
そこで、モデルを圧縮してより小さく&より速く動かすための技術が「量子化」です。

ここでは2種類の量子化を紹介します。
モデルの重みそのものを圧縮するLLMの量子化と、推論中のメモリを節約するKVキャッシュの量子化です。

LLMの量子化

LLMにおける量子化とは、モデルの重みを高精度な浮動小数点(FP16/BF16=16bit)から、より低ビットの整数(4bit・5bit・8bitなど)に変換して、モデルサイズとメモリ使用量を削減する技術です。

Ollamaのモデル名についているQ4_K_Mのような表記は、この量子化を表しています。
これはGGUFという形式で使われる「K-quants」の命名規則で、意味は次の通りです。

  • Qのあとの数字:重み1つあたりの目標ビット数(Q4なら約4bit、Q8なら約8bit)
  • _K:k-quantsという量子化手法(256重みの「スーパーブロック」単位で圧縮する方式)
  • _S / _M / _L:同じビット数帯の中でのSmall / Medium / Largeの違い(大きいほど品質重視)
  • _0 / _1:k-quants以前のレガシー方式(Q8_0などは今もよく使われる)

https://github.com/ggml-org/llama.cpp/pull/1684
https://github.com/ggml-org/llama.cpp/blob/master/tools/quantize/README.md

当然ながら、ビット数を下げるほどサイズは小さくなりますが、そのぶん品質は少しずつ劣化します。
llama.cpp公式(PR #1684)にLLaMA 7Bでの実測比較があるので引用します。

Type Perplexity(低いほど良い) File Size
F16(非量子化) 5.9066 13.0 GB
Q2_K 6.7764 2.67 GB
Q3_K_M 6.1503 3.06 GB
Q4_K_S 6.0215 3.56 GB
Q4_K_M 5.9601 3.80 GB
Q5_K_M 5.9208 4.45 GB
Q6_K 5.9110 5.15 GB

https://github.com/ggml-org/llama.cpp/pull/1684

表を見ると、Q4_K_Mはサイズを13 GB → 3.8 GBと約1/3以下に圧縮しながら、パープレキシティの劣化はF16比でわずか+0.05程度に抑えられているのがわかります。
このバランスの良さからか、Ollamaでもタグを指定せずにpullするとQ4_K_M版になることが多く、実際に今回のornithもタグ無しのlatest(=9b)はQ4_K_M版でした。(詳細は後述の検証にて)

KVキャッシュの量子化

もう一つの量子化が「KVキャッシュ」の量子化です。

KVキャッシュとは、Transformerの推論で計算したKey/Valueをメモリに保持し、トークン生成のたびに再計算せず使い回すための仕組みです。
これにより生成は速くなるのですが、コンテキスト長が長くなるほどKVキャッシュのメモリ消費も増えていくという性質があります。

Ollama公式も、コンテキスト長を大きくすると必要メモリが増えると明記しています。

https://docs.ollama.com/context-length

このKVキャッシュも量子化してメモリを節約できます。
Ollamaでは環境変数OLLAMA_KV_CACHE_TYPEで指定します。

  • f16:デフォルト。高精度・高メモリ使用
  • q8_0:8bit量子化。f16の約1/2のメモリ使用、精度低下はわずか
  • q4_0:4bit量子化。f16の約1/4のメモリ使用、精度低下は小〜中程度

https://docs.ollama.com/faq#how-can-i-set-the-quantization-type-for-the-k/v-cache

ただし、このKVキャッシュ量子化が有効になるのはFlash Attentionが有効なときだけ、という点に注意が必要です。
Flash AttentionはAttention計算を効率化する仕組みであり、現在はバックエンドとデバイスが対応していれば自動でFlash Attentionを使うようになっているようです。

https://docs.ollama.com/faq#how-can-i-enable-flash-attention

長いコンテキストを扱いたいけどVRAMが厳しい、という場合はq8_0あたりが品質とのバランスが良い選択肢になりそうですね。

色々モデルを比べてみる

ここまでで、モデル選びに関わる要素(VRAM・量子化・KVキャッシュ)を一通り見てきました。
最後に、これらをふまえて筆者環境で色々な量子化レベルのモデルを動かし、実際にVRAMへどう載るかを検証してみます。

コンテキスト長は256K

KVキャッシュの影響がわかりやすいように、コンテキストを256Kまで広げた状態で計測しました。
前述の通りコンテキスト長を伸ばすとKVキャッシュのメモリ消費が増えるため、同じモデルでもVRAMに載りきるかどうかが変わってきます。
ファイルサイズだけでなく、KVキャッシュ込みでVRAMに収まるかが重要になりそうです。

KVキャッシュはq8_0に量子化

256Kという長いコンテキストだと、KVキャッシュをデフォルトのf16のまま扱うとメモリ消費がかなり大きくなってしまいます。
そこで今回は、前述のKVキャッシュ量子化を有効にして計測することにしました。

量子化レベルはq8_0を選びます。今回は環境変数で設定します。

setx OLLAMA_KV_CACHE_TYPE "q8_0"
setx OLLAMA_FLASH_ATTENTION "1"

なお、KVキャッシュ量子化(q8_0)はFlash Attentionが有効なときだけ効くため、OLLAMA_FLASH_ATTENTIONも併せて1にしています。
また環境変数はOllamaサーバー側の設定なので、設定後はOllamaを再起動してから計測しています。

検証結果

検証したモデルは次の通りです。
ollama psPROCESSOR列と実際に触ってみた所感を記録していきます。

https://ollama.com/library/ornith/tags

モデル 量子化 ファイルサイズ コンテキスト ollama ps(PROCESSOR) 所感
ornith:latest
ornith:9b
ornith:9b-q4_K_M
Q4_K_M 5.6 GB 256K 100% GPU 全部GPUに載って最速。かなりサクサク
ornith:9b-q8_0 Q8_0 9.5 GB 256K 100% GPU こちらも全部GPUに載る。q4より少し遅いが十分快適
ornith:9b-bf16 BF16 18 GB 256K 37%/63% CPU/GPU 激遅。今回の中では最遅で実用は厳しい…
ornith:35b
ornith:35b-q4_K_M
Q4_K_M 21 GB 256K 37%/63% CPU/GPU 一部GPUから溢れるが、意外と実用的な速度(約30 t/s)
ornith:35b-q8_0 Q8_0 37 GB 256K 62%/38% CPU/GPU CPUの比率が増えて速度低下
ornith:35b-bf16 BF16 69 GB 256K 79%/21% CPU/GPU ほぼCPUでかなり遅い、普段使いは厳しい…

[!NOTE]
ornith:latestornith:9bornith:9b-q4_K_Mはいずれも同じダイジェスト(a75697c14589)で、実体は同一のQ4_K_M版です。
同様にornith:35bornith:35b-q4_K_Mも同一(5a470e0f652c)のため、上記の表では重複を除いてまとめています。

各モデルのollama ps--verboseオプションの結果は以下の通りです。

検証結果一覧

ornith:9b-q4_K_M(5.6 GB)

NAME         ID              SIZE     PROCESSOR    CONTEXT    UNTIL
ornith:9b    a75697c14589    11 GB    100% GPU     262144     4 minutes from now
total duration:       3.1323146s
load duration:        208.3475ms
prompt eval count:    75 token(s)
prompt eval duration: 153.479ms
prompt eval rate:     488.67 tokens/s
eval count:           173 token(s)
eval duration:        2.756458s
eval rate:            62.76 tokens/s

ornith:9b-q8_0(9.5 GB)

NAME              ID              SIZE     PROCESSOR    CONTEXT    UNTIL
ornith:9b-q8_0    b1edce684170    14 GB    100% GPU     262144     4 minutes from now
total duration:       3.9848905s
load duration:        211.4153ms
prompt eval count:    75 token(s)
prompt eval duration: 112.603ms
prompt eval rate:     666.06 tokens/s
eval count:           190 token(s)
eval duration:        3.658139s
eval rate:            51.94 tokens/s

ornith:9b-bf16(18 GB)

NAME              ID              SIZE     PROCESSOR          CONTEXT    UNTIL
ornith:9b-bf16    0ed5c778f8a9    24 GB    37%/63% CPU/GPU    262144     4 minutes from now
total duration:       42.7021961s
load duration:        210.77ms
prompt eval count:    75 token(s)
prompt eval duration: 1.76954s
prompt eval rate:     42.38 tokens/s
eval count:           243 token(s)
eval duration:        40.719391s
eval rate:            5.97 tokens/s

ornith:35b-q4_K_M(21 GB)

NAME          ID              SIZE     PROCESSOR          CONTEXT    UNTIL
ornith:35b    5a470e0f652c    25 GB    37%/63% CPU/GPU    262144     4 minutes from now
total duration:       13.0198449s
load duration:        211.5483ms
prompt eval count:    75 token(s)
prompt eval duration: 2.055351s
prompt eval rate:     36.49 tokens/s
eval count:           326 token(s)
eval duration:        10.750258s
eval rate:            30.32 tokens/s

ornith:35b-q8_0(37 GB)

NAME               ID              SIZE     PROCESSOR          CONTEXT    UNTIL
ornith:35b-q8_0    44788b2fdab4    40 GB    62%/38% CPU/GPU    262144     4 minutes from now
total duration:       22.9267956s
load duration:        211.295ms
prompt eval count:    75 token(s)
prompt eval duration: 4.532222s
prompt eval rate:     16.55 tokens/s
eval count:           349 token(s)
eval duration:        18.179703s
eval rate:            19.20 tokens/s

ornith:35b-bf16(69 GB)

NAME               ID              SIZE     PROCESSOR          CONTEXT    UNTIL
ornith:35b-bf16    cfc852542826    73 GB    79%/21% CPU/GPU    262144     4 minutes from now
total duration:       38.7281788s
load duration:        210.656ms
prompt eval count:    75 token(s)
prompt eval duration: 10.298072s
prompt eval rate:     7.28 tokens/s
eval count:           333 token(s)
eval duration:        28.216238s
eval rate:            11.80 tokens/s

結果の考察

VRAMに載るかどうかが一番大事…

100% GPUで動いた9b系は、どちらも快適そのものでした。ですが、少しでもCPUにあふれると途端に遅くなります。
また同じ9bでも、VRAMに載りきらなかったbf16は5.97 t/sまで落ち込みました。

前半で「VRAMに載せるのが基本」と書きましたが、まさかここまで露骨に数字に出るとは、という感じです。

9b-bf16が35b系より遅いのは意外だった

パラメータ数が多いほど遅い、と単純に思っていたのですが、そうでもありませんでした。
具体的には9b-bf16(5.97 t/s)は、パラメータ数が4倍近い35b-q4_K_M(30.32 t/s)よりも大幅に遅かったです。

これは、LLMのトークン生成が「計算の速さ」より「メモリ帯域幅」で決まる、いわゆるメモリバウンドな処理だからかな?と思います。(前述の「VRAMに載せるのが基本」で触れた話ですね)

CPUにあふれた重みがbf16(非量子化・16bit)だと、q4_K_M(約4bit)などの量子化版に比べてトークンごとに読み出すデータ量が単純に4倍前後になり、その分だけメモリ帯域を食ってしまう、ということだと思います。

VRAM 16GBでは9bが良さそう

今回の環境では、9bのq4_K_M / q8_0が、256Kというかなり長いコンテキストでも100% GPUで快適に動いてくれました。
逆に35BクラスやBF16版は、16GBには収まりきらずCPUに逃げてしまい、速度はガクッと落ちました。

とはいえ、35b-q4_K_Mは一部CPUに逃げてもなお30 t/s程度は出ていて、体感ではまだ十分実用的な速さでした。
より賢い回答を期待したいなら、多少の速度低下には目をつぶって35b-q4_K_Mを選ぶのも全然アリかなと思います。

さいごに

以上、ゲーム用PCでローカルLLMを動かしてみた記録でした。

高価な専用マシンがなくても、手持ちのゲーム用PC(AMD / VRAM 16GB)とOllamaで、思った以上にあっさりローカルLLMを動かせました。
一方で、速度を左右する一番のポイントはVRAM容量で、載りきる範囲で量子化してサイズを抑えるのが基本、というのが今回の学びでした。

思った以上に手軽に試せるので、まずは手持ちのPCで気軽に試してみるのは全然アリだと思います。

とはいえ今回はまだ「動かしてみた」レベルなので、今後は実際のコーディングでも本格的に使ってみて、新しい発見や良さげな使い方が見つかれば、また記事にしようと思います。

この記事が、これからローカルLLMを触ってみたい方の参考になれば幸いです。

この記事をシェアする

関連記事