メインコンテンツへスキップ
見出し画像

llama.cppはROCmだと推論精度が落ちる!? ~Ryzen AI MaxをVulkanで叩いて比較する~

    こんにちはRcatです。
    最近ある切っ掛けから、ROCmビルドのllama.cppがどうも推論精度悪い気がしています。
    そこで、とりあえず別バックエンドにしてどう変わるのか見ていきたいと思います。

    画像

    次回:原因となるコミットを特定しました


    はじめに

    利用規約

    情報や作品の活用時は事前に利用規約をご確認ください。

    コメントについて

    利用規約のガイドラインを確認の上コメントしてください。
    則っていないコメントは削除します。


    概要

    切っ掛け ~バックエンドなんて関係ないやろ~

    最近CUDAビルドのllama.cppを触る機会があったのですが、同じモデルの同じ量子化(同じ配布もとなので同ハッシュのはず)でもROCmビルドのllama.cppで推論したときに比べて明らかに頭がいいんですよね…。

    なんと言いますか、いままでに比べて急に気が利くというか、理解が深いというかそんな感じ。

    Geminiに聞いてみたところ、浮動小数点の丸め誤差なんかで可能性はあるらしい。絶対ないと言い切れないならバックエンドで知能の性能差が出ている可能性も否定できません。

    ですがハードを変えるのは無理なので、とりあえずバックエンドのAPIだけでも変えてみてどうなるか見てみることにしました。
    そこでVulkanに白羽の矢が立ちました。

    Vulkanとは

    GPUに依存しない汎用的なレンダリングAPIです。最近マインクラフトがこれに移行していることで有名ですね。
    そんなレンダリングAPIをLLM推論のバックエンドに使ったのがllama.cppのVulkanバージョン。
    汎用性があり、NidiaだろうがAMDだろうがIntelだろうがGPUを使える。

    準備

    環境

    大前提として今回の環境を挙げます

    • マシン
      EVO-X2

      • APU: Ryzen AI Max+395 (Radeon 8060S)

    • 推論エンジン

      • llama.cpp

        • ROCm 7.2.4

        • Vulkan 1.4.357.0

    • モデル

      • Laguna S2.1 IQ4

    • プラットフォーム

      • OpenHands

    llama.cppをVulkanビルドする

    あとで気づいたんですが、llama.cppのプロジェクトにDockerfileあるんですね…。
    気づく前に自分で作っちゃったのでそれ使いますがw

    画像

    簡単に説明すると、Vulkanの公式からLinuxでのインストール方法を持ってきてそれをDockerfileに落としこんだだけ。前まで使ってたROCmのやつがベースで作りました。

    準備出来たらビルドします
    composeは特典の方に貼っときます。デバイスマッピングとか要ります。

    docker compose build

    Vulkanビルド起動

    コンテナを立ち上げる

    ビルドが通ったら起動します。ROCmより体感短くビルド終わりましたね。

    $ docker compose up
    [+] up 1/1
     ✔ Container llama-cpp-server-vulkan Created      0.0s
    Attaching to llama-cpp-server-vulkan
    llama-cpp-server-vulkan  | 0.00.037.059 I cmn  common_param: common_params_print_info: verbosity = 3 (adjust with the `-lv N` CLI arg)
    llama-cpp-server-vulkan  | 0.00.038.289 I srv   load_models: Loaded 0 cached model presets
    llama-cpp-server-vulkan  | 0.00.039.234 I srv   load_models: Loaded 7 custom model presets from /opt/models.ini
    llama-cpp-server-vulkan  | 0.00.044.114 I srv    operator(): Available models (7) (*: custom preset)
    llama-cpp-server-vulkan  | 0.00.044.117 I srv    operator():   * Laguna-S-2.1-UD-IQ4_NL (aliases: MAX)
    llama-cpp-server-vulkan  | 0.00.044.119 I srv    operator():   * Qwen3.6-27B-IQ4_XS
    llama-cpp-server-vulkan  | 0.00.044.121 I srv    operator():   * Qwen3.6-35B-A3B-MTP-UD-IQ4_XS (aliases: MAIN)
    llama-cpp-server-vulkan  | 0.00.044.122 I srv    operator():   * gemma-4-E4B-it-IQ4_NL (aliases: COMPRESS)

    パフォーマンス

    面白い結果になりましたw

    画像

    なんとプリフィルはROCmのほうが早いのに、デコードはVulkanのほうが早いですw
    あれ、デコードって帯域でブロックされてなかったっけ…
    まだ上がったのかw

    CPU-MoEだとさらに面白い挙動が判明する

    MoEエキスパートをメインメモリに逃がすcpu-moeオプションですが、統合メモリなら転送速度が同じなので、少なくともデコードはほぼ変わらないはずです。
    しかし、Vulkan君どうしたw

    さすがにおかしいと思ってCPUとGPUを監視したところ、デコード時の挙動に大きな差があることがわかりました。

    画像

    ROCmは常にGPUが全開で回っているのですが、VulkanはデコードフェーズになるとCPUが代わりに回り始めました。

    あーCPUがデコード担っちゃったのか。
    逆にROCm何気にすごいのでは? 統合メモリだからだとは思いますが、明示的なcpu-moeでまさかのcpuに仕事させてない!?

    どうでもいいかもしれませんが、ROCm7.14をこのタイミングで試しました。若干の低下ですね。7.14は495対応のためだと思ったのですが逆に下がりますか…。

    画像

    Vulkan VS ROCm

    実験開始

    というわけで、Laguna S2.1 IQ4_NLを使ってOpenHandsで丸投げします。
    というかROCmは昨日丸投げして結果が微妙だったので、Vulkanでやり直す感じです。

    実装する内容はこちらの記事で作った仕様書になります。

    実施結果

    では結果です。タスクの流れを上から比較していきます

    まずは最初の開始時
    「設計終わったらレビュー依頼してね」という指示があります。
    それに対して…
    ROCmでは止まらずに進んでしまいました。
    Vulkanの時はレビュー依頼お願いしますでちゃんと止まりました。

    指示追従性に違いがすでに出ていると

    画像

    グローバルルールの順守度
    「ユーザーとやり取りは日本語で、それ以外は自由でいいです」というルールがあります。
    それに対して…
    ROCmではドキュメント含め全部英語でした。
    Vulkanではちゃんと設計書であったり、私にレビューを求めるときの発言が日本語でした。それ以外の独り言は英語で、トークン効率が良くなっています。
    ※Lagunaは日本語トークン効率が超絶悪い

    READMEは仕上げなので、最後までちゃんと指示を覚えていられるかってところですね。

    画像

    結果報告
    前述のユーザーとのやり取りは日本語としているルールに則れば日本語で書くのが正解。
    しかし、これは両方英語でした。まぁグローバルルールはAGENTS.MDに書いてあって、それが常時システムには含まれない仕様らしいので、途中のコンテキスト圧縮で抜けたかな?
    でもREADMEは日本語だったし、ずっと英語で独り言言ってたのに引っ張られたかな?

    画像

    テスト
    APIのテストはちゃんと通すのですが、ブラウザを使ったテストをするかどうかに違いが出ました
    Vulkanは言わなくてもブラウザで動かすのに対し、ROCmでは完了後に指摘して初めて開始しました。
    しかもよく見ると…ROCmは指示無視してブラウザ動かしてない。

    タスク完了後の追加指示にちゃんと従うかに差が出てますね。
    低性能モデルは完了するともう満足なのか、従わない傾向にあります。つまりROCmは劣化してる?

    画像

    動作確認
    最後に動いたかどうかです。
    Vulkan版は動作しました。ちょっとコントラストがおかしくて見えないのですが、Lagunaはビジョンないのでまぁ仕方ないとします。
    ROCm版は動作しませんでした。ブラウザに読み込むと404エラーがコンソールに出て進みませんね。サーバーも動くしvue.jsもビルドできるから惜しいところまで行ってるんでしょうけど。

    画像

    修正依頼
    ROCmは動かなかったのでこの際もう無視します。
    Vulkan版はコントラストの問題で見えなかったので、どこの色がどう悪いか教えたところ直してくれました。

    画像

    まとめ

    検証の結果、現時点ではllama.cppにてROCmバックエンドを使用すると、推論精度が低下することが分かりました。

    一度や二度ならず様々な指示の聞き洩らしやタスクの遂行結果や、今までも違和感からしてこの差は明らかです。
    cpu-moeでだいぶパフォーマンスが落ちてしまいますが、動かないものを無駄に作るよりはマシ。 
    この結果だとVulkanビルドに移行するしかなさそうだな…。

    ただし、これがAPU(RDNA3.5)だからなのかは別途検証の余地が残ります。
    Radeon RXは持ってないので試せません。

    それではまたお会いしましょう。


    リンク集

    感想投稿フォーム

    コメントは公開で恥ずかしい!! Rcatだけに送りたい人向け


    メンバーシップの説明


    Docker-Composeマネージャー


    【ローカルLLM】バイブコーディング完全ガイド


    【ローカルLLM】自己成長AIエージェントHermesをホスト

    ミニPCにLinuxをインストール


    メンバーシップ特典

     
     
    モノづくりが趣味。 "売ってないなら自分で作ればいいじゃない"をコンセプトに、機械/電気/AI/プログラム/ネットワーク 全部やります。 記事執筆はAI不使用。 ご連絡や利用規約はプロフィール記事参照。

    あなたへのおすすめ