技術 約8分で読めます

LemonadeをStrix Halo (EVO-X2) で動かしたらVulkanの共有メモリ漏れとROCmの安定性が見えた

前回の紹介記事でAMD公式のローカルAIサーバーLemonadeを取り上げた。HNのコメントや公式ドキュメントをベースに書いた記事だったが、自分のEVO-X2(Ryzen AI Max+ 395 / Radeon 8060S)で実際に動かしてみたので、その結果をまとめる。

検証環境

項目
PCGMKtec EVO-X2
CPU/GPURyzen AI Max+ 395 / Radeon 8060S (gfx1151)
メモリ64GB UMA
Lemonadev10.0.1(内蔵llama.cpp b8460)
ドライバAMD Software 26.3.1

BIOS設定は検証項目によって32GB/32GBと48GB/16GBを切り替えた。この配分の意味と影響はVRAM配分の記事に詳しいが、Vulkanリグレッションの記事で書いたとおり、AMDドライバ26.3.1ではBIOS配分がパフォーマンスに直結する状態になっている。

ベースラインとして、llama-server b8183直叩きでのQwen3.5-35B-A3B Q6_K(26.55GB)の速度は前回計測済みで、ctx=65536 / q8_0 KVで53.6 t/s。

Lemonade経由のオーバーヘッド

まず一番気になる「Lemonadeを挟むと遅くなるのか」を確認した。

構成モデルctx速度
Lemonade v10.0.1 (b8460)Q4_K_XL (21.2GB)409657.9 t/s
llama-server b8183 直叩きQ6_K (26.55GB)409653.7 t/s
llama-server b8183 直叩きQ4_K_M (19.7GB)409654.9 t/s

Lemonade経由のほうが速いが、これはモデルの量子化が異なるため直接比較はできない。lemonade pullで落ちてくるのはQ4_K_XL(21.2GB)固定で、手持ちの直叩きデータはQ6_K(26.55GB)。abliteratedモデルの選定で試したQ4_K_Mとも量子化方式が異なり、公平な比較にはならない。

Lemonadeの内部構成はこうなっている。

  • lemonade-router.exe(port 8000: Web UI、port 9000: APIプロキシ)
  • llama-server(port 8001: 推論エンジン、b8460)

推論自体はllama-serverがやっていて、routerはプロキシに過ぎない。紹介記事で引用した開発者の「素のllama.cppと同等」は妥当だろう。オーバーヘッドはほぼゼロと見ていい。

カスタム引数も--llamacpp-argsで渡せる。

lemonade run Qwen3.5-35B-A3B-GGUF --ctx-size 65536 \
  --llamacpp-args "--cache-type-k q8_0 --cache-type-v q8_0 --no-mmap --reasoning-budget 0"

ctx=65536 / q8_0 KVで63.5 t/s。直叩きの設定をそのまま持ち込める。

NPU Hybrid実行

紹介記事で「NPUはプリフィルのオフロードに使える」と書いたが、実際にHybridモデルを動かしてみた。

lemonade run Qwen3-8B-Hybridを実行すると、RyzenAI-Server v1.7.0(542MB)が自動ダウンロード・起動された。

項目
バックエンドryzenai-llm (FastFlowLM)
モデルQwen3-8B(AWQ量子化 ONNX)
TTFT0.44秒
生成速度24.0 t/s(300トークン)

比較対象としてVulkanでの35Bモデルが57.9 t/sなので、NPU Hybridの8Bモデルはその半分以下。ただしTTFT 0.44秒は高速で、Vulkanでの大モデルのプリフィルが数秒かかることを考えると、小型モデルの低レイテンシ用途には明確に向いている。NPUはGPU VRAMを消費しないので、GPUで大きいLLMを動かしつつNPUで音声系の小型モデルを常駐させる分担が現実的だ。

なおQwen3.5-35B-A3BのHybrid版はリストになく、NPU対応は小型モデル(8B以下)限定だった。

