Ollama の高速化と VRAM 最適化設定 (ファインチューニング: 2)

2025年 1月現在、Ollama では試験的に利用が可能になっている高速化および VRAM 最適化の設定があります。近いうちにどちらも標準設定になりそうな雰囲気もありますが、執筆時の最新バージョン0.5.7ではユーザが設定してあげる必要があるので、その方法を共有します。

Apple Silicon Mac (M シリーズ CPU) でローカル LLM を使用している方は、前回の記事もご覧ください。Mac の GPU に自由にメモリを割り当てる方法を紹介しています。

とりあえず環境

Ollama に施す設定なので OS には依存しないはずですが、設定方法は macOS にしか触れていません。また、インストール方法も、ソースコードをビルドするとか、brew で入れるとか、Docker で実行するとかあるみたいですが、アプリ以外の設定方法でどうするのかは知りませんのでお調べください。ごめんなさい。

オフィシャルの情報参照元

Ollama FAQ:

Ollama に上記機能を導入した中心的メンテナーのブログ:

ファインチューニング (2) Flash Attention で VRAM 使用量を抑え計算速度も上げる

上に貼ったボクの前回のブログに書いた方法が (1) なので、こちらは (2) から始めます。

まずは、Ollama で Flash Attention を有効にします。Flash Attention は VRAM の使用量を抑え、LLM の計算速度も上げてくれます。いろいろなところで説明されていますが、この機能を有効にする事によるネガティブな影響は無いようです。3倍速くなったという検証結果もあるらしいですが、ま、そこまでとは言わないまでも、良い効果しか無いならやらない理由は無いですね。 Ollama でも将来的にデフォルトで有効になりそうですが、今のところは自分で有効にしてあげる必要があります。Mac ならターミナルで以下コマンドを実行してください:

launchctl setenv OLLAMA_FLASH_ATTENTION 1

無効にする (元に戻す) なら、上記の値を1から0にします。現在の設定を確認するには、getenvコマンドを実行します。以下、有効になっている場合の実行例で、1が返ってきています。

% launchctl getenv OLLAMA_FLASH_ATTENTION
1

ファインチューニング (3) K/V cache の量子化でコンテキスト長を抑える

K/V cache の量子化とは、コンテキストのキャッシュを量子化することで以降の計算効率を高め、必要なメモリも抑えるというような技術らしいです (K/V context cache 等と書かれていることもあります)。ファインチューニング (1) では LLM を載せるための VRAM を増やすことで大きなモデルやコンテキスト長を扱えるようにしましたが、K/V cache は、モデルの実行時に必要となるメモリの使用量を抑えることで、同じ様な事を実現します。また、モデル自体の量子化は 8bit であれば性能の低下は小さく速度を向上できるように、K/V cache の量子化もコンテキストキャッシュのサイズに対して同様の効果が望めます。K/V cache に 8bit の量子化を施した場合、必要なメモリの量は量子化しない場合の半分程になるため、使用できるコンテキスト長を倍に増やすことができます。

こちらの機能は現在 Ollama では Experimental (実験的導入) という表現がされており、エンベッドモデル (Embedding models)、ビジョン・マルチモーダルモデル、アテンションヘッドが高いタイプのモデルでは性能の低下が結果に影響する可能性がありうるとのことです。なので Ollama は Embed モデルを検知した際には自動的に無効化するらしいです。ということですので、本設定はモデルとの相性問題があり得ると理解し、試してみた上で性能が下がるようであれば無効にしておくのが良いでしょう。残念ながら今のところモデル毎に設定する方法はありません。

さて設定方法ですが、量子化の選択肢には、8bit (q8_0) と 4bit (q4_0) があるのでどちらかを選びます (デフォルトは量子化無しのf16)。4bit にした場合、メモリ削減効果は大きいですがその分性能も下がるため、これまで GPU だけでは動かせなかったモデルを使うというような場合以外は 8bit を選びましょう。また、前提として Flash Attention の有効化が必要ですので、上に書いたファインチューニング (2) を実行してから進めてください。Mac でのコマンドは以下となります (8bit の場合):

launchctl setenv OLLAMA_KV_CACHE_TYPE "q8_0"

デフォルトに戻す場合は"f16"、4bit にするなら"q4_0"を値に指定して実行します。現在の設定を確認する方法と実行例は以下となります:

% launchctl getenv OLLAMA_KV_CACHE_TYPE
q8_0

また、設定後に Ollama でモデルを実行してログを確認すると、量子化とキャッシュのサイズが確認できます。以下の例では、途中までデフォルトのf16となっており、変更後はq8_0になっていて、全体的にサイズが減っているのがわかります。

