llama.cppでのStrix Halo + eGPU RTX 5070 Ti(OCuLink経由):ベンチマークと結論(パート2)

Reddit r/LocalLLaMA / 2026/4/9

💬 オピニオンTools & Practical UsageModels & Research

要点

  • RADV経由でStrix HaloのAPUと、OCuLink経由で外部GPU(RTX 5070 Ti)にモデルのレイヤーを分割したハイブリッド構成において、Vulkanバックエンドを用いてllama.cppの性能をベンチマークした内容。
  • 27BのQwen3.5-27B-UD-Q4_K_XLモデルを対象に、テンソル分割比率を10%刻みで変化させ、100% APU/0% eGPUから0% APU/100% eGPUまでをテストする。
  • 取得したPrompt Processing(PP)およびToken Generation(TG)の指標を、以前に公開された汎用推定式による性能予測と比較している。
  • 重要な示唆として、コミュニティからベンチマークの実施は求められていたものの、著者は、同様のAPU+eGPU/テンソル分割構成では、先行する予測手法が概ね有効であるため、広範な再実行(追加の大量ベンチ)をほとんど不要にできると主張している。
  • フォローアップの全体的な目的は、ユーザーがテンソル分割を用いる任意のモデルに対してより確実に性能を見積もれるよう、手法を明確化することにある。
Strix Halo + eGPU RTX 5070 Ti via OCuLink in llama.cpp: Benchmarks and Conclusions (Part 2)

https://preview.redd.it/wqk6fh12d0ug1.jpg?width=4096&format=pjpg&auto=webp&s=292562e4000da9239b21ca5dc0e01adcf127f127

みなさんこんにちは!前回の投稿でのコミュニティのフィードバックを踏まえて、いくつかの点を明確にし、補足するためにこの記事を書こうと思いました。

コメント欄で多くの方からベンチマークを求められたので、まずは現在のモデルのベンチマークから始めます。

私はQwen3.5-27B-UD-Q4_K_XL.ggufをベンチマークしました。APUとeGPUの間で層(tensor split)を10%刻みで配分します。つまり、100%/0%から0%/100%までの範囲です。

以下では、現実にはこれらのベンチマークを厳密に行う必要がなかった理由を示します。ここでは、最初の記事で私が示した式から予測された値と、実際のPP(Prompt Processing)およびTG(Token Generation)の指標を比較します。前回の投稿の主目的は、tensor splitを使う場合に、どんなモデルに対してもAPU+eGPU構成の性能を推定するための普遍的な方法を示すことでした。しかし、寄せられた質問の数を見ると、この考え方を十分に明確に伝えられていなかったようです。なので、今ここで訂正します!