Vulkan vs ROCm: 共有メモリ漏れの発見

ここが今回の検証で一番大きな発見だった。

48GB VRAM / 16GBシステムのBIOS設定で、Vulkan(mmap)とROCmを比較した。

バックエンド速度専用GPU共有メモリメインRAM残
Vulkan (mmap)46 t/s16.1 GB7.1 GB0.8 GB
ROCm37.8 t/s21.6 GB3.3 GB6.7 GB

Vulkanのほうが18%速いが、共有メモリに7.1GBも漏れている。Q4_K_XL(21GB)のうち約5GBがシステムRAM側に配置されてしまっていた。48/16でシステム16GBのうち7.5GBをGPU共有に取られると、OS+Parsec+Tailscaleの残りが0.8GB。実用的に危険な状態だ。

ROCmだと共有メモリ漏れが3.3GBに半減し、メインRAMに6.7GBの余裕ができる。速度は落ちるがメモリ健全性が段違いに良い。

この共有メモリ漏れはAMDドライバ26.3.1 + Vulkan固有の問題で、ROCmバックエンドでは発生しない。後述の画像生成(sd-cpp / ROCm)では共有メモリが0.9GBまで下がることも確認しており、Vulkanドライバのメモリ配置ロジックに問題がある。

4モデル同時起動

Lemonadeの最大の売りであるマルチモダリティ同時起動を試した。48/16 BIOS、ROCmバックエンドで4モデルを同時起動。

モデルバックエンドポート
Qwen3.5-35B-A3B Q4_K_XLllama.cpp ROCm8001
Whisper-Smallwhisper.cpp + NPU8002
Kokoro-v1 TTSkokoro (ONNX)8003
Flux-2-Klein-4Bsd-cpp ROCm8004
項目
専用GPU37.6 GB / 48 GB(残り10.4 GB)
共有GPU3.4 GB
メインRAM67%(残り約5.3 GB)
LLM速度37.7 t/s

VRAM 10GB余り、メインRAM 5GB余り。4モデル同時でもLLM速度が単体時(37.8 t/s)からほぼ低下していない。Whisper + Kokoroは計+0.3GBしか食わないので影響が軽微。

LLM + 画像生成 + 音声認識 + 音声合成を1つのサーバーで同時に動かせるのは、紹介記事で書いた「Ollamaとの最大の差別化ポイント」を実感できる結果だった。OllamaがMLXバックエンドに移行してApple Silicon側が整理されつつある一方、AMD側はこういう統合レイヤーが必要な段階にある。

mmapとBIOS配分のトレードオフ

4モデル同時起動にはmmap(デフォルト)が必須だった。--no-mmapだとロード時にファイル全体をシステムRAMに読み込むため、48/16の16GBでは溢れてctx=65536のロードが失敗する。mmapはページ単位の読み込みなのでピークメモリが抑えられる。

ただしmmapには速度ペナルティがある。

構成ctx速度
32/32, —no-mmap, Q6_K6553653.6 t/s
48/16, mmap, Q4_K_XL6553646.3 t/s
48/16, —no-mmap, Q4_K_XL409657.8 t/s

mmapだと46 t/sで、—no-mmapの57 t/sより遅い。UMA上での共有メモリアクセスパターンの違いが効いている可能性がある。

BIOS向いている用途制約
48/16マルチモダリティ同時起動ctx=65536はmmap必須(速度低下)、—no-mmapだとctx=4096限定
32/32LLM単体の長コンテキストVRAM余裕が少なくマルチモダリティは厳しい

画像生成: Flux-2-Klein-4B

LLM/Whisper/Kokoroを全停止後、Flux Klein 4Bを単体で起動した。

項目
バックエンドsd-cpp (ROCm)、Vulkanではなく自動選択
モデルサイズ15.4 GB(text encoder 7.7GB + diffusion 7.4GB + VAE 0.3GB)
GPU専用16.8 GB
共有メモリ0.9 GB
生成時間約2分(512x512、1枚)