% grep OLLAMA_KV_CACHE_TYPE ~/.ollama/logs/server2.log|tail
llama_new_context_with_model: KV self size  = 1792.00 MiB, K (f16):  896.00 MiB, V (f16):  896.00 MiB
llama_new_context_with_model: KV self size  = 1536.00 MiB, K (f16):  768.00 MiB, V (f16):  768.00 MiB
llama_new_context_with_model: KV self size  =  512.00 MiB, K (f16):  256.00 MiB, V (f16):  256.00 MiB
llama_new_context_with_model: KV self size  = 1792.00 MiB, K (f16):  896.00 MiB, V (f16):  896.00 MiB
llama_new_context_with_model: KV self size  = 1792.00 MiB, K (f16):  896.00 MiB, V (f16):  896.00 MiB
llama_new_context_with_model: KV self size  =  952.00 MiB, K (q8_0):  476.00 MiB, V (q8_0):  476.00 MiB
llama_new_context_with_model: KV self size  =  952.00 MiB, K (q8_0):  476.00 MiB, V (q8_0):  476.00 MiB
llama_new_context_with_model: KV self size  =  680.00 MiB, K (q8_0):  340.00 MiB, V (q8_0):  340.00 MiB
llama_new_context_with_model: KV self size  =  816.00 MiB, K (q8_0):  408.00 MiB, V (q8_0):  408.00 MiB
llama_new_context_with_model: KV self size  = 1224.00 MiB, K (q8_0):  612.00 MiB, V (q8_0):  612.00 MiB

設定を永続的にする

上記 2つの設定方法では、Mac を再起動後に初期化されてしまいます。Mac にログインするたびに、またはスクリプトを実行したときにこれらのファインチューニングを行った状態で Ollama を起動するには、以前書いたブログ記事にある「Ollama を自動的に LAN に公開」の手法が良いと思います。

スクリプトの中身を以下の様に変更してください。それ以外は同じ手順でアプリの作成と起動項目への追加ができます。Ollama を実行するときは常にこのスクリプト (アプリ) を実行することで、設定が適用されます。

do shell script "launchctl setenv OLLAMA_HOST \"0.0.0.0\""
do shell script "launchctl setenv OLLAMA_FLASH_ATTENTION 1"
do shell script "launchctl setenv OLLAMA_KV_CACHE_TYPE \"q8_0\""
tell application "Ollama" to run

超便利!自分の VRAM で使えるモデルとコンテキストサイズを調べるツール

上でも紹介した Ollama のメンテナーの方のブログに、Interactive VRAM Estimator という便利ツールが貼られています。使いたいモデルのサイズ (Model Size)、使いたいコンテキスト長 (Context Size)、そしてモデルの量子化 (Quantization Level) を選ぶと、その下に KV cache のサイズとモデルのサイズが表示されます。例えば、QwQ:32B-Preview-Q4_K_M の場合、32BQ4_K_M を選びます。そして今回 Q8_0K/V cache を設定したのでそこの Total をにらみながら Context Size を選ぶと、そのモデルを実行するために必要な VRAM のサイズがおおよそわかります (Estimator = 見積機)。

16K tokens なら 21.5GB に収まる、とわかる

32K (= 32768) だとボクの Mac の VRAM 24GB を超えしまうので、もうちょっと攻めた数字を出すために右上の Advanced モードを有効にします。Q8_0 の Total を見ながら Context Size スライダをいじると、24K (24 * 1024=24576) で 23GB RAM に収まりそうだということがわかりました。

というわけで、Dify で作った生成 AI アプリの Size of context window に 24576 を入れてチャットしてみた時のollama psの結果が下のスクリーンショットです。見事に 100% GPU で処理されています。勝利ですね。

ちなみに Dify でいじるところは、作った AI アプリのモデルを選んだここです:

ファインチューニング前はたしか 4k とかでやってました

最後に雑記

前回と今回の記事で、LLM を実行する環境側のファインチューニング方法を紹介しました。ボクは 32GB のユニファイドメモリしかないのでうまくやりくりしないとローカル LLM を有効活用できない環境にあり、毎度苦労したり工夫したりしながらなんとかやっています。そんな中でいくつか効果的な方法が確認できたので、まとめた次第です。

実行速度に関する調査はしていませんので、そのあたりは実際にお試しください。少なくとも LLM が必要とするメモリや 100% VRAM に収める方法を理解・実践するだけで、最近のモデルは結構実用的な速度で楽しめることがわかると思います。

正直言って 16GB でローカル LLM をあれやこれやするのはきびしいと思います。逆に、128GB あるならこれらのファインチューニングで、ローカル LLM を並列で動かすこともできますね。

最近中国企業のモデルの性能の高さが大きく評価されていながらも、情報流出を懸念して利用禁止という話も出ています。ローカルで実行すればその心配も無いので好きに試せますよ。個人的には、出たばかりのおフランスのモデル mistral-small:24b の性能の高さとレスポンスの速さが気に入っています。中国産モデルのような、中国語や中国の漢字が出てこないのも (すごく) 良いですね。QwQ の Preview が取れた正式版はいつか出るのでしょうか。

Image by Stable Diffusion (Mochi Diffusion)

単純に、荷物をいっぱい積んだラマを描いてもらいました。最初は Mistral-Small 24B にイメージを伝えてプロンプトを作ってもらったんですが、全然ダメでした。どうやら色々余計なことを書くよりも、とにかく必要な要素だけ書いて、後は何度も出力させた方がそれっぽいものが生まれるという感じがしてきました。

Date:
2025年2月2日 1:55:30

Model:
realisticVision-v51VAE_original_768x512_cn

Size:
768 x 512

Include in Image:
A Llama with heavy load of luggage on it

Exclude from Image:

Seed:
2221886765

Steps:
20

Guidance Scale:
20.0

Scheduler:
DPM-Solver++

ML Compute Unit:
CPU & GPU

© Peddals.com