見出し画像

【Linux】OllamaでGemma4 MTPとsplit tensorのGPU並列処理を強引に有効にする話【RTX5060ti×二枚】


はじめに

筆者は、ローカルLLMを利用する主環境としてollama + Open WebUIを利用しています。

しかしollamaは、あまり新機能対応に積極的ではないため、最速の状態でLLMを動作させる事ができません。さらに、(必要な事なので悪い事ではありませんが)最近は資金調達に熱心で、ローカルで快適に動作させる事よりも有料クラウド利用の対応と他社とのビジネス連携に力をいれているようです。

たとえば、Gemma4 31Bを利用する場合、(筆者環境はマルチGPUなので)--split-mode tensorと、--model-draft等のMTPオプションをllama-serverコマンドで動作させると、100 token/sに迫る超高速生成が可能になります。しかし、通常のollamaでは20〜30 token/sにとどまります。

ollama 0.30以降は、エンジンとしてllama-serverコマンド(llama.cpp)をそのまま実行する仕様に変更され、最新バージョンのollama内のllama-serverモジュールは、MTPもsplit tensorも対応しています。

しかし、他の都合(誤動作やセキュリティの問題を防ぐ等)でオプションをllama-server環境変数で直接渡すことを禁止しているようです。

これらの対応はgithubにも要望として上がってますが、大変そうなので後回しになっているようです。

そこで、強引にオプションを変更して、今のollamaで無理矢理MTP+split tensorを使えるようにしようという記事です。

※ 強引な事をするので、もちろん自己責任です。筆者のように(ollamaクライアントを良く利用し)ollamaで動作させる必要がない限りあまり意味のない記事です。通常は素直にllama.cppを直接利用すれば良いので。

※ ollama 0.32.0を利用しています

何がメリットなのか?

先に結果・結論です。

筆者環境では、Gemma4のMTPを有効にすると2〜3倍高速化ます。RTX5060ti×2環境で、split tensorを有効にすると(split layerよりも)1.3〜1.5倍高速化します。

特にGemma4 31Bの場合、これらの効果で3〜4倍になります。

Gemma4 31Bの場合

※ gemma-4-31B-it-qat-UD-Q4_K_XL.gguf(コンテキストサイズは64k)

19.7 token/s → 84.7 token/sへパワーアップします。

