Local LLM の推論速度

Local LLM は使用するソフトによって動作速度が変わります。前回紹介したモデルがどれくらいの速度で動くのか、いろいろな環境で比較してみました。

Qwen3.5 122B-A10B : Ryzen 5700X DDR4 + RTX 5060Ti 16GB

  • モデル Qwen3.5 122B-A10B Q4_K_M、Qwen3.5 122B-A10B UD-Q4_K_M MTP
  • Ryzen 7 5700X DDR4-3200 96GB + GeForce RTX 5060Ti 16GB、Windows 11、CUDA

Qwen3.5 122B-A10B を Ryzen 7 5700X DDR4-3200 と GeForce RTX 5060Ti 16GB で走らせた場合の速度比較です。ctx size は以降すべて 8192 です。

ModelCPU + GPUソフトウエア設定速度 (大きい方が高速)
Qwen3.5 122B5700X + 5060TiOllama 0.24.0デフォルト3.28 tps
Qwen3.5 122B5700X + 5060TiOllama 0.30.8デフォルト13.34 tps
Qwen3.5 122B5700X + 5060TiLMStudio 0.4.16デフォルト5.69 tps
Qwen3.5 122B5700X + 5060TiLMStudio 0.4.16GPU=48, CPU=4214.01 tps
Qwen3.5 122B5700X + 5060Tillama.cpp b9631デフォルト13.97 tps

Ollama は v0.24 までは非常に遅くお勧めできなかったのですが、最近リリースされた 0.30 から llama.cpp ベースになったようで、速度が改善されています。

LMStudio はデフォルトだとあまり速くありません。環境に合わせて設定すればきちんと速度が出ます。GPU は「GPU Offload」の値、CPU は「Nubmer of layers for which to force MoE layers into CPU」の値です。

llama.cpp は最新版を使っておけば、デフォルトのままで速いので簡単です。

MTP だとさらに速くなりますが、CPU 併用の MoE だとそこまで大きな差が出ません。以下の例だと MTP で +13% ほど速くなっています。

ModelCPU + GPUソフトウエア設定速度 (大きい方が高速)
Qwen3.5 122B UD MTP5700X + 5060TiLMStudio 0.4.16デフォルト5.22 tps
Qwen3.5 122B UD MTP5700X + 5060TiLMStudio 0.4.16GPU=49, CPU=4514.34 tps
Qwen3.5 122B UD5700X + 5060TiLMStudio 0.4.16CPU=49, CPU=4512.50 tps
Qwen3.5 122B UD5700X + 5060TiLMStudio 0.4.16CPU=49, CPU=4412.66 tps

Qwen3.5 122B-A10B : Core i7-13700 DDR5 + RTX 4060Ti 16GB

  • Qwen3.5 122B-A10B Q4_K_M 、 Qwen3.5 122B-A10B UD-Q4_K_M MTP
  • Core i7-13700 DDR5-5600 96GB + GeForce RTX 4060Ti 16GB、Linux、CUDA

別のマシン (Linux) での比較です。やはり Ollama は 0.24 以前と 0.30 以後では別物です。それでも結果を見ると llama.cpp をそのまま使用した方が速度が速く効率が良さそうです。

ModelCPU + GPUソフトウエア設定速度 (大きい方が高速)
Qwen3.5 122B13700 + 4060TiOllama 0.24.0デフォルト5.18 tps
Qwen3.5 122B13700 + 4060TiOllama 0.30.9デフォルト13.71 tps
Qwen3.5 122B13700 + 4060Tillama.cpp b9672デフォルト18.94 tps
Qwen3.5 122B UD MTP13700 + 4060Tillama.cpp b9672–spec-type draft-mtp
–spec-draft-n-max 2
19.22 tps

Qwen3.6 27B : Ryzen 7 9700X DDR5 + Radeon R9700 32GB

  • モデル Qwen3.6 27B Q4_K_M 、 Qwen3.6 27B UD-Q4_K_M MTP
  • Ryzen 7 9700X DDR5-5600 128GB + Radeon AI PRO R9700 32GB、Windows 11、Vulkan

以下は更に別マシンでの比較です。Qwen3.6 27B は 122B-A10B よりもパラメータは少ないですが Dense なので 122B-A10B よりも演算負荷は高くなっています。

VRAM が 32GB あるためパラメータが全部 VRAM に全部乗っています。この場合調節とか不要なので簡単です。また MTP の効果も高く、生成は 40~60% くらい速くなっています。MTP の結果は結構ばらつきがあるので注意。

ModelCPU + GPUソフトウエア設定速度 (大きい方が高速)
Qwen3.6 27B9700X + R9700Ollama 0.24.0デフォルト2.40 tps
Qwen3.6 27B9700X + R9700Ollama 0.30.9デフォルト28.21 tps
Qwen3.6 27B9700X + R9700LMStudio 0.4.16デフォルト33.10 tps
Qwen3.6 27B UD MTP9700X + R9700LMStudio 0.4.16デフォルト52.73 tps
Qwen3.6 27B9700X + R9700llama.cpp b9670デフォルト33.32 tps
Qwen3.6 27B UD MTP9700X + R9700llama.cpp b9670–spec-type draft-mtp
–spec-draft-n-max 2
54.00 tps

Ollama 0.24 の速度が極端に遅いですが、GPU を認識できておらず CPU だけで動いていました。0.30 では GPU が使われるようになっています。

Gemma 4 31B : Ryzen 7 9700X DDR5 + Radeon R9700 32GB

  • モデル Gemma 4 31B QAT
  • Ryzen 7 9700X DDR5-5600 128GB + Radeon AI PRO R9700 32GB、Windows 11、Vulkan

Gemma 4 31b も 32GB あればそこそこ大きな ctx で VRAM に載ります。

ModelCPU + GPUソフトウエア設定速度 (大きい方が高速)
Gemma 4 31B QAT9700X + R9700LMStudio 0.4.16デフォルト29.69 tps
Gemma 4 31B QAT9700X + R9700llama.cpp b9670デフォルト30.13 tps

Qwen3.5 122B-A10B : EVO-X2 128GB Ryzen AI MAX+ 395

  • モデル Qwen3.5 122B-A10B Q4_K_M 、 Qwen3.5 122B-A10B UD-Q4_K_M MTP
  • EVO-X2 128GB Ryzen AI Max+ 395 + Radeon 8060S、Windows 11、Vulkan

比較的速いメモリが 128GB あるため大きなモデルも動きますが、専用 VRAM を使った GPU よりは低速です。VRAM には 96GB 割り当てています。mmap の無効化が必要です。

ModelCPU + GPUソフトウエア設定速度 (大きい方が高速)
Qwen3.5 122BRyzen AI MAX+395Ollama 0.24.0OLLAMA_NO_MMAP=18.73 tps
Qwen3.5 122BRyzen AI MAX+395Ollama 0.30.9OLLAMA_NO_MMAP=125.49 tps
Qwen3.5 122BRyzen AI MAX+395LMStudio 0.4.16Try mmap()=off28.78 tps
Qwen3.5 122B UD MTPRyzen AI MAX+395LMStudio 0.4.16Try mmap()=off32.45 tps
Qwen3.5 122BRyzen AI MAX+395llama.cpp b9670–no-mmap29.86 tps
Qwen3.5 122B UD MTPRyzen AI MAX+395llama.cpp b9670–no-mmap
–spec-type draft-mtp
–spec-draft-n-max 2
33.34 tps

Radeon AI PRO R9700 (RDNA4) と違ってこちらは Ollama 0.24 でも GPU (RDNA3.5) を認識していますが、なぜか VRAM 割り当てを間違えます。VRAM に余裕があるのに CPU に 33% 割り当てられてしまい速度が落ちています。0.30 ではこの問題も直っており、GPU 100% になりました。

エージェントで使う場合

エージェントで利用する場合は大きな Context Windows が必要なので 64K 以上に設定することになります。その分メモリが必要で、今回の結果よりも速度は遅くなります。またエージェントでは入力プロンプトも大きく Prefill でかなり時間がかかります。EVO-X2 は 122B など大きなモデルも動きますが Prefill 自体はあまり速くないので、ローカル LLM の場合できるだけ KV キャッシュを壊さないような使い方が必要になります。

Ollama は速度が遅く VRAM の容量割り振りなど問題があったのですが、先日リリースされた 0.30 で改善されているようです。ただローカルで動かす場合、他のソフトが使えるなら他のソフトを使った方が良さそうです。(Ollama Cloud はよく使っています)

関連ページ

普段よく使ってる Local LLM のオープンモデル

普段よく Local LLM としてローカルマシン上で使っているモデルは黄色いエリアのものです。

各グループ毎に上が上位モデルで下が下位モデルになっています。エージェント用でお勧めのものは青線より上です。

個人向けの一般 PC (RAM 64GB 以下&VRAM 16GB 以下) で快適に動くのは残念ながら青線よりも下の緑色のあたりになります。黄色のモデルを走らせる場合は、メモリや VRAM の大きい高性能な PC が必要です。

Arm CPU の INT8 TOPS 値も計測してみる

前回の x64 VNNI 命令の TOPS 計測に続いて ARM CPU の TOPS 値も求めてみました。vfpbench による実測です。

結果

SoCarchCore数命令INT8 tops
Snapdragon 8s Gen 4v8.2A X4 A720 A720 A7201+2+3+2I8MM4.200 TOPS
Tensor G5 (Pixel 10 Pro)v9.2A X4 A725 A5201+5+2I8MM3.173 TOPS
Snapragon 7+ Gen 3v8.2A X4 A720 A5201+4+3I8MM2.400 TOPS
Tensor G4 (Pixel 9a)V9.2A X4 A720 A5201+3+4I8MM2.202 TOPS
Snapdragon 6 Gen 1V8.2A A78 A554+4 DotProd0.789 TOPS

INT8 TOPS で最も演算能力が高かったのは Snapdragon 8s Gen4 で、CPU だけでも 4.2 TOPS 出ています。同じ 8 core でも Snapdragon 8s Gen4 はすべて big Core なので、その分演算能力が高くなっています。

前回の x64 CPU の結果と比べると以下のとおり。SIMD 幅が 128bt の Mobile Arm CPU でも INT8 演算能力は Desktop CPU と比べて遜色ないレベルに見えます。これは Arm CPU が VNNI のような内積命令だけでなく、Matrix の乗算命令 I8MM を持っているためです。

CPUArchCore数命令INT8 TOPS
Ryzen AI Max+ 395Zen516C 32TAVX512-VNNI20.482 TOPS
Ryzen 7 9700XZen58C 16TAVX512-VNNI10.699 TOPS
Core i7-13700RaptorCove16C 24TAVX-VNNI5.456 TOPS
Ryzen 7 7840HSZen48C 16TAVX512-VNNI4.713 TOPS
Snapdragon 8s Gen 4X4 A7208C 8TI8MM4.200 TOPS⭐️
Ryzen 7 5700XZen38C 16TAVX23.547 TOPS
Ryzen 9 3950XZen216C 32TAVX23.178 TOPS
Tensor G5 (Pixel 10 Pro)X4 A725 A5208C 8TI8MM3.173 TOPS⭐️
Snapdragon 7+ Gen 3X4 A720 A5208C 8TI8MM2.400 TOPS⭐️
Tensor G4 (Pixel 9a)X4 A720 A5208C 8TI8MM2.202 TOPS⭐️
Ryzen 7 4750GZen28C 16TAVX21.629 TOPS
Snapragon 6 Gen 1A78 A558C 8TDotProd0.789 TOPS⭐️
Intel N97Gracemont4C 4TAVX-VNNI0.366 TOPS

I8MM 命令

x64 の VNNI に相当する命令は Arm にも搭載されており DotProd (udot/sdot) です。DotProd は 32bit 単位で 4要素同士の内積を行います。128bit で 32 iops になります。

I8MM 命令 (smmla/ummla/usmmla) は 2×8と 8×2 のマトリクス乗算が可能で、それぞれ各 8bit 値が 2回ずつ利用されます。64bit 単位、8要素の内積を 4組実行します。128bit で 32個の積和演算が可能で、命令あたりの演算回数は 64 iops となります。レジスタへの再転送なしに DotProd と比較して 2倍の演算ができるわけです。

また結果を見ると Cortex-X4 の場合 DotProd/I8MM は同時に 4命令実行可能であることがわかります。以下は Google Tensor G5 (Pixel 10 Pro) の Cortex-X4 の結果からの抜粋です。

Cortex-X4                             TIME(s)   MFLOPS      MOPS     IOP   IPC
NEON smmla.4s  (int8 x16) n12     :    0.272   799709.3    12495.5  ( 64.0 3.3)
NEON ummla.4s  (int8 x16) n12     :    0.227   959218.0    14987.8  ( 64.0 4.0) ⭐️
NEON usmmla.4s (int8 x16) n12     :    0.225   966448.1    15100.8  ( 64.0 4.0) ⭐️
NEON sdot.4s   (int8 x16) n12     :    0.225   483251.9    15101.6  ( 32.0 4.0)
NEON udot.4s   (int8 x16) n12     :    0.225   483342.0    15104.4  ( 32.0 4.0)

よって CPU Core あたり最大 256 iops となり、これは AMD Ryzen Zen5 の AVX512-VNNI に匹敵します。

ただしこれだけ強力なのは Prime Core の X4 だけで、Mobile SoC の場合は大抵 1~2 core しか搭載されていません。Cortex-A725/A720 の場合は半分の同時 2命令、LITTEL Core (E-Core) の Cortex-A520 の場合は 2 Pipe が 2 CPU で共有されているため実質 1 命令です。

下の表は CPU Core 毎の INT8 演算能力の比較です。

CPU Core対応命令bit幅clockあたりCORE あたりの演算数
Cortex-X4I8NN128bitx4256 iops
Cortex-A725/A720I8NN128bitx2128 iops
Cortex-A520I8NN128bitx1 (実質)64 iops
Zen5AVX512-VNNI512bitx 2256 iops
Zen4AVX512-VNNI512bitx 1128 iops
RaptorLake (RaptorCove) P-CoreAVX-VNNI256bitx 2128 iops
AlderLake-N (Gracemont) E-CoreAVX-VNNI256bitx 0.532 iops

BF16 命令

TOPS とは直接関係ないのですが、AI 向けの演算命令として bfloat16 命令があります。bfloat16 は 16bit の浮動小数点フォーマットの一種で、一般的な fp16 の s10e5 ではなく s7e8 になります。仮数部の精度は 8bit しかありませんが、その代わり指数部のレンジも 8bit あり fp32 と同等です。

Arm CPU には I8MM 同様 bfloat16 にも 2×4 と 4×2 のマトリクス乗算命令 bfmmla があります。結果は fp32 です。fp16 には同等の命令がないので、16bit のピーク FLOPS 値は fp16 よりも bfloat16 の方が高くなっています。

単純に考えると bit 数が倍なので 8bit I8MM の半分のレートになるように見えますが、結果を見ると 8bit int の 1/4 となっています。以下は Tensor G5 の Cortex-X4 の結果の抜粋です。INT8 が 966 TOPS なのに対して BF16 はおよそ 1/4 の 230~250 FLOPS となっています。

Cortex-X4
Group 2:  Thread=1  Clock=3.782000 GHz  (mask:80)
  SingleThread HP   max:   181.306 GFLOPS     INT8  3/16
  SingleThread SP   max:    90.649 GFLOPS     INT8  3/32
  SingleThread DP   max:    45.310 GFLOPS     INT8  3/64
  SingleThread BF16 max:   253.620 GFLOPS     INT8  1/4
  SingleThread INT8 max:   966.281 GOPS       INT8
  MultiThread  HP   max:   138.243 GFLOPS
  MultiThread  SP   max:    67.191 GFLOPS
  MultiThread  DP   max:    45.303 GFLOPS
  MultiThread  BF16 max:   229.727 GFLOPS
  MultiThread  INT8 max:   966.448 GOPS

Cortex-X4 の bfmmla 命令は I8MM の smmla/ummla/usmmla とは異なり同時に 2命令しか実行できないことが原因です。以下は Cortex-X4 の bfmmla 命令の抜粋です。

Cortex-X4                             TIME(s)   MFLOPS      MOPS     FOP   IPC
NEON bfmmla.4s (bf16 x8) n12      :    0.429   253620.4     7925.6  ( 32.0 2.1) ⭐️
NEON bfdot.2s (bf16 x4) n12       :    0.451    60410.1     7551.3  (  8.0 2.0)
NEON bfdot.4s (bf16 x8) n12       :    0.368   148077.4     9254.8  ( 16.0 2.4)

ちなみに fp16 命令 (HP) は 181 GFLOPS と INT8 の 3/16 になっています。Cortex-X4 の浮動小数点積和命令は 3命令同時に実行できるため、4命令実行可能な I8MM と比べて (3/4) ✕ (16 iop / 64 iop) = 3/16 となります。

Cortex-A725/A720 の場合は INT8 も BF16 も同じ 2命令なので、BF16 はちょうど 1/2 となっています。また浮動小数点積和も 2命令で同じなので、fp16 (HP) もぴったり 1/4 です。

Cortex-A725
Group 1:  Thread=5  Clock=3.052000 GHz  (mask:7c)
  SingleThread HP   max:    97.521 GFLOPS
  SingleThread SP   max:    48.758 GFLOPS
  SingleThread DP   max:    24.377 GFLOPS
  SingleThread BF16 max:   194.937 GFLOPS
  SingleThread INT8 max:   390.017 GOPS
  MultiThread  HP   max:   487.591 GFLOPS     INT8  1/4
  MultiThread  SP   max:   243.788 GFLOPS     INT8  1/8
  MultiThread  DP   max:   121.888 GFLOPS     INT8  1/16
  MultiThread  BF16 max:   917.726 GFLOPS     INT8  1/2
  MultiThread  INT8 max:  1950.065 GOPS       INT8

Cortex-A520 の場合は bfmmla は一つの ALU を複数コアで共有しており、シングルスレッド時に 1命令、マルチスレッドでは 0.5 に半減します。実測値を見ると理論値よりも値が小さくなっていますが、おそらくレイテンシが大きいためだと思われます。

Cortex-A520                           TIME(s)   MFLOPS      MOPS     FOP   IPC
NEON bfmmla.4s (bf16 x8) n12      :    1.264    51177.2     1599.3  ( 32.0 0.7)
NEON bfdot.2s (bf16 x4) n12       :    0.929    17408.1     2176.0  (  8.0 1.0)
NEON bfdot.4s (bf16 x8) n12       :    0.927    34897.8     2181.1  ( 16.0 1.0)

Aarm A520 のマニュアルによると Exec Latency は 14~15 cycle となっており、また bfloat16 の演算は VMAC と VALU を両方占有する特殊な命令であることもわかります。

まとめ

Arm CPU も AI 向けの演算命令が強化されており、高い演算能力を持っていることがわかります。今後 SME/SME2 によってさらにマトリクス演算命令は強化されていくようです。Apple M4 以降や C1 ではすでにこれらの命令が搭載されているため、さらに高いスループットが得られるものと思われます。

計測データのリンク

関連ページ

vfpbench のカテゴリ一覧

VNNI 命令を使って AI Max+ 395 と他の CPU の INT8 TOPS 値を計測してみる

AI 向け演算能力である TOPS 値は GPU や NPU のスペックとして用いられますが CPU ではあまりデータが載っていません。vfpbench に int8 と bf16 命令の計測機能を追加したので、実際の CPU でもこれらの値を調べてみました。(TOPS 値が大きい方が高速)

CPUArchCore数命令INT8 TOPS
Ryzen AI Max+ 395Zen516C 32TAVX512-VNNI20.482 TOPS
Ryzen 7 9700XZen58C 16TAVX512-VNNI10.699 TOPS
Core i7-13700RaptorCove16C 24TAVX-VNNI5.456 TOPS
Ryzen 7 7840HSZen48C 16TAVX512-VNNI4.713 TOPS
Ryzen 7 5700XZen38C 16TAVX23.547 TOPS
Ryzen 9 3950XZen216C 32TAVX23.178 TOPS
Ryzen 7 4750GZen28C 16TAVX21.629 TOPS
Intel N97Gracemont4C 4TAVX-VNNI0.366 TOPS

Ryzen AI Max+ 395 (EVO-X2) は CPU だけで 20 TOPS となりました。かなり速く、同じ 16コアの 3950X と比べても 6.4 倍です。もちろんこれはメモリ速度やデータ転送を一切考慮しないピーク値となります。実際のアプリケーションでこの速度が出るわけではありませんので予めご了承ください。また計測は短時間で完了するのでブースト時の結果となります。

Zen5 で特に高い値が出ているのは AVX512-VNNI の vpdpb 命令を同時に 2命令実行できるためです。同じく VNNI 対応の Zen4 や Raptor Lake と比べてもクロックあたり 2倍です。

CPU Core対応命令bit幅clockあたりCORE あたりの演算数
Zen5AVX512-VNNI512bitx 2256 iop
Zen4AVX512-VNNI512bitx 1128 iop
RaptorLake (RaptorCove)AVX-VNNI256bitx 2128 iop
AlderLake-N (Gracemont)AVX-VNNI256bitx 0.532 iop

AlderLake-N (Gracemont) はいわゆる AlderLake / RapterLake (Inel Core 12000/13000) の E-Core です。N97 を使っていますが CPU の仕様はほぼ N100 と同じです。通常の AVX 命令は 128bit x2 もしくは 256bit x1 なのですが、VNNI 命令はさらに半分のレートとなっているようです。おそらく int8 VNNI 命令を実行できる Pipe が 128bit 1本しかないためと思われます。

VNNI 非対応の Zen2/Zen3 は代わりに AVX2 の vpmaddsbsw を使用しています。3950X は Core 数が 2倍なのに Zen3 の 5700X より速度が出ていません。どうやら Zen2 では vpmaddsbsw は同時に 1命令しか実行できないようです。Zen3 では 2命令走るので、ちょうど Core 数の差を補っている形になります。なお fp32 の fma は Zen2 でも 2命令実行できるため、fp32 の FLOPS 値では Core 数が多い 3950X が逆転します。

Ryzen AI Max+ 395 の公称値との比較

Ryzen AI Max+ 395 の公称値は CPU, GPU, NPU を全部合わせて 126 TOPS となっています。

NPU 単体は 50 TOPS ですが、GPU や CPU の値は上記 AMD の仕様ページでも特に記載されていませんでした。ですがスペック表をよく見ると、各グレードの Core 数の差から CPU の TOPS 値がわかります。

メーカーのページから AI Max+ のスペックを抜き出してまとめると以下の通りです。

CPUCPU コア数GPU CU数GPU ClockNPUOverall
AMD Ryzen AI Max+ 3951640 CU2.9 GHz50 TOPS126 TOPS
AMD Ryzen AI Max+ 3921240 CU2.9 GHz50 TOPS122 TOPS
AMD Ryzen AI Max+ 388840 CU2.9 GHz50 TOPS118 TOPS

AI Max+ 395 と AI Max+ 388 のコア数差が 8 で、OVERALL の TOPS 値の差もちょうど 8 です。AI Max+ 392 を含めても、それぞれ Core 数の差と TOPS 値の差が同一です。公式スペックでは CPU 1 core あたり 1 TOPS の見積もりになっていることがわかります。Ryzen AI Max+ 395 は 16 core あるため、126 TOPS 中 CPU が 16 TOPS です。

これは CPU が 4.0 GHz で動作している計算になります。今回の計測結果では 20.48 TOPS なので、公式のスペックよりもだいぶ高い値となっています。20.48 TOPS から逆算すると 5.0 GHz なので、公式よりも 1 GHz 高いクロックで vfpbench が走っていたことになります。

おそらく短時間のブーストだったことと、CPU 単体での計測が原因と思われます。公称値は NPU, GPU, CPU の全ユニットの合計なので、すべてのユニットが同時にフル稼働する場合は冷却&電力制限から公式の値の通り 4.0GHz に下がるのではないかと考えられます。

CPU が判明したので GPU の分もわかります。Ryzen AI Max+ の GPU (Radeon 8060S) 単体では以下のように 60 TOPS です。

CPUCPU最大TOPSGPU最大TOPSNPU最大TOPS合計
AMD Ryzen AI Max+ 39516 TOPS60 TOPS50 TOPS126 TOPS
AMD Ryzen AI Max+ 39212 TOPS60 TOPS50 TOPS122 TOPS
AMD Ryzen AI Max+ 3888 TOPS60 TOPS50 TOPS118 TOPS

計算からも求めてみます。AI Max+ 395 の GPU は RDNA 3.5 の Ryzen 8060S ですが、CU の基本仕様は RDNA 3 と同じです。CU あたり 64 sp x Dual Issue なので、単純に計算すると 40CU、 2.9GHz の Ryzen 8060S は fp32 で 29.7 TFLOPS になります

fp32 64(sp) x 2(dual) x 2(fma) x 40(cu) x 2.9GHz = 29696 GFLOPS

fp16 では少々制限がありますが内積の Dual Issue もしくは WMMA 利用時にこの 2倍です。int8 演算は fp32 FMA のような Dual Issue に対応しておらず、また Matrix 専用命令の WMMA でも以下のページによると演算レートは fp16 と変わらないようです。

データ形式CLockあたりのピーク演算能力 (RDNA3)
fp32256 fop / CU
fp16512 fop / CU
bf16512 fop / CU
int8512 iop / CU
int41024 iop / CU

よって int8 では 2.9GHz 時に

512(iop) x 40(cu) x 2.9GHz = 59.392 TOPS

となり、公称値から求めた 60 TOPS とほぼ同じ結果になりました。また int4 ではなく int8 の値が用いられていることもわかります。

fp32 と int8 演算

AI 用途向けに、CPU にも専用の演算命令が追加されるようになってきました。そのため従来の fp32, fp64 等の基本演算と比べて、AI 向け演算の方が急激に能力が上がってきていることが分かります。

世代fp32 (fma)fp32の性能比int8int8の性能比iop/fop
Zen564 fopx 2.0256 iopx 5.34.0
Zen432 fopx 1.0128 iopx 2.74.0
Zen332 fopx 1.096 iopx 2.03.0
Zen232 fopx 1.048 iopx 1.01.5

この傾向は他の CPU でも同じで、ARM では VNNI のような内積だけでなく i8mm といった Matrix の乗算命令も搭載されています。今後も Matrix 命令や fp8 演算対応など、この傾向はさらに強くなっていくものと思われます。

vfpbench では ARM の i8mm にも対応したので、ARM CPU の TOPS 値についても計測しています。こちらは次回以降にまとめてみたいと思います。

実際の計測データ

実際の計測データは以下のリンクから参照できます。

関連ページ

OpenClaw を複数台の PC を使って 122b の Local LLM だけで運用する

複数台の PC を使って OpenClaw を使用しています。OpenClaw は多くのトークンを消費しますので、クラウドの API を使わずに自分の PC だけで運用できないかいろいろ試しています。

現在は以下の図のように 120b クラスのモデルを使用しています。AI 用の特別なマシンではなく、(メモリ増設した) 汎用の PC です。

本来なら LLM 用の PC は 1台だけでも動作できるのですが、複数台に分けているのは理由があります。PC-3 は空いてる PC の VRAM を間借りすることが目的です。PC-2 を用意したのは Sub Agent をバックグラウンドで並列動作させられることと、Main セッションの KV キャッシュとの分離のためです。

もし使える PC 台数に余裕があるなら、だいぶ贅沢ですが Heartbeat 用 PC も分けることができます。

一般向け PC での生成速度

前回説明したように、普通の PC でもメモリさえあれば 100b 以上のモデルも動くようになってきました。生成速度は 10~20 token/s ほどなので、AI 専用のマシンやクラウドの API と比べると非常に低速です。

それでも Slack のようにストリーミング表示してくれるクライアントで使っていると、思ったよりもずっと早くレスポンスが返ってくることがわかります。生成速度が遅くても使えているのは KV キャッシュが再利用できているおかげです。

逆にキャッシュが効かないケースでは一度のやりとりでも 5~10分ほど待たされるので、これが非常に重要であることがわかります。

Sub Agent を別の PC に割り当てる

OpenClaw は大きなコンテキストサイズを必要としますが、コンテキストウィンドウ長を増やすとその分生成速度は落ちていきます。VRAM 16GB でバランスを取るとだいたい 64K くらいがちょうどよいかと思います。

OpenClaw はコンパクション後でもトークン数は 20K 以上あり、使っていると簡単に 50K を超えます。そのため Main セッションの場合は、コンテキストウィンドウはほぼ単一のスロットです。この状態で Sub Agent などの別のセッションが走ると KV キャッシュが上書きされてしまい、再び長い再生成 (Prefill) 待ちになってしまうことがあります。

そこで Sub Agent に使う LLM 用の PC を別に用意すれば、長いコンテキストでのキャッシュ領域の衝突を避けることができます。.openclaw/openclaw.json の設定だと以下のようになります。

{
  "agents": {
    "defaults": {
      "model": {
        "primary": "llamacpp-pc1/Qwen3.5-122B-A10B"                 Main モデル
      },
      "subagents": {
        "model": "llamacpp-pc2/NVIDIA-Nemotron-3-Super-120B-A12B",  Sub Agent 
        "maxConcurrent": 1
      },
      "maxConcurrent": 2,
      "timeoutSeconds": 1800,
      "llm": {
        "idleTimeoutSeconds": 1800
      },
      
    }
  },
  "models": {
    "providers": {
      "llamacpp-pc1": {
        "api": "openai-completions",
        "apiKey": "llama.cpp",
        "baseUrl": "http://192.168.0.101:8080/v1",     Main  LLM PC  URL
        "models": [
          {
            "contextWindow": 65536,
            "cost": { "cacheRead": 0, "cacheWrite": 0, "input": 0, "output": 0 },
            "id": "Qwen3.5-122B-A10B",
            "input": [ "text", "image" ],
            "maxTokens": 32768,
            "name": "Qwen3.5-122B-A10B",
            "reasoning": true
          }
        ]
      },
      "llamacpp-pc2": {
        "api": "openai-completions",
        "apiKey": "llama.cpp",
        "baseUrl": "http://192.168.0.102:8080/v1",     Sub Agent  LLM PC  URL
        "models": [
          {
            "contextWindow": 65536,
            "cost": { "cacheRead": 0, "cacheWrite": 0, "input": 0, "output": 0 },
            "id": "NVIDIA-Nemotron-3-Super-120B-A12B",
            "input": [ "text" ],
            "maxTokens": 32768,
            "name": "NVIDIA-Nemotron-3-Super-120B-A12B",
            "reasoning": true
          }
        ]
      }
    }
  },
  
}

また PC を分けたことで、Sub Agent を完全にバックグラウンドで並列に走らせられるようになります。

なお Heartbeat は Main と同じコンテキストを共有しますが、同じスロットが割り当てられるので実行するタスクによっては競合する可能性があります。もし Heartbeat に使う LLM 用 PC も別に用意する場合は以下のように設定します。

{
  "agents": {
    "defaults": {
      "model": {
        "primary": "llamacpp-pc1/Qwen3.5-122B-A10B"                 Main モデル
      },
      "subagents": {
        "model": "llamacpp-pc2/NVIDIA-Nemotron-3-Super-120B-A12B",  Sub Agent 
        "maxConcurrent": 1
      },
      "heartbeat": {
        "model": "llamacpp-pc4/Qwen3.5-122B-A10B"                   Heartbeat 
      },
      "maxConcurrent": 2,
      "timeoutSeconds": 1800,
      "llm": {
        "idleTimeoutSeconds": 1800
      },
      
    }
  },
  
}

注意点

OpenClaw 用に Mac 上で LMStudio を使う場合は GGUF の方をお勧めします。単純な生成速度なら MLX の方が速いのですが、MLX ではキャッシュが再利用されずに毎回 Prefill が走ってしまうようです。

LLM 用 PC 側での実行例

LLM 用 PC では llama.cpp を使っています。以下はその実行例です。

llama-server.exe --model Qwen3.5-122B-A10B-Q4_K_M-00001-of-00002.gguf --mmproj mmproj-Qwen3.5-122B-A10B-BF16.gguf --alias Qwen3.5-122B-A10B -t 8 --ctx-size 65536 --host 0.0.0.0 --port 8080 --temp 0.6 --min-p 0.0 --top-p 0.95 --top-k 20 -fa on
llama-server --model NVIDIA-Nemotron-3-Super-120B-A12B-Q4_K_M-00001-of-00003.gguf --alias NVIDIA-Nemotron-3-Super-120B-A12B -t 8 --ctx-size 65536 --temp 0.6 --min-p 0.0 --top-p 0.95 --host 0.0.0.0 --port 8080 -fa on

複数の Sub Agent を同時実行するには

subagents.maxConcurrent = 1 を指定していますが、複数の Sub Agent を実行することは可能です。ただし並列度は 1になるので、Agent の数だけ時間がかかることになります。

もし実行時間短縮のために並列に走らせたい場合は、Sub Agent 用に更に追加の PC を割り当てる必要があります。直接コマンドから spawn 起動する場合は個別にモデル指定ができますが、設定ファイルの openclaw.json には Agent 毎に一つの Sub Agent モデルしか記述しておくことができないようです。

複数台の PC を使った並列化を行いたい場合は、個別にコマンドから model 指定で spawn するか、もしくは別の Coding Agent を利用する方法があります。例えば OpenClaw から Codex CLI の呼び出しができるので、Codex 側の設定で別の PC の Local LLM を割り当てておけば以下の 3つで並列実行になります。

  • Main Session / Heartbeat
  • Sub Agent
  • Codex CLI

画像認識モデルの指定

クラウドの商用モデルと違い、Local LLM が使うオープンモデルは画像認識に対応していないことがあります。Qwen3.5 の場合は画像入力に対応しているので不要ですが、他のモデルを使うときは以下のように VLM モデルを指定することができます。ここでは更に別の PC を割り当てています。

{
  "agents": {
    "defaults": {
      "model": {
        "primary": "llamacpp-pc1/NVIDIA-Nemotron-3-Super-120B-A12B"  Main モデル
      },
      "imageModel": {
        "primary": "lmstudio-pc3/qwen/qwen3-vl-4b"                  画像認識 
      },
      "subagents": {
        "model": "llamacpp-pc2/NVIDIA-Nemotron-3-Super-120B-A12B",  Sub Agent 
        "maxConcurrent": 1
      },
      "maxConcurrent": 2,
      "timeoutSeconds": 1800,
      "llm": {
        "idleTimeoutSeconds": 1800
      },
      
    }
  },
  "models": {
    "providers": {

       pc1/pc2 省略

      "lmstudio-pc3": {
        "api": "openai-completions",
        "apiKey": "lmstudio",
        "baseUrl": "http://192.168.0.103:1234/v1",     画像認識  VLM PC  URL
        "models": [
          {
            "contextWindow": 16384,
            "cost": { "cacheRead": 0, "cacheWrite": 0, "input": 0, "output": 0 },
            "id": "qwen/qwen3-vl-4b",
            "input": [ "text", "image" ],
            "maxTokens": 16384,
            "name": "qwen/qwen3-vl-4b",
            "reasoning": true
          }
        ]
      },
    }
  },
  
}

テキスト埋め込みモデルの指定

OpenClaw で Local LLM を使う場合は、メモリ検索用の埋め込みモデルを指定する必要があります。

OpenClaw が走っている PC のスペックが高く、RAM もストレージも余裕がある場合は CPU が使えます。とはいえ 300m (0.3b) でも 1GB ほどメモリを消費しますので、スペックに余裕がない場合はこれまでと同じ様に他の PC を割り当てて使うことが可能です。

Ollama で Local CPU を使う場合の例

  1. Ollama をインストール
  2. モデルをダウンロード
    • ollama pull embeddinggemma:300m
  3. 以下の設定を追加
{
  "agents": {
      "memorySearch": {
        "provider": "openai",
        "model": "embeddinggemma:300m",             埋め込みモデル
        "fallback": "none",
        "remote": {
          "baseUrl": "http://127.0.0.1:11434/v1",   埋め込みモデル用 PC  URL
          "apiKey": "ollama"
        }
      },
      
    }
  },

}

他の PC で処理する場合の例

LMStudio を使って他の PC 上で走らせる場合の設定例。

{
  "agents": {
      "memorySearch": {
        "provider": "openai",
        "model": "text-embedding-qwen3_embedding_4b",    埋め込みモデル
        "fallback": "none",
        "remote": {
          "baseUrl": "http://192.168.2.103:11434/v1",    埋め込みモデル用 PC  URL
          "apiKey": "lmstudio"
        }
      },
      
    }
  },

}

上記以外に provider = “local” を使う方法もあります。以下のページにまとめています。

しばらく使用してみて

llama.cpp のキャッシュ再利用のおかげで思ったよりもレスポンスは早いです。Slack で簡単な応答なら、リアクションマークが付いたあと 10秒くらいでストリーミングが始まります。ストリーミング表示されないクライアントだと全部生成してからメッセージが届くため、体感速度はだいぶ下がると思います。

たまに Heartbeat ジョブが走って Prefill 待ちが入ることがありますが、それでも長くて 2分くらいです。Heartbeat 用 PC があればこの待ち時間がなくなります。

内容も普通にチャットしている分には全く違和感なく、簡単なプログラムの作成なども問題なくこなします。memory も増えて徐々に育てていくことができます。普通に使う分には十分です。700b などの、よりパラメータ数の多いモデルと比べると細かいところでは正確性(追従性)に差が出るようです。メモリ更新などは指示して明示的にやらせた方が良いです。バックアップはこまめに取りましょう。

応答の仕方はモデルによって結構変わります。用途に合わせてモデルや量子化、temperature 等のパラメータ調整をしていくと良いのかもしれません。Sub Agent も当初はタイトル通り Qwen3.5 122B-A10B を使っていたのですが、今は Nemotron 3 Super に置き換えてテストしています。

注意点

OpenClaw で Local LLM を使用する場合はリスクを伴います。必ず完全に隔離した仮想マシンで Sandbox を有効にしてください。また重要な情報は絶対に与えず、テストする場合でもネットワークアクセスを制限しておくことをお勧めします。

{
  "agents": {
    "defaults": {
      "sandbox": {
        "mode": "all"
      },
      
    }
  },
  
}

openclaw status コマンドを実行すると、制限無しに 300b 未満のモデルを使っている場合にセキュリティの警告が表示されます。今回の説明でも 120b のモデルを使っているためセキュリティ警告が出ています。考えられるリスクとして、AI が騙されて危険な指示に従ってしまう可能性があります。OpenClaw ではできるだけ性能が高いモデルの利用が推奨されていますので、Local LLM を使う場合はご注意ください。

関連ページ