「EVO-X2 x Qwen3.8-Flash-Next番外編3 llama-benchとllama-cliでPP速度が違う理由は入力依存性?」 の続き。
前回の番外編3ではllama-benchにランダムトークンだけでなく実文書を入力できる機能を追加して、日本語文書とランダムトークンでPPが変わることを検証した。
その後、公式(upstream)llama.cppの最新情報を確認したら、第11回で検証したMoE tile選択方式が旧方式に戻っているのと、他にも気になる更新がいくつか入っていたので、またまたベースのllama.cppを入れ替えて、修正前の速度を測って、PLE16変換テーブル対応とQSA unionの高速化を入れて計測して、と第11回と同じ手順を繰り返した。
(この時の計測結果は今回の本題から外れるので末尾におまけとして載せておく)
前回のベース入れ替えから4日しか経っていなくて、今後これを毎回繰り返すのはどうかと思っているところだけど、それは後で考えることにして、次はどこから着手しようかと考えているうちに、番外編3で「自作高速化に特別に有利なベンチマークで測っているのではないか」という疑いを持ったことを思い出した。
次の高速化をするまえに、ここをクリアにしておきたい、というところから、また沼にハマった。
以降、Prompt Processing(入力を読み込む処理)をPP、Token Generation(出力生成)をTGと表記する。どちらも単位はtok/sで、高いほど速い。
結論
今回は、7種類の入力を使ってVulkan(QSA union OFF / ON)とROCmのPP速度を比較した。
-
入力文書が違うとPP速度はかなり変わる。
- Vulkanはコンテキスト64kで最速/最遅の差が約1.21倍、128kで約1.41倍
- ROCmは64kで約1.06倍、128kで約1.04倍とVulkanより差は小さい
- 「自作高速化に特別に有利な入力だけで測っているのではないか」という疑いは、とりあえず否定できた。
一方で、結果の傾向はかなり複雑だった。
- Vulkan(QSA union ON)では英語技術文書やC/C++コードが速かった
- Vulkan(QSA union OFF)ではC/C++コードが最速だった
- ROCmではランダム入力が最速で、Vulkanとはかなり違う順位になった
- 64kと128kでも順位や改善率が入れ替わった
つまり、今回の範囲では「こういう文書はいつも読み込みが速い」と単純には言えない。ただし、入力文書の違いがPP速度に影響すること自体は分かった。
ソース、Windowsビルド、検証スクリプトなどはここで公開している。
https://github.com/ariera-j/llama.cpp-evox2-windows
今回の作業は、r5/upstream-refresh-20261009 から分岐した専用ブランチで行っている。
検証環境
速度に関係するところだけ先に。
| 項目 | 内容 |
|---|---|
| PC | GMKtec NucBox EVO-X2 |
| APU | AMD Ryzen AI MAX+ 395 / Radeon 8060S |
| RAM | 128GB UMA |
| UMA Frame Buffer | 96GB |
| OS | Windows 11 Pro 26H2(ビルド26300.9550) |
| メインモデル | Unsloth Qwen3.8-Flash-Next UD-IQ3_XXS |
| モデル配置 | 主な比較ではPLE16変換版。過去のMoE tile比較はオリジナル版 |
| KV cache | f16 |
| batch / ubatch | 2048 / 1024 |
| MTP | OFF |
| Vulkan compiler | LLVM / Clang 20.1.8 |
| ROCm | 10.0.0 / TheRock |
| ROCm compiler | AMD Clang 23.0.0 |
| GPU target | gfx1151 |
| 主な入力長 | 64k:61,789 / 128k:126,253 tokens |
最初にテストデータを準備する
以前に第5回や番外編1で、日本語出力結果の比較をしていて、文章の評価基準の作り方はとても難しい、それに比べたら速度計測は客観的な数字が出るから評価が楽だと思った。
でも実際はそんなことはなかった。入力内容によって速度が違うということは分かったけど、じゃあどんな入力でテストしたらよいのかと考えると意外と難しい。
今回は、一般論は置いといて、私が実際にローカルLLMに入力して作業してもらいたいと思う文書の種類として
- 日本語技術文書
- 英語技術文書
- C/C++ソースコード
の3種類、それから文書の種類による差が気になるので
- 日本語文学
- 英語文学
の2種類を追加して、それに今まで使っていた日本語論文の繰り返し文書と、llama-bench本来のランダムトークン入力の7種類を比較することにした。
最初は公開ベンチマークからデータを借りて来ようかと思ったのだけど、私の今のローカルLLMの用途だと、外に出せない文書を読み込んで要約してもらうか質問に答えてもらうというのがメインで、難しい推論はそんなに必要としてない。
なので、シンプルに文書を丸ごと読み込んでもらうだけにした。今回のテストデータは、いつも使っている日本語論文以外は指示文も追加していない。
文書は「一般公開されていて誰でもアクセスできる」「1文書で64トークン以上」という条件で、以下のものを選んだ。
| 分類 | 使ったデータ | 作り方・概要 | 全ファイルtoken数 |
|---|---|---|---|
| 日本語・技術 | 機械学習入門 | githubリポジトリからmd形式の本文を自作スクリプトで統合 | 65,007 |
| 英語・技術 | Dive into Deep Learning v1.0.3 | githubリポジトリからmd形式の本文を自作スクリプトで統合 | 520,411 |
| C/C++ソースコード | ggml-org/llama.cpp | 推論関連のソースを自作スクリプトで抽出・統合 | 1,864,775 |
| 日本語・文学 | 夏目漱石『吾輩は猫である』 | 青空文庫版テキストをUTF-8変換 | 251,252 |
| 英語・文学 | モンテ・クリスト伯 | Project Gutenbergからテキストダウンロード | 668,434 |
| 日本語・繰り返し | テキストを対象とした評価情報の分析に関する研究動向 | これまで速度計測に使ってきた繰り返し文書 | 255,169 |
| ランダム | llama-bench標準のランダムtoken入力 | - | — |
Vulkan版で計測
データができたので、さっそく速度計測してみた。今回は出力内容は見ないので、warmupや繰り返しを簡単にできるようにllama-benchのみを使った。
まずはVulkan版で、第11回で入れたQSA union高速化ON/OFFを比較してみた。
第11回で入れたMoE tile選択旧方式については、今回入れ替えたupstreamでは既に対応済みだったので、今回は追加移植も手動設定もしていない。
64kでは、実文書6種類はいずれも元ファイルの先頭から61,789トークンを読み込ませている。ランダムはllama-bench標準の生成トークンを使用する。
64k:7種類 × Vulkan QSA union OFF/ON
以下の数値に付けた (1)、(2)…は、各表の各数値列の中で大きい順の順位。たとえば 272.362 (7) は、その列で7種類中7位を意味する。
ON改善率やunion平均も同様に大きい値から1位を付けているので、**union平均の1位は「KVが最も多い」**という意味であり、「最も高速」という意味ではない。
| 入力 | OFF tok/s | ON tok/s | ON改善率 |
|---|---|---|---|
| 日本語・技術 | 299.235 (5) | 366.032 (4) | +22.32% (2) |
| 英語・技術 | 312.423 (2) | 378.992 (1) | +21.31% (3) |
| C/C++コード | 329.275 (1) | 377.754 (2) | +14.72% (6) |
| 日本語・文学 | 285.479 (6) | 344.105 (5) | +20.54% (5) |
| 英語・文学 | 304.394 (4) | 368.631 (3) | +21.10% (4) |
| 日本語・繰り返し | 272.362 (7) | 342.858 (6) | +25.88% (1) |
| ランダム | 308.390 (3) | 324.074 (7) | +5.09% (7) |
いつも使っている日本語論文繰り返し文書は、QSA union ON/OFFの改善率が一番高かったけど、日本語技術文書、英語技術文書も比較的高いので、繰り返しのせいかどうかは分からない。
速度の順位を見ると、
- QSA union OFFだけで比べると、一番速いのはC/C++コード、一番遅いのは日本語論文繰り返し
- QSA union ONだけで比べると、一番速いのは英語技術文書、一番遅いのはランダム
QSA union ON/OFFの改善率と、QSA union ON時の速度順位と、QSA union OFF時の速度順位が全部同じにはなっていない。
64kでは最速/最遅の差は、
- QSA union OFF:329.275 / 272.362 ≒ 1.21倍
- QSA union ON:378.992 / 324.074 ≒ 1.17倍
で、QSA union ONの方が入力間の差は少し縮まる。
64k:QSA union統計診断も取ってみた
QSA unionの統計診断機能をONにして、unique unionとpadded unionの平均も取ってみた。これは速度比較用ではなく、内部挙動を見るための診断値。
QSA unionの説明と、統計診断機能の実装については番外編3に書いたので、ここでは説明を省略する。
| 入力 | Unique union平均 | Padded union平均 |
|---|---|---|
| 日本語・技術 | 14,471.06 (5) | 14,596.95 (5) |
| 英語・技術 | 13,396.22 (6) | 13,524.24 (6) |
| C/C++コード | 11,836.90 (7) | 11,964.69 (7) |
| 日本語・文学 | 19,225.61 (2) | 19,352.74 (2) |
| 英語・文学 | 15,424.84 (4) | 15,552.09 (4) |
| 日本語・繰り返し | 17,406.27 (3) | 17,532.78 (3) |
| ランダム | 24,562.67 (1) | 24,688.34 (1) |
64kのunique union平均(横軸)とQSA union ONでの速度改善率(縦軸)

グラフ中の略称は、JA Tech=日本語技術、EN Tech=英語技術、JA Lit=日本語文学、EN Lit=英語文学、JA Repeat=日本語繰り返し、C/C++=C/C++ソースコード、Random=ランダム
Unique union平均とQSA union ONによる速度改善率は相関関係があるのかと思ったら、そうでもない。ランダムだけが極端な外れ値のようにも見える。
- C/C++コード:unique union最小だが、改善率は**+14.72%**で6位
- 日本語・繰り返し:unique unionはそれより大きいが、改善率は**+25.88%**で1位
- ランダム:unique union最大で、改善率は**+5.09%**で最下位
128kでも測ってみた
次に128kでも測ってみた。日本語技術文書だけは、元の文書が短くて128kに足りなかったのでテストから外した。実文書は先頭126,253トークンを使用しているため、64kとの比較にはKV長の変化だけでなく、追加された入力内容の違いも含まれる。
| 入力 | 128k OFF tok/s | 128k ON tok/s | ON改善率 |
|---|---|---|---|
| 日本語・技術 | —(対象外) | — | — |
| 英語・技術 | 214.921 (2) | 343.589 (2) | +59.87% (4) |
| C/C++コード | 236.129 (1) | 346.600 (1) | +46.78% (6) |
| 日本語・文学 | 168.064 (6) | 294.020 (5) | +74.95% (1) |
| 英語・文学 | 204.938 (3) | 335.141 (3) | +63.53% (3) |
| 日本語・繰り返し | 183.660 (4) | 310.682 (4) | +69.16% (2) |
| ランダム | 170.615 (5) | 261.673 (6) | +53.37% (5) |
64kでは改善率が+5~26%だったのに対して、128kでは**+47~75%**と一気に大きくなった。
128kの最速/最遅の差は、
- QSA union OFF:236.129 / 168.064 ≒ 1.41倍
- QSA union ON:346.600 / 261.673 ≒ 1.32倍
で、64kよりかなり大きい。
特にQSA union OFFでは、C/C++最速のコードと最遅の日本語文学の差が**約40.5%**もある。
128k:union統計は特徴的な3種類だけ取った
128kの統計データは、特徴の違いが分かりやすい3種類だけ取ってみた。
| 入力 | 128k Unique union加重平均 |
|---|---|
| 日本語・技術 | —(未測定) |
| 英語・技術 | —(未測定) |
| C/C++コード | 14,155.45 (3) |
| 日本語・文学 | 22,798.57 (2) |
| 英語・文学 | —(未測定) |
| 日本語・繰り返し | —(未測定) |
| ランダム | 29,598.36 (1) |
128k、16k幅のKV区間別unique union加重平均 横軸は各KV区間の中点

128kでも、順序はコード < 文学 < ランダムのままだった。
今回の128kの診断データをKV区間別に見ると、コードのunique union平均は32–48k区間の12,487から48–64k区間で10,941まで減少した。128kまで減り続けるのかと思ったけれど、実際にはその後また増えていた。つまり、「コードは後半に行くほどどんどん小さくなる」みたいな単純な話でもなかった。
64k/128kをまとめて眺めると
64k, 128kで、ON改善率、OFF時の速度、ON時の速度それぞれの順位が入れ替わっていて、だんだん混乱してくる。 ざっくり見ると、今回のデータでは
- 文書の種類で見ると ソースコード > 技術文書 > 文学
- 言語で見ると プログラミング言語 > 英語 > 日本語
という傾向はありそう。
英語と日本語は同じ内容の翻訳ではないので、厳密な比較ではない。
今回使った英語技術文書と日本語技術文書はどちらも情報処理分野のものだけど、本文中に数式やソースコード例が混ざっている。日本語論文繰り返し文書の方は自然言語処理分野のもので、数式やソースコードはほとんど出てこない。
だから、日本語論文繰り返し文書と日本語技術文書の差の原因が、繰り返しの有無なのか、数式やソースコードの比率なのか、それ以外の内容差なのかは、まだよく分からない。
でも、ここまでの計測結果で、最初に心配していた 自作高速化に特別に有利なベンチマークで測っているのではないか」という疑いは、いちおう否定できたと思う。
ROCm版で計測
上記の結果がVulkan特有のものなのか、ROCmでも同じ傾向なのかが気になったので、ROCmでも測って、Vulkanと比較してみた。
64k:Vulkan OFF / ON / ROCm比較
こちらのVulkan欄はROCm対照用に改めて計測した数値を使ったので、前節のVulkan初回計測表とは一部の値がわずかに違う。
| 入力 | Vulkan OFF | Vulkan ON | ROCm |
|---|---|---|---|
| 日本語・技術 | 299.24 (5) | 366.03 (4) | 397.65 (5) |
| 英語・技術 | 312.42 (2) | 378.99 (1) | 398.78 (4) |
| C/C++ | 329.47 (1) | 378.01 (2) | 394.67 (6) |
| 日本語・文学 | 285.48 (6) | 344.11 (5) | 404.03 (3) |
| 英語・文学 | 304.39 (4) | 368.63 (3) | 405.36 (2) |
| 日本語・繰り返し | 272.34 (7) | 342.64 (6) | 394.03 (7) |
| ランダム | 308.25 (3) | 323.35 (7) | 415.82 (1) |
64k Vulkan QSA union ON, OFF, ROCmの入力ごとのPP速度比較表

グラフ中の略称は、JA Tech=日本語技術、EN Tech=英語技術、JA Lit=日本語文学、EN Lit=英語文学、JA Repeat=日本語繰り返し、C/C++=C/C++ソースコード、Random=ランダム
ROCmの方はVulkanほど入力の違いによるPP差が大きくない。しかも順位がかなり違う。
Vulkan QSA union OFFではC/C++コード、Vulkan QSA union ONでは英語技術文書、ROCmではランダムが最速だった
64kの最速/最遅の差は、
- Vulkan QSA union OFF:約1.21倍
- Vulkan QSA union ON:約1.17倍
- ROCm:415.82 / 394.03 ≒ 約1.06倍
速度自体は、64kではROCmは全7入力でVulkan両モードより速かった。
128k:Vulkan OFF / ON / ROCm比較
| 入力 | Vulkan OFF | Vulkan ON | ROCm |
|---|---|---|---|
| 日本語・技術 | —(対象外) | — | — |
| 英語・技術 | 214.92 (2) | 343.59 (2) | 298.89 (4) |
| C/C++ | 236.13 (1) | 346.60 (1) | 296.08 (6) |
| 日本語・文学 | 168.06 (6) | 294.02 (5) | 301.54 (3) |
| 英語・文学 | 204.94 (3) | 335.14 (3) | 302.22 (2) |
| 日本語・繰り返し | 183.66 (4) | 310.68 (4) | 296.27 (5) |
| ランダム | 170.62 (5) | 261.67 (6) | 308.22 (1) |
128k Vulkan QSA union ON, OFF, ROCmの入力ごとのPP速度比較表

ROCm 128kの最速/最遅の差は、308.22 / 296.08 ≒ 約1.04倍。
Vulkan OFFの約1.41倍、Vulkan ONの約1.32倍と比べると、かなり差が小さい。
そして、Vulkanでは遅い方だったランダムが一番速く、ソースコードが一番遅い、技術文書より文学の方が速いというVulkanとは真逆の結果になっている。
速度自体は、128kでは6入力中4つで、Vulkan QSA union ONの方がROCmより速かった
このあたりを見ると、入力依存性は「モデルと入力だけ」で決まるのではなく、バックエンドの実装ともかなり関係していそう。
この後、VulkanのQSA union OFF、つまりupstreamそのままに近い状態で、入力による差がとても大きく、C/C++コードが一番速くて日本語文学が一番遅い、そしてランダムは一番速くも一番遅くもないというのが気になって沼にハマって行くことになるのだけど、長くなるのでその話は次回の検証編にまわす。
まとめ、今後の予定
7種類の文書でPP速度を比べてみた結果、VulkanのQSA union OFF、QSA union ON、ROCmですべて傾向が違っていて、「こういう文書は読み込みが速い」と単純には言えないことが分かった。
ただ、入力文書によって読み込み速度が違うことは確かで、特にVulkanではその傾向が大きい。
最近、ハードウェア構成によって自動的にモデルや設定を調整してくれる推論エンジンが流行っているけど、ハードウェア構成だけでなく、入力文書のタイプやサンプルを渡したら、それに合わせてバックエンドや設定を自動調整してくれる、みたいなものがあったら便利かもしれない。
今回は、「自作高速化に特別に有利なベンチマークで測っているのではないか」という疑いは否定できた。前回と違って、当初の目的は達成している(笑)
次回はこの続きの検証編として、特にVulkan QSA union OFFで見えた入力差に注目し、GPUプロファイラや診断ログまで使って原因を掘り下げる予定。ROCm側の入力差が小さい理由は、引き続き別の調査課題として残る。
付録
おまけ:upstream入れ替えからQSA union導入まで
本文冒頭で書いた「upstreamを入れ替えてまた計測」の結果を書いておく。これは7種類の入力を比較した表とは別の計測で、いつもの日本語論文繰り返し文書をllama-cliで読み込ませた結果。
① upstream入れ替え直後(Unsloth Originalモデル、MTP OFF)
| Context | Vulkan PP | Vulkan TG | ROCm PP | ROCm TG |
|---|---|---|---|---|
| 64k | 269.24 | 25.31 | 390.73 | 21.18 |
| 128k | 179.51 | 23.67 | 292.69 | 17.13 |
| 256k | 135.41 | 20.02 | 193.64 | 12.37 |
各セル1回測定。この計測の前にWindowsを26H2へ更新しており、前回入れ替え時のupstream計測との差をすべてupstream変更に帰することはできないが、前回入れ替え時(第11回)のupstreamそのままの計測結果と比べてPP、TGともに少しずつ速くなっている。
② PLE16変換モデル対応後(64k)
| Backend | Original PP | PLE16 PP | Original TG | PLE16 TG |
|---|---|---|---|---|
| Vulkan | 269.30 | 270.65 | 25.42 | 25.90 |
| ROCm | 389.78 | 389.01 | 21.18 | 21.15 |
OriginalとPLE16の読み込み・推論に成功し、対応前と比べてPP、TGともに大きな差はなかった。
③ QSA union導入後(Vulkanのみ)
| モデル | Context | QSA union OFF PP | ON PP | ON PP改善率 | TG OFF / ON |
|---|---|---|---|---|---|
| Original | 64k | 270.74 | 341.94 | +26.30% | 25.58 / 25.89 |
| PLE16 | 64k | 270.26 | 339.48 | +25.61% | 25.97 / 25.80 |
| PLE16 | 128k | 179.34 | 307.15 | +71.27% | 24.03 / 23.53 |
| PLE16 | 256k | 135.10 | 277.68 | +105.54% | 20.19 / 20.12 |
upstream入れ替え後も、QSA unionは引き続き高速化に有効なことが分かった
テストデータの作り方
日本語・繰り返し
これは今まで計測に使ってきたデータと基本的に同じ。
乾孝司・奥村学「テキストを対象とした評価情報の分析に関する研究動向」(『自然言語処理』Vol.13, No.3, 2006年、pp.201–241)
この論文の、言語処理学会論文誌LaTeXコーパス
https://www.anlp.jp/resource/journal_latex/
に収録されているLaTeXソースから、第3章の一部を9,406字と14,874字で切り出し、2種類のブロックを繰り返して、必要な長さの日本語文書を作成し、先頭と末尾に指示文を加えた。
これまでのllama-cliによる計測では64k用(d7)、128k用(d15)、256k用(d31)の入力ファイルを使い分けていたが、今回の7種類比較では256k用のnlp-survey-ch3-d31-b1.txtに統一し、他の文書と同じく先頭から必要なトークン数を切り出した。
なので、今回の64kと128kの計測では、末尾の指示文は読み込まれていない。
日本語・文学
- 出典:青空文庫『吾輩は猫である』
- 加工:ダウンロードしたテキストファイルは文字コードがSJISだったのでUTF-8に変換
英語・文学
- 出典:Project Gutenberg #1184, The Count of Monte Cristo(モンテ・クリスト伯)
- 加工:ダウンロードしたテキストをそのまま使用
日本語・技術
- 出典:深層学習入門
- 加工:githubリポジトリからソースのzipファイルをダウンロード・展開し、目次データを参考に各章のmarkdownファイルを統合するpythonスクリプトを自作して、1ファイルに統合した
英語・技術
- 出典:Dive into Deep Learning 英語版 v1.0.3
- 加工:githubリポジトリからソースのzipファイルをダウンロード・展開し、目次データを参考に各章のmarkdownファイルを統合するpythonスクリプトを自作して、1ファイルに統合した
C/C++ソースコード
- 出典:ggml-org/llama.cpp
- 加工:今回のベースに使った
de7fa0a3c6a2e1b4cd9f22eb8d6bf5b12dbdb63bのソースから、自作スクリプトで推論関連コードを抽出し、1ファイルに統合した
ランダム
- llama-bench標準のランダムtoken入力を使用。実文書ファイルはなし
改造版llama-bench実文書入力のコマンド例
64k相当、PPだけを計測する例。-fが入力ファイル指定、-pが処理するtoken数。次の例は64k入力に必要なだけの長さがあるソースファイルを使用する。
.\llama-bench.exe `
-m "(メインモデルのパス)" `
-f "(十分長い実文書ファイルのパス)" `
--prompt-slice head `
-c 65536 `
-p 61789 `
-n 0 `
-d 0 `
-r 1 `
-b 2048 `
-ub 1024 `
-ctk f16 `
-ctv f16 `
-t 4 `
-ngl 999 `
-ncmoe 0 `
-fa auto `
-o json
random入力を測るときは-fと--prompt-sliceを外す。128kなら-c 131072 -p 126253に変更する。
これは私が改造したもので、公式llama-benchに同じオプションがあるという意味ではない。改造ソースはgithubリポジトリに置いてある
詳細な検証環境
Hardware
- Device: NucBox EVO-X2
- CPU / APU: AMD Ryzen AI MAX+ 395 with Radeon 8060S
- CPU clock displayed by Windows: 3.00 GHz
- Installed memory: 128GB
- UMA Frame Buffer: 96GB
- Windows CPU側に見えるRAM: 約32GB
- GPU: AMD Radeon 8060S Graphics
- GPU arch:
gfx1151
OS
- OS: Windows 11 Pro
- Version: 26H2(r5測定時)
- OS Build: 26300.9550
- Update: KB5121794(2026-10-08、r5測定前)
- Windows Feature Experience Pack: 計測資料で未確認
ベースのllama.cpp
- Upstream repository: ggml-org/llama.cpp
- r4 upstream pin: de7fa0a3c6a2e1b4cd9f22eb8d6bf5b12dbdb63b
Vulkan:
- Compiler: LLVM / Clang 20.1.8
- Vulkan SDK: 1.4.357.0
ROCm:
- ROCm: 10.0.0 / TheRock
- Compiler: AMD Clang 23.0.0
- Host toolchain: Visual Studio 2022 Build Tools / MSVC 14.44
- GPU target:
gfx1151
使用したモデル
- Repository:
unsloth/Qwen3.8-Flash-Next-GGUF - URL: https://huggingface.co/unsloth/Qwen3.8-Flash-Next-GGUF
- Quantization:
UD-IQ3_XXS - File size reported by llama.cpp: 76.32 GiB
- BPW: 3.71
- Model params: 176.94B
上記モデルを LaurentZuijdwijkのStrix Halo専用fork 内の gguf-py\gguf\scripts\gguf_split_ple_heads.py で変換したPLE16モデルを使った。