デフォルトのollama(19.7 token/s
MTP + split tensorのollama(84.7 token/s

Qwen3.6 27Bの場合

※ huggingface.co/bytkim/Qwen3.6-27B-MTP-pi-reasoning-GGUF:Q4_K_M

Qwen3.6の場合は、デフォルトollamaでもMTPが利用可能なので、split tensor(並列処理の違い)のみの変化になります。

43.45 token/s → 61.86 token/sへパワーアップします。

デフォルトのollama(43.45 token/s
MTP + split tensorのollama(61.86 token/s

何がデメリットなのか?

もちろん、整合性のない強引な変更をするので、想定しない不具合は多いと思いますが、筆者が確認した大きな問題は、ollamaプロセスの正確なメモリ占有量を内部で取得できなくなる事です。

これは致命的で、複数のモデルを同時利用する場合や、自動でオフロード量を調整するような機能は全て全滅します。

Gemma4 31BのGPUメモリ利用量を1.1GBと報告する

しかし、筆者のようにゲーミングPCで動作させる場合は、複数のモデルを同時に利用する事はまずありません。また、リソースを手動で設定し、ゲーミングPCギリギリまで利用するため、筆者のような用途であれば大きな問題にはなりません。

※ トラブルが起きないよう、同時にモデルを読み込まないように環境変数で明示的に指定する方が良いと思います。

OLLAMA_MAX_LOADED_MODELS=1

linuxの場合は、systemd管理になるので、「/etc/systemd/system/ollama.service」を変更する事になります

※ 他にも筆者の変更がはいっています

そして、llama-serverのバイナリバージョンにもよりもますが、Gemma4 MTP+split tensorの組み合わせは時々落ちます。

LM Studioもollamaも積極的にGemma4 + MTP対応しない理由なのだと思います。

改造のやり方

もちろん、オープンソースなので、ソースを変更するという方法も可能ですが、ビルドが大変なので、より簡易的なラッパースクリプトを利用します。ソースを変更する事無く動作を変更できます。

ラッパースクリプト

※ ラッパースクリプトとは、実行ファイルや関数をラップして(包み込んで)外からコントロールする手法です。Windowsではスクリプトと実行バイナリは別物ですが、UNIX系OSでは区別がないので良く利用される手法です

ollamaで推論を実行すると、内部でollamaモジュールのひとつ

/usr/local/lib/ollama/llama-server

が、引数と共に呼ばれます。このコマンドの引数を改造・上書きするllama-serverのラッパースクリプトを作ります。

まずは、オリジナルの「llama-server」バイナリのファイル名を「llama-server.real」と変更し、「llama-server」というスクリプトを作ります

# オリジナルの実行バイナリの名前を変更
sudo mv /usr/local/lib/ollama/llama-server /usr/local/lib/ollama/llama-server.real

# gedit等何かしらのエディタでファイルを作る
sudo editor /usr/local/lib/ollama/llama-server

もっとも簡単な例は、「--split-mode tensor」をオプションの最後に必ずつけるというものです。設定関係なく強制的にすべてsplit tensorモードで実行されます。

#!/bin/sh

# ファイル名:/usr/local/lib/ollama/llama-server
# 設定
REAL=/usr/local/lib/ollama/llama-server.real

# 常に付けるオプション
set -- "$@" \
    --split-mode tensor

# 新しいオプションで実行
exec "$REAL" "$@"

コマンドとして実行属性をつけます。

sudo chmod +x /usr/local/lib/ollama/llama-server

しかし、全てに対して--split-mode tensorすると問題が起こります。なので、特定のモデルのみ引数を変更するというスクリプトに改良します。

特定モデル実行時だけに反応するように改良

その前に、モデルを準備します。

Gemma4のドラフトモデルは対になるものなので、Unslothのモデルがおすすめです。

本当はollama pullでダウンロードできれば簡単なのですが、エラーで失敗します。なので、個別にダウンロードしてollamaに取り込む必要があります。

  • ① gemma-4-31B-it-qat-UD-Q4_K_XL.gguf(本体)

  • ② mmproj-F16.gguf(視覚モデル)

  • ③ mtp-gemma-4-31B-it.gguf(ドラフトモデル)

まずは、ダウンロードしたモデル①②をollamaへ取り込みます。

# Modelfile generated by "ollama show"
# To build a new Modelfile based on this, replace FROM with:
#FROM gemma4:31b
FROM /home/usr01/Downloads/gemma-4-31B-it-qat-UD-Q4_K_XL.gguf
FROM /home/usr01/Downloads/mmproj-F16.gguf

TEMPLATE {{ .Prompt }}

RENDERER gemma4
PARSER gemma4

PARAMETER temperature 1
PARAMETER top_k 64
PARAMETER top_p 0.95

「gemma4-31b-qat.modelfile」という名前で保存し、ollama用のモデルを作ります。

ollama create gemma4-31b-qat -f gemma4-31b-qat.modelfile

取り込まれた先のファイル名を確認します。

ollama show --modelfile gemma4-31b-qat | less
blobs形式で取り込まれ保存されます。
※ 筆者は昔のまま利用しているので、今のollamaのファイルパスはデフォルトだと異なるはずです。

--model <モデルファイル>でllama-serverが実行されるため、特定のモデルが実行されたときのみ引数を変更するようにします。

下記スクリプトの「TM」に記載したモデルが実行された時のみ置換が発生します。

DMには、③ドラフトモデルのファイルパスを記載します。ただしollamaプロセスはollamaユーザーで実行されるため、ollamaユーザーがアクセスできる場所に保存する必要があります。例:

  • /home/ollama/custom_models/mtp-gemma-4-31B-it.gguf

  • /opt/models/mtp-gemma-4-31B-it.gguf

パーミッションも必要であれば変更しておきます。

# /home/ollama/custom_models以下をollamaユーザーかつollamaグループにする
chown -R ollama:ollama /home/ollama/custom_models

※ ollamaインストール先は、アップデート時に削除されるため避けた方が無難です

#!/bin/sh

# ファイル名
# /usr/local/lib/ollama/llama-server

# 設定
REAL=/usr/local/lib/ollama/llama-server.real

# 初期化
MODEL=""
PREV=""

# --model の値を取得
for arg in "$@"; do
    if [ "$PREV" = "--model" ]; then
        MODEL="$arg"
        break
    fi
    PREV="$arg"
done

# gemma4 31b speculative decoding を有効化
# TM:ターゲットモデル DM:ドラフトモデル
TM="/home/ollama/.ollama/models/blobs/sha256-6048da4ae9dfab560bbb0386176bee5a255d89fcd39a8dbf7c6ae817ee67876d"
DM="/home/ollama/custom_models/mtp-gemma-4-31B-it.gguf"
if [ "$MODEL" = "$TM" ]; then
    set -- "$@" \
	--split-mode tensor \
    --spec-type draft-mtp \
    --spec-draft-n-max 4 \
    --model-draft "$DM"
    TM=""
    DM=""
fi

# Qwen3.6 27b pi-tune split-tensor を有効化
# リーズニングも強制off
TM="/home/ollama/.ollama/models/blobs/sha256-dbc7ff308e07345024466de9f57a0a9f32e64e50f536059ebaf2c03463e92e72"
if [ "$MODEL" = "$TM" ]; then
    set -- "$@" \
	--split-mode tensor \
	--reasoning off 
    TM=""
    DM=""
fi

# Qwen3.6 27b pi-tune-reasoning split-tensor を有効化
TM="/home/ollama/.ollama/models/blobs/sha256-bfae98454dba6b372c63a8989c9cdc2ea10e0af38d20381d72c910bdb8ee2403"
if [ "$MODEL" = "$TM" ]; then
    set -- "$@" \
	--split-mode tensor
    TM=""
    DM=""
fi

# 新しいオプションで実行
exec "$REAL" "$@"

動作確認

Open WebUIでollama実行した時に、ラッパースクリプト経由でオプションが変更されているか確認します。

Qwen3.6 27Bを実行しているので、「--split-mode tensor --reasoning off」が追加されているはずです。

# llama-serverという名前のプロセス検索する
$ ps aux | grep llama-server
ollama    492214 23.8 16.7 37460672 10989888 ?   Dl   11:52   0:02 /usr/local/lib/ollama/llama-server.real --model /home/ollama/.ollama/models/blobs/sha256-dbc7ff308e07345024466de9f57a0a9f32e64e50f536059ebaf2c03463e92e72 --port 45723 --host 127.0.0.1 --no-webui --offline -c 131072 -np 1 --log-verbosity 4 --no-log-prefix --no-log-timestamps --no-jinja --chat-template chatml --mmproj /home/ollama/.ollama/models/blobs/sha256-eacf610d1ee4bd5ed0197a0777dd8f4fceb8eefa27009067c7d496cb68fbde45 --spec-type draft-mtp --spec-draft-n-max 4 --spec-draft-backend-sampling --cache-type-k f16 --cache-type-v f16 --flash-attn on -b 512 -ub 512 -ngl 256 --context-shift --keep 4 --split-mode tensor --reasoning off

まとめ

※ ただしアップデートすると、ラッパースクリプトが消えてしまうので注意が必要です

他にもこの手法を利用すると便利な事があります。

問答無用で「--reasoning off」ができるので、Hermes Agent等でollama APIを利用するとリーズニングが常に有効になってしまうという問題を解決できます。(これもディスカッションされていますが、対応は後回しにされています)

※ 他にもollamaクライアントでリーズニング制御ができない問題が多いので有用だと思います

もちろん、そもそもバグ無くすべて仕様に沿って動作・対応してくれれば、強引な手法は必要無くなります。

一時的な「改造」として、本家が根本対応してくれるまでの繋ぎです。

※ また、Windows版も似たやり方は可能ですが、Windowsの場合は、ラッパースクリプト(やラッパー・バイナリ)はウイルスとして偽装判定・悪用されることが多いので、あまり推奨されません

※ Gemma4 26BやQwen3.6 35BのMoEモデルでも試してみましたが、ollamaで利用しているllama-serverではあまり良い結果は得られませんでした。

以下、関連する記事の【PR】です


いいなと思ったら応援しよう!