~/llama.cpp/build-vulkan/bin/llama-bench  -m ~/Qwen3.5-27B-UD-Q4_K_XL.gguf  -ngl 99  -fa 1  -dev vulkan1/vulkan0  -ts 10/0,9/1,8/2,7/3,6/4,5/5,4/6,3/7,2/8,1/9,0/10 ggml_vulkan: Found 2 Vulkan devices: ggml_vulkan: 0 = NVIDIA GeForce RTX 5070 Ti (NVIDIA) | uma: 0 | fp16: 1 | bf16: 1 | warp size: 32 | shared memory: 49152 | int dot: 1 | matrix cores: NV_coopmat2 ggml_vulkan: 1 = Radeon 8060S Graphics (RADV STRIX_HALO) (radv) | uma: 1 | fp16: 1 | bf16: 0 | warp size: 64 | shared memory: 65536 | int dot: 1 | matrix cores: KHR_coopmat 
model size params backend ngl fa dev ts test t/s
qwen35 27B Q4_K - Medium 16.40 GiB 26.90 B Vulkan 99 1 Vulkan1/Vulkan0 10.00 pp512 268.02 ± 0.46
qwen35 27B Q4_K - Medium 16.40 GiB 26.90 B Vulkan 99 1 Vulkan1/Vulkan0 10.00 tg128 11.89 ± 0.03
qwen35 27B Q4_K - Medium 16.40 GiB 26.90 B Vulkan 99 1 Vulkan1/Vulkan0 9.00/1.00 pp512 280.95 ± 10.11
qwen35 27B Q4_K - Medium 16.40 GiB 26.90 B Vulkan 99 1 Vulkan1/Vulkan0 9.00/1.00 tg128 12.43 ± 0.03
qwen35 27B Q4_K - Medium 16.40 GiB 26.90 B Vulkan 99 1 Vulkan1/Vulkan0 8.00/2.00 pp512 267.87 ± 9.95
qwen35 27B Q4_K - Medium 16.40 GiB 26.90 B Vulkan 99 1 Vulkan1/Vulkan0 8.00/2.00 tg128 12.89 ± 0.02
qwen35 27B Q4_K - Medium 16.40 GiB 26.90 B Vulkan 99 1 Vulkan1/Vulkan0 7.00/3.00 pp512 293.02 ± 2.44
qwen35 27B Q4_K - Medium 16.40 GiB 26.90 B Vulkan 99 1 Vulkan1/Vulkan0 7.00/3.00 tg128 13.48 ± 0.13
qwen35 27B Q4_K - Medium 16.40 GiB 26.90 B Vulkan 99 1 Vulkan1/Vulkan0 6.00/4.00 pp512 336.32 ± 1.94
qwen35 27B Q4_K - Medium 16.40 GiB 26.90 B Vulkan 99 1 Vulkan1/Vulkan0 6.00/4.00 tg128 14.62 ± 0.24
qwen35 27B Q4_K - Medium 16.40 GiB 26.90 B Vulkan 99 1 Vulkan1/Vulkan0 5.00/5.00 pp512 377.92 ± 14.46
qwen35 27B Q4_K - Medium 16.40 GiB 26.90 B Vulkan 99 1 Vulkan1/Vulkan0 5.00/5.00 tg128 17.20 ± 0.08
qwen35 27B Q4_K - Medium 16.40 GiB 26.90 B Vulkan 99 1 Vulkan1/Vulkan0 4.00/6.00 pp512 462.06 ± 3.56
qwen35 27B Q4_K - Medium 16.40 GiB 26.90 B Vulkan 99 1 Vulkan1/Vulkan0 4.00/6.00 tg128 19.81 ± 0.08
qwen35 27B Q4_K - Medium 16.40 GiB 26.90 B Vulkan 99 1 Vulkan1/Vulkan0 3.00/7.00 pp512 563.40 ± 1.84
qwen35 27B Q4_K - Medium 16.40 GiB 26.90 B Vulkan 99 1 Vulkan1/Vulkan0 3.00/7.00
tg128 22.19 ± 0.10 qwen35 27B Q4_K - Medium 16.40 GiB 26.90 B Vulkan 99 1 Vulkan1/Vulkan0 2.00/8.00 pp512 757.22 ± 3.64 qwen35 27B Q4_K - Medium 16.40 GiB 26.90 B Vulkan 99 1 Vulkan1/Vulkan0 2.00/8.00 tg128 26.05 ± 0.06 qwen35 27B Q4_K - Medium 16.40 GiB 26.90 B Vulkan 99 1 Vulkan1/Vulkan0 1.00/9.00 pp512 988.62 ± 5.18 qwen35 27B Q4_K - Medium 16.40 GiB 26.90 B Vulkan 99 1 Vulkan1/Vulkan0 1.00/9.00 tg128 30.25 ± 0.06
ggml_vulkan: デバイスメモリの割り当てサイズ 1067094656 に失敗しました。 ggml_vulkan: vk::Device::allocateMemory: ErrorOutOfDeviceMemory main: エラー: モデル '~/Qwen3.5-27B-UD-Q4_K_XL.gguf' の読み込みに失敗しました 

モデルが完全にはVRAMに収まらなかったため、VRAMオフロード100%では、llama-benchがメモリ不足エラーでクラッシュしました。

コメント欄では、なぜ私が古い llama-2-7b.Q4_0.gguf でテストを実行したのか、多くの人が当然の疑問として驚いていました。理由を説明します。意図的に選んだのは2つの理由です:

  1. 比較のための普遍的なベースラインです。 歴史的に、この同一のモデルはLLMハードウェアテストにおける「ゴールドスタンダード」として定着しました。この正確なモデルに関する、非常に膨大な結果データベースがオンラインにあります(たとえば、この GitHubスレッド)。Apple Silicon、NVIDIA、AMD、APU、そしてそれらのバックエンドなど、幅広い構成についてのデータです。このLlamaに対してTGおよびPPの指標を比較すれば、当社のAPU+eGPUコンボの性能レベルが、他のあらゆるハードウェアに対してどの程度かを簡単に理解できます。
  2. ハードウェア性能定数を計算するためです。 このモデルで、各ノードごとにTG128とPP512の速度を測定しました(モデルがRTX 5070 Ti上に完全にロードされている場合、またはStrix Halo上に完全にロードされている場合)。古いLlamaの絶対値は私たちにとってそれほど重要ではありません。重要なのは、その比率です。GPU速度とAPU速度の比(以降、GtA_ratioと呼びます)は、チップ自体のメモリ帯域幅と演算能力にのみ依存する定数です。そしてこの定数は、どんなモデルでも同じになります。

数値で見るとこうなります:

  • トークン生成(TG128): 5070 Tiでは168.91 t/s、Strix Haloでは52.62 t/sです。TG128のGtA_ratio定数 = 168.91 / 52.62 = 3.21
  • プロンプト処理(PP512): 5070 Tiでは7461.22 t/s、Strix Haloでは1194.55 t/sです。PP512のGtA_ratio定数 = 7461.22 / 1194.55 = 6.25

もちろん、グラフィックスカードを別のものに入れ替えれば、これらの定数は変わります。しかし、現在のシステムでそれらを把握しておけば、どんな新しいLLMでも速度を予測できます。

前回の記事で、Tensor Split中の性能低下はAmdahlの法則に従い、その低下のグラフは双曲線になると述べました。より分かりやすくするために、基本式を少しだけ調整しました。

変更後はこうです:

Perf = [ GtA_ratio / ( 1 + (Share / 100) * (GtA_ratio - 1) ) ] * 100%

ここで:

  • Perf — ベースとなるAPU速度に対する割合としての、システム全体の性能。
  • GtA_ratio — 我々のeGPU対APUの速度比(先ほど計算した定数)。
  • Share — 遅い方のシステムメモリ(APU RAM)にオフロードされるモデルの割合。0〜100の範囲で、0はモデル全体が高速なeGPUのVRAMに収まることを意味し、100はシステムRAM上で完全に動作することを意味します。

では、ベースラインであるllama-2-7b.Q4_0.ggufのベンチマークに基づいて、全体の性能グラフを描きます。

https://preview.redd.it/ki4nhgty00ug1.png?width=3000&format=png&auto=webp&s=f5a96195b565d75591545cabe24ac69c14df2377

次に、現在のQwen3.5-27B-UD-Q4_K_XL.ggufモデルの新しいテスト結果を、この双曲線の上に重ねます。

ちょっとしたリマインド:モデルが完全にVRAMに収まらなかったため、最終データ点(VRAMオフロード100%)はグラフから欠落しています

ご覧の通り、実際のQwen3.5のテスト結果は、我々の数学的なカーブに完全にフィットしています!これが主張のポイントを証明しています。どんな新しいモデルに対してもシステム性能を推定するのに、必ずしもベンチマークを実行する必要はありません。単純な3ステップのアルゴリズムに従うだけで十分です:

  1. モデルの「テール(尾)」を計算します: モデルファイルサイズからGPU VRAM容量(私の場合は16GB)を引きます。これにより、eGPUに収まらず、Strix HaloのRAMに送られるウェイトが何ギガバイト分あるかが分かります。
  2. その「テール」を見つけます: この「テール」を、モデル全体のウェイト量に対する割合へ変換します。得られた値が、Shareの値です。
  3. 式に適用します: Shareと、GtA_ratioの定数を代入して、最終速度のPerfを計算します。

私のシステム(RTX 5070 Ti + Strix Halo)での計算は以下のようになります:

トークン生成(TG128): GtA_ratio = 3.21。式:

Perf_tg128 = [ 3.21 / ( 1 + (Share / 100) * (3.21 - 1) ) ] * 100%

プロンプト処理(PP512): GtA_ratio = 6.25。式:

Perf_pp512 = [ 6.25 / ( 1 + (Share / 100) * (6.25 - 1) ) ] * 100%

リマインド:Perf_tg128とPerf_pp512は、単一のAPUだけでモデルを動かした場合に対する割合として、動作速度を表示します。

コメント欄で別のホットな話題になっているのは、eGPUのインターフェースの選択です。多くの人がOCuLinkとThunderbolt(TB)またはUSB4のどちらかについて質問しました。すべての疑問を解消するために、プロセスの仕組みを分解して説明します。

前述した通り、OCuLinkはプロンプト処理(PP)でもトークン生成(TG)でもボトルネックではありません。理由を理解するために、Tensor Splitを使っているときに単一トークンを生成するのにかかる時間を構成する要素を見てみましょう。生成時間は常に3つの段階の合計です:

  1. eGPU上で最初の層のチャンクを計算する。
  2. 活性テンソル(中間結果)を、eGPUからAPUへケーブル経由で送信する。
  3. APUのシステムRAM上で残りの層を計算する。

そして、ここに最も重要なニュアンスがあります。2番目の段階では、帯域幅よりもレイテンシがはるかに重要です。

送信されるアクティベーションテンソルのサイズは比較的小さいため、どの最新のインターフェース(OCuLink、TB、USB4のいずれであっても)でも、生の帯域幅は十分すぎるほどで、余裕も大きいです。通信は「パイプ」を飽和させません。しかし、この送信サイクルが生成されるすべてのトークンごとに繰り返されるため、前面に出てくるのは、信号が初期化され、点Aから点Bへ到達するまでの速さです。

ここに、主な技術的な違いがあります:

  • OCuLink は本質的に「むき出し」の PCIe バス拡張です。データは、最小限の遅延で、CPU の最も低遅延のレーンへ直接流れます。
  • Thunderbolt と USB4 は、PCIe 信号をそれぞれの独自プロトコルにパッケージ(カプセル化)し、コントローラ経由で通し、そして反対側でアンパックする必要があります。これにより、すべてのトランザクションにオーバーヘッドとマイクロディレイが追加されます。

したがって、ローカル LLM 用のインターフェースを選べるのであれば、OCuLink を使うことを強くおすすめします。

最後に、約束どおり、Qwen3.5-122B-A10B-UD-Q4_K_XL モデルに対して私のシステムで行ったベンチマーク結果はこちらです:

~/llama.cpp/build-vulkan/bin/llama-bench \
 \
 -m ~/Qwen3.5-122B-A10B-UD-Q4_K_XL-00001-of-00003.gguf \
 -ngl 99 \
 -fa 1 \
 -dev vulkan1/vulkan0 \
 -ts 100/0,95/5,90/10,85/15,80/20,75/25,70/30 ggml_vulkan: Found 2 Vulkan devices: ggml_vulkan: 0 = NVIDIA GeForce RTX 5070 Ti (NVIDIA) | uma: 0 | fp16: 1 | bf16: 1 | warp size: 32 | shared memory: 49152 | int dot: 1 | matrix cores: NV_coopmat2 ggml_vulkan: 1 = Radeon 8060S Graphics (RADV STRIX_HALO) (radv) | uma: 1 | fp16: 1 | bf16: 0 | warp size: 64 | shared memory: 65536 | int dot: 1 | matrix cores: KHR_coopmat 
model size params backend ngl fa dev ts test t/s
qwen35moe 122B.A10B Q4_K - Medium 71.73 GiB 122.11 B Vulkan 99 1 Vulkan1/Vulkan0 100.00 pp512 247.59 ± 5.96
qwen35moe 122B.A10B Q4_K - Medium 71.73 GiB 122.11 B Vulkan 99 1 Vulkan1/Vulkan0 100.00 tg128 19.46 ± 0.26
qwen35moe 122B.A10B Q4_K - Medium 71.73 GiB 122.11 B Vulkan 99 1 Vulkan1/Vulkan0 95.00/5.00 pp512 270.07 ± 2.77
qwen35moe 122B.A10B Q4_K - Medium 71.73 GiB 122.11 B Vulkan 99 1 Vulkan1/Vulkan0 95.00/5.00 tg128 19.91 ± 0.63
qwen35moe 122B.A10B Q4_K - Medium 71.73 GiB 122.11 B Vulkan 99 1 Vulkan1/Vulkan0 90.00/10.00 pp512 281.56 ± 12.32
qwen35moe 122B.A10B Q4_K - Medium 71.73 GiB 122.11 B Vulkan 99 1 Vulkan1/Vulkan0 90.00/10.00 tg128 20.40 ± 0.39
qwen35moe 122B.A10B Q4_K - Medium 71.73 GiB 122.11 B Vulkan 99 1 Vulkan1/Vulkan0 85.00/15.00 pp512 295.46 ± 16.68
qwen35moe 122B.A10B Q4_K - Medium 71.73 GiB 122.11 B Vulkan 99 1 Vulkan1/Vulkan0 85.00/15.00 tg128 20.75 ± 0.57
qwen35moe 122B.A10B Q4_K - Medium 71.73 GiB 122.11 B Vulkan 99 1 Vulkan1/Vulkan0 80.00/20.00 pp512 311.33 ± 2.39
qwen35moe 122B.A10B Q4_K - Medium 71.73 GiB 122.11 B Vulkan 99 1 Vulkan1/Vulkan0 80.00/20.00 tg128 21.79 ± 0.46
ggml_vulkan: Device memory allocation of size 650418176 failed. ggml_vulkan: vk::Device::allocateMemory: ErrorOutOfDeviceMemory main: error: failed to load model '~/Qwen3.5-122B-A10B-GGUF/Qwen3.5-122B-A10B-UD-Q4_K_XL-00001-of-00003.gguf' 

ご覧のとおり、モデルのごく一部(最大20%)しか VRAM に収まらないため、全体的な TG(TG)と PP(PP)の速度はわずかにしか増えませんでした。具体的には、Token Generation(TG)がわずか約12%(19.46 から 21.79 t/s)上昇し、Prompt Processing(PP)は約25.7%(247.59 から 311.33 t/s)増加しました。

巨大なモデルの場合は、性能向上が制限されるのは単純に、eGPU の VRAM 容量が通常、Strix Halo で利用可能な大容量のシステム RAM よりはるかに小さいためです。

submitted by /u/xspider2000
[link] [comments]