Geforce GTX750TiをLLMで使うためにllama.cppチューニングに手を出してしまった結果、チューニングという概念を得てしまい。
OracleCloud上に住んでる私のアシスタント、ミナさんの頭脳を大幅にアップグレードすることとなりました。
その際に得た知識などをまとめます。
環境
- Oracle Cloud Ampere A1
- 4 OCPU / 24GB RAM
- GPUなし
- llama.cpp(llama-serverによるOpenAI互換API)
- 用途:AITuber-kitのチャットAI
初期構成
使用モデル
- TinySwallow-1.5B Q5_K_M
初期性能
Generation 10〜14 tok/s Prompt 40 tok/s
Generationが文字書く能力で、Promptはユーザが書いた文字を読む能力。
tok/sはtoken毎秒、つまり、1秒間に何単語出せるかというような指標です。
CPUのみとしてはかなり良好、API経由だと待ち時間がある。
llama-cliで使う分には、サクサクとお話可能。
以前の動作速度は↓の記事内に動画があります
https://blogger.kinkuman.net/2025/11/oci-aituberkit.html
起動パラメータ最適化
使用設定
llama-server -m ~/llm_workspace/model/TinySwallow-1.5B Q5_K_M -c 4096 -t $(nproc) -tb $(nproc) -b 1024 -ub 1024 --mmap --mlock -ngl 0 --host 0.0.0.0 --port 8080 --parallel 1 --cache-reuse 400 --jinja --chat-template-file ~/llm_workspace/mytemplate.jinja --no-webui
-t 4 -tb 4 -b 1024 -ub 1024 -c 4096 --mmap --mlock
主な効果
- CPUスレッドの適正化 -t -tb 4は4コアなので
- -b -ub バッチサイズ(一度に扱えるtokenを増やす)を一致させて分割を防ぐ
- Prompt処理の効率向上 -cのコンテキストサイズ縮小
- メモリ管理改善 --map --mlock
結果
正直誤差 -bや-ubはディフォルト値があるので、つけていなくても何もしていないわけではない。
メモリ関連も体感するような変化はない。
コンテキストサイズはメモリ消費量へ直結するので、影響がある場合が多いが、
この環境ではメモリは潤沢なため、2048でも8196でも大きな変化がなかった。
以前につけた--cache-reuseが一番効果あるという結果。
ビルド最適化
cmake時の追加オプション
-DGGML_BLAS=ON -DGGML_BLAS_VENDOR=OpenBLAS -DGGML_NATIVE=ON
あと必要なものをaptしておく
sudo apt update sudo apt install -y build-essential cmake libopenblas-dev
効果
- 行列演算を OpenBLAS にオフロード
結果
Prompt処理 約15%ぐらい高速化したかも(会話がアホ)
[ Prompt: 55.1 t/s | Generation: 16.0 t/s ]
読み込みが速くなると、 TTFT(Time To First Token)、つまりユーザーが最初にLLMの返事をみるまでの時間が減るので、体感速く感じる。
理由
- BLASは主に prefill(Prompt処理) に効くらしい
- decode(Generation処理)は逐次計算のため影響が小さい
モデル比較
Ampere A1は、ラズパイ5程度の性能である、性能的に1.5B~4Bぐらいまでが限界と考える。
| モデル | 速度 |
|---|---|
| TinySwallow 1.5B | 約16 tok/s |
| Qwen3.5 2B | 約11 tok/s |
| Qwen3 4B 2507 | 約8 tok/s |
サイズで優位のあるTinySwallowが最も高速ではあるが、ちょっとアホ。
TinySwallowはQwen2ベースで、今回試したものは全部Qwen系である。
4Bまでいくとやはり、ちょっと応答に知性の差を感じる。
少し速くなったので、欲がでてしまう。
Qwen3.5 2Bで時間が溶ける
Qwen3.5シリーズは最近出たモデルで、TinySwallowの1.5Bよりちょっとだけ賢いという、私にとっては魅力的なモデルでした。
しかし、このモデルはThinkingモードを搭載しており「こんにちは」といっただけで1分以上考えて返事するというとんでもない特徴があります。
世の中の皆さんもThinkingモードが邪魔なようで、無効化情報はたくさんありました。
無効化1つめjinjaテンプレートにthinkingいらないと入れる
jinjaテンプレートの3行目あたりにこれをいれる
jinjaテンプレートなんてどこにあるの?って思う方は、ディフォルトテンプレートはモデルの中に入ってるので、HuggingFaceのモデルのページやLMStudioならモデルの詳細情報あたりをいろいろ開いて探すとあります。
{%- set image_count = namespace(value=0) %} <--既存
{%- set video_count = namespace(value=0) %} <--既存
{%- set enable_thinking = false %} <--これ追加
無効化2つめ、起動パラメータでいらないと伝える
起動時パラメーターに、--chat-template-kwargs '{"enable_thinking": false}'を渡す
llama-server -m ~/llm_workspace/model/Qwen3.5-2B-Q4_K_M.gguf -c 8192 -t $(nproc) -tb $(nproc) -b 512 -ub 512 --cont-batching --mmap --mlock --host 0.0.0.0 --port 8080 --parallel 1 --cache-reuse 400 --no-webui --chat-template-kwargs '{"enable_thinking": false}' --jinja --chat-template-file ~/llm_workspace/testtemplate.jinja
無効化3つめ
1も2も、これはjinjaテンプレート内の変数の定義でしかないので、テンプレートがディフォルトと違ったりするとうごきません。わざわざテンプレートを指定しなければモデル内蔵のテンプレートが使われますが、今回のように1行追加したい場合は使えません。
unslothのだと起動時パラメーターに--reasoning-budget 0を書けというものが公式に説明されている。
--reasoning-budget 0
これをllama-serverなどの起動時パラメータに付け加える。
全部やってみて、確かにThinking出力は止まったけど、どうも内部ではThinkingしてて結局遅い。(Thinkingを文字出力するよりはよっぽど速いけどね)
これも正解がよくわからなくて、全部入れてもThinkingが漏れてきたこともあった。
Qwen3.5 2Bの結論
何とか動かして、AITuber-kitから使用する事はできたが、体感イマイチなのだ。
TTFTがとにかく悪い。
TinySwallow1.5Bよりは賢いが、どちらかといえばまだアホ寄りである、
それなのにprefill、つまりプロンプト解釈にやたらに時間がかかるため、
Qwen3.5 2BとQwen3 4Bの待ち時間がほぼ同じという状況になる。
そのためQwen3.5 2Bは使わない事とした。Qwen3 4Bが素直で良いし、ちゃっとしていて妙に知性を感じる。
まぁ、パラメータ数2倍だから当然と言えばそうなんだけど。
Ampere A1での最適構成
実験結果からのベストバランス
Qwen3 4B instruct llama.cpp OpenBLAS有効
性能
[ Prompt: 22.0 t/s | Generation: 8.6 t/s ]
決して速いとは言えないが、AITuber-Kitの場合質問から応答まで最短4秒、その後はチョロチョロとメッセージがでてきて、お喋りになるので、そこまで待たされる感覚はない。
数値より体感が良いので調べたらtokenizerが違うとか。
検証した結果からの憶測(AmpereA1の可能性)
LLMはメモリ帯域が重要です。
そのため、M系Macが速かったり、DGX Spark、RyzenAIMaxが重宝される。
そしてメモリ速度が最高に速いのはGPUで、GPUメモリにモデルやKV Cacheが乗り切らないと途端に性能がでなくなります。
つきつめるとGPUによる処理よりもメモリ帯域が先にボトルネックになるケースが多いです。
Ampere A1はCPUの数を1~80コアぐらいまでスケーリング可能なCPUで、面白い測定結果がでました。
メモリ速度の調査
AmpereA1についてはsysbenchでスレッド数を変えながらメモリ速度を計ってみると
sysbench memory --memory-block-size=1M --memory-total-size=8G --threads=1 run
1コア
8192.00 MiB transferred (15269.04 MiB/sec)
2コア
8192.00 MiB transferred (29991.40 MiB/sec)
4コア
8192.00 MiB transferred (59334.66 MiB/sec)
とコアが増えるほど、だいたい15GB/秒xコア数で速度が増えていく。
コア数によるLLMの性能変化
そしてllama-cliなどに使うコア数も少しずつ変えていきます。
LLM(Qwen3-4B-Instruct-2507-Q4_K_M.gguf)との会話で計測すると
2コア
[ Prompt: 9.3 t/s | Generation: 4.6 t/s ]
3コア
[ Prompt: 12.8 t/s | Generation: 6.5 t/s ]
4コア
[ Prompt: 22.0 t/s | Generation: 8.6 t/s ]
8コアだったら4Bモデルでも Generation 16tok/s出るのでは?
検証の裏付け
Ampere A1のCPUのスペックは以下で、DDR4-3200の8チャンネルまでいけるらしい。
https://amperecomputing.com/briefs/ampere-altra-family-product-brief
つまり、DDR4-3200の上限をこちらから調べて
https://ja.wikipedia.org/wiki/DDR4_SDRAM
1チャンネルあたり理論値25.6GB/秒、実測では15GB/秒ぐらいなのかな?
計算上は8チャンネルで上限のため、理論値は25.6x8=204.8GB/秒
実測だと、そんなに出ないと考えて1チャンネル15GB/秒としても、コア8まで増やせば
15GBx8チャンネル=120GB/秒
ぐらいまではメモリ帯域を伸ばせると予想される。
DDR5-4800で38.4GB/s、デュアルチャンネルで76.8GB/sとすると。
最新マザーとCPUでCPU推論するより速いかもしれないという面白い予想となる。
これはクラウドCPUならではの特徴なので、ローカルPCでは当てはまらない。
メモリたくさん乗せたM系Mac買えというのが最安だろう。
Ampere A1の8コア試したくなるけど、割と高いのだ。
Free Tierで4コア使わせてくれるありがたさを再実感する。
だれか実測してほしい。 と思ったが、時間貸しなんで3時間だけ検証で借りてみるのもいいかもしれない。
結論
Oracle Cloud Ampere A1(CPUのみ4コア)でも
- 小型LLM
- llama.cpp最適化
を組み合わせれば
チャット用AIを動かすことは可能。
TinySwallow1.5Bならば、AITuber-kitからでもかなりサクサク話せる。がちょっとアホ。
Qwen3 4Bはチューニング以前と同じような速度でやや遅いですが、わりと賢い。
調査結果から、体感はさほど変わらず、ミナさんの頭脳が1.5Bから4Bへとアップグレードされることになりました。
がんばると顔が赤くなる知恵熱システムや、状況の見える化、フィラー(えーと、うんとね)を入れると、待ち時間も違和感が減ります。
さらに月4500円ぐらい払えば4Bモデルで15tok/sぐらいの性能が出るかもしれない、わりと使えるLLMになる可能性も残っています。