LLM(Vulkan)を外したら共有メモリが7.1GB→0.9GBに激減した。sd-cppのROCmバックエンドは正しく専用GPUメモリに載せている。共有メモリ漏れがVulkan + ドライバ26.3.1固有の問題であることの裏付けになった。

生成結果:

Flux-2-Klein-4Bで生成した猫の画像。窓辺に座る茶トラ猫、フォトリアリスティック品質

Flux-2-Klein-4Bで生成したアニメ風イラスト。桜の木の下に立つ黒髪の女の子

512x512でフォトリアル系もアニメ系も問題なく生成できた。ただし1枚あたり約2分かかる。RTX 4060 LaptopでComfyUIを回したときと比べても特段速いわけでもなく、画像生成の実用性としては「動くことは動く」という段階。バッチ生成やイテレーションを回す用途には厳しい。

ぶつかった壁

routerプロキシが機能しない

Lemonadeのrouterはlemonade-router.exeがport 9000でAPIプロキシを提供する設計だが、chat completionsリクエストに一切応答しなかった。

エンドポイントバインドローカルTailscale
router (9000)0.0.0.0応答なし応答なし
llama-server (8001)127.0.0.1動作アクセス不可

llama-server(8001)は127.0.0.1バインドなので外部からアクセスできず、router(9000)は応答しない。48/16のクリーン再起動後でも同じ症状で、前セッションのllama-serverとは無関係。router自体のバグだ。

Tailscale経由でAPIを公開する構成をすでに運用しているが、Lemonade単体ではこれが不可能。llama-server直叩き(--host 0.0.0.0)のほうが確実という結論になった。

recipesコマンドが500エラー

lemonade recipesは一貫して500エラー。ログを見ると原因が判明した。

Backend availability:
  - NPU hardware: Yes
  - System RAM: 64.0 GB (max model size: 51.2 GB)

GPUが検出されていない。NPUとRAMしかリストされず、Radeon 8060S(Vulkan GPU)がBackend availabilityに出ない。

Strix HaloはUMA APUでiGPUとして動作するため、Lemonadeのdiscrete GPU検出ロジックに引っかからないのだろう。推論自体はllama.cppが直接Vulkanデバイスを叩くので動くが、Lemonadeの管理レイヤーがGPUの存在を認識できていない状態。dGPU(RX 7900 XTXなど)なら問題ないはず。

48/16 BIOSに切り替えたらNPUすら検出されなくなり、状況がさらに悪化した。32/32ではNPU: Yesだったので、BIOS配分がバックエンド検出にも影響している。

pullでモデル量子化を選べない

lemonade pull Qwen3.5-35B-A3B-GGUFで落ちてくるのはQ4_K_XL固定。Q6_KやQ8_0を指定する手段がない。手持ちのGGUFを使いたい場合はカスタムパスを指定する必要があるが、その手順が明確にドキュメント化されていない。

VulkanとROCmどちらを選ぶか

最終的な比較をまとめる。

VulkanROCm
LLM速度46 t/s37.8 t/s
共有メモリ漏れ7.1 GB3.3 GB
メインRAM残(4モデル時)危険(0.8 GB)5.3 GB
マルチモダリティメモリ限界余裕
画像生成未検証ROCm自動選択、正常動作

API運用+マルチモダリティならROCmが正解。速度は18%落ちるがメモリ健全性が段違いで、4モデル同時起動しても安定している。LLM単体の速度を最優先するならVulkan + 32/32 BIOS + llama-server直叩きのほうが速い。

Lemonadeは「全部入り」の手軽さに価値があるツールなので、マルチモダリティを活かすならROCm一択という結論になった。


v10.0.1時点ではGPU検出やrouterなどStrix Halo UMA固有の不具合が目立つが、4モデル同時起動がROCmで安定したのは収穫だった。