ROCm7.2から10.1.0へ!Radeon 780MでComfyUIをDocker運用するまでの全記録

はじめに

AMDの内蔵GPUでStable Diffusionを動かす。

言葉にすれば簡単だが、実際にはROCm、PyTorch、GPUアーキテクチャ、Pythonの依存関係など、さまざまな問題が立ちはだかる。

今回使用したのは、MINISFORUM UM790 Proに搭載されたAMD Radeon 780M Graphics。OSはLinux Mint 22.3である。

もともとホスト側ではROCm 7.2系を使用していたが、既存環境を壊さずに新しい構成を試すため、Docker上にROCm 10.1.0とPyTorch 2.14.0の環境を構築した。

結果として、従来500秒以上かかっていた1024×1024ピクセルの画像生成が、約130秒で完了するようになった。

もちろん、最初から順調だったわけではない。GPUのアクセス権限、DynamicVRAMのエラー、Dockerコンテナ内のユーザー権限、ワークフローJSONの所有権など、いくつもの問題に遭遇した。

この記事では、実際に使用したDockerfileと起動スクリプトを交えながら、その構築過程と解決方法を記録する。

1. 使用環境

項目 構成
PC MINISFORUM UM790 Pro
CPU AMD Ryzen 9 7940HS
GPU AMD Radeon 780M Graphics
GPUアーキテクチャ gfx1103
OS Linux Mint 22.3
ホスト側ROCm 7.2系
Docker側ROCm 10.1.0
Docker側PyTorch 2.14.0+rocm10.1.0
Python 3.12.3
ComfyUI 0.43.0
ComfyUIフロントエンド 1.57.6

Radeon 780MはRDNA 3世代の内蔵GPUであり、専用のVRAMを搭載したディスクリートGPUではない。

今回の環境では、ComfyUIのログ上で次のように認識されている。

AMD arch: gfx1103
Total VRAM 30031 MB, total RAM 60062 MB
Device: cuda:0 AMD Radeon 780M Graphics : native

ここで表示されるVRAM容量は、内蔵GPUが利用できるメモリとして認識された値であり、30GBの専用VRAMが物理的に搭載されているという意味ではない。

2. なぜDockerを選んだのか

ホスト側には、すでにROCm 7.2系で動作するComfyUI環境が存在していた。

PyTorchとROCmの組み合わせを変更する際、既存のPython仮想環境を直接書き換えると、それまで動いていた環境まで壊してしまう可能性がある。

そこで、ROCm 10.1.0とPyTorch 2.14.0をDockerコンテナ内に分離することにした。

ComfyUI本体やモデル、ワークフローはホスト側のディレクトリをバインドマウントして共有する。

ただし、DockerでPython環境を分離しても、GPUデバイスやホスト側のファイルに対するアクセス権限は別途管理する必要がある。

3. Dockerイメージを構築する

3.1 使用したDockerfile

今回使用したのは、ROCm 10.1.0とPyTorch 2.14.0を組み合わせたベースイメージである。

ComfyUIの依存関係をインストールする際、ROCm版PyTorchが別のビルドに置き換わらないよう、制約ファイルを利用した。

Dockerfile.comfyui-rocm101

FROM rocm/pytorch:rocm10.1.0_ubuntu24.04_py3.12_pytorch_release_2.14.0

# ComfyUIの依存関係をインストール
# ROCm版PyTorchは既存のバージョンを維持する
RUN apt-get update \
    && apt-get install -y --no-install-recommends git \
    && rm -rf /var/lib/apt/lists/*

RUN git clone --depth 1 \
      https://github.com/Comfy-Org/ComfyUI.git \
      /tmp/comfyui-src \
    && python3 -m pip freeze \
      | grep -Ei '^(torch|torchvision|torchaudio)==' \
      > /tmp/torch-constraints.txt \
    && python3 -m pip install --no-cache-dir \
      -r /tmp/comfyui-src/requirements.txt \
      -c /tmp/torch-constraints.txt \
    && python3 -c 'import torch; assert torch.__version__.startswith("2.14.0+rocm10.1.0"), torch.__version__' \
    && rm -rf /tmp/comfyui-src /tmp/torch-constraints.txt

WORKDIR /workspace/ComfyUI

3.2 PyTorchのバージョンを維持する工夫

まず、インストール済みのPyTorch関連パッケージのバージョンを制約ファイルに記録する。

python3 -m pip freeze \
  | grep -Ei '^(torch|torchvision|torchaudio)==' \
  > /tmp/torch-constraints.txt

続いて、制約ファイルを指定してComfyUIの依存関係をインストールする。

python3 -m pip install --no-cache-dir \
  -r /tmp/comfyui-src/requirements.txt \
  -c /tmp/torch-constraints.txt

さらに、インストール後にPyTorchのバージョンを検証する。想定外のバージョンに変更されていた場合は、Dockerイメージのビルドを失敗させる仕組みである。

3.3 Dockerイメージのビルド

docker build \
  -t comfyui-rocm101:local \
  -f "$HOME/Apps/Sources/Dockerfile.comfyui-rocm101" \
  "$HOME/Apps/Sources"

なお、このDockerfileはビルド時点のComfyUIリポジトリから依存関係を取得するため、厳密な再現性を求める場合はComfyUIのコミットIDや依存パッケージのバージョンを固定する必要がある。

4. DockerからRadeon 780Mを利用する

AMD GPUをDockerコンテナ内から利用するには、GPUデバイスへのアクセスを許可する必要がある。

--device /dev/kfd
--device /dev/dri

今回の環境では、さらに以下のオプションを指定した。

--ipc=host
--network=host

GPUデバイスへのアクセスには、Linuxのグループ権限も関係する。

今回のホスト環境では、renderグループのGIDが992、videoグループのGIDが44だった。

ただし、GIDは環境によって異なるため、固定値ではなく起動時に取得する方式とした。

RENDER_GID=$(getent group render | cut -d: -f3)
VIDEO_GID=$(getent group video | cut -d: -f3)

Docker起動時には以下を指定する。

--group-add "$RENDER_GID" \
--group-add "$VIDEO_GID"

コンテナ内にrenderという名前のグループが存在しなくても、数値のGIDを指定すればよい。

5. PyTorchからGPUを認識できるか確認する

ComfyUIのコンテナを起動した状態で、PyTorchからGPUの認識状況を確認した。

docker exec comfyui-rocm101-local python3 -c '
import torch
print("PyTorch:", torch.__version__)
print("HIP:", torch.version.hip)
print("GPU:", torch.cuda.get_device_name(0))
print("Available:", torch.cuda.is_available())
'

実際の結果は以下のとおり。

PyTorch: 2.14.0+rocm10.1.0
HIP: 7.16.26385
GPU: AMD Radeon 780M Graphics
Available: True

Radeon 780Mが正常に認識された。

ROCm版PyTorchでもGPU関連のAPIにはtorch.cudaという名前が使われる。そのため、AMD GPUであってもtorch.cuda.is_available()で確認できる。

なお、ここで表示されるHIPのバージョン番号と、ROCmディストリビューションのリリース番号は同一ではない。

6. DynamicVRAMのエラーに遭遇

GPUの認識には成功したものの、画像生成時に次のエラーが発生した。

MemoryError: VBAR allocation failed

エラーの発生箇所は、ComfyUIのDynamicVRAMに関連するcomfy_aimdo.model_vbar.ModelVBARだった。

そこで、ComfyUIの起動オプションに以下を追加した。

--disable-dynamic-vram

今回の環境では、これによって画像生成を正常に完了できるようになった。

最終的に使用した主なオプションは以下のとおり。

--disable-dynamic-vram \
--disable-async-offload \
--disable-pinned-memory \
--fp16-vae

これは今回の環境における動作実績であり、すべてのAMD GPU環境に適した設定とは限らない。

また、ComfyUIの起動ログにはDynamicVRAM無効化オプションが将来削除される可能性についての警告も表示されていた。将来のバージョンでは設定の見直しが必要になるかもしれない。

7. 起動スクリプトの作成

毎回長いDockerコマンドを入力するのは面倒なので、起動スクリプトを作成した。

このスクリプトは、Dockerイメージの存在確認、コンテナ起動、GPU認識確認、Firefoxの起動、終了時のコンテナ停止までを自動化する。

保存先は以下とした。

~/Apps/Sources/comfyui-rocm101.sh

以下は実際の運用構成をもとにした掲載用スクリプトである。既存コンテナを誤って停止しないためのSTARTEDフラグを追加している。

#!/usr/bin/env bash
set -Eeuo pipefail

IMAGE="comfyui-rocm101:local"
APP_DIR="$HOME/Apps/ComfyUI"
DOCKERFILE="$HOME/Apps/Sources/Dockerfile.comfyui-rocm101"
CONTAINER="comfyui-rocm101-local"
PORT=8189
FIREFOX_PID=""
STARTED=0

cleanup() {
    trap - EXIT INT TERM

    echo
    echo "[ComfyUI] shutting down..."

    if [[ -n "$FIREFOX_PID" ]]; then
        kill "$FIREFOX_PID" 2>/dev/null || true
        wait "$FIREFOX_PID" 2>/dev/null || true
    fi

    if [[ "$STARTED" == 1 ]]; then
        docker stop -t 10 "$CONTAINER" >/dev/null 2>&1 || true
    fi
}

trap cleanup EXIT
trap 'exit 130' INT
trap 'exit 143' TERM

[[ -f "$APP_DIR/main.py" ]] || {
    echo "ComfyUI not found: $APP_DIR/main.py"
    exit 1
}

command -v docker >/dev/null
command -v curl >/dev/null
command -v firefox >/dev/null

if ! docker image inspect "$IMAGE" >/dev/null 2>&1; then
    echo "[ComfyUI] Building ROCm 10.1.0 image..."
    docker build \
        -t "$IMAGE" \
        -f "$DOCKERFILE" \
        "$HOME/Apps/Sources"
fi

if docker container inspect "$CONTAINER" >/dev/null 2>&1; then
    echo "Container already exists: $CONTAINER"
    exit 1
fi

RENDER_GID=$(getent group render | cut -d: -f3)
VIDEO_GID=$(getent group video | cut -d: -f3)

echo "[ComfyUI] Starting ROCm 10.1.0..."

docker run -d --rm \
    --name "$CONTAINER" \
    --device /dev/kfd \
    --device /dev/dri \
    --user "$(id -u):$(id -g)" \
    --group-add "$RENDER_GID" \
    --group-add "$VIDEO_GID" \
    --ipc=host \
    --network=host \
    -e AMD_SERIALIZE_KERNEL=3 \
    -e HOME=/tmp \
    -e XDG_CACHE_HOME=/tmp/comfyui-cache \
    -v "$APP_DIR:/workspace/ComfyUI" \
    -w /workspace/ComfyUI \
    "$IMAGE" \
    python3 main.py \
        --listen 127.0.0.1 \
        --port "$PORT" \
        --disable-dynamic-vram \
        --disable-async-offload \
        --disable-pinned-memory \
        --fp16-vae

STARTED=1

echo "[ComfyUI] Waiting for startup..."

READY=0

for i in $(seq 1 120); do
    if curl -fsS "http://127.0.0.1:$PORT/" >/dev/null 2>&1; then
        READY=1
        break
    fi

    if [[ "$(docker inspect -f '{{.State.Running}}' \
        "$CONTAINER" 2>/dev/null || true)" != true ]]; then
        echo "[ComfyUI] Container exited."
        docker logs "$CONTAINER" 2>&1 | tail -80 || true
        exit 1
    fi

    sleep 1
done

if [[ "$READY" != 1 ]]; then
    echo "[ComfyUI] Startup timeout."
    docker logs "$CONTAINER" 2>&1 | tail -80 || true
    exit 1
fi

echo "[ComfyUI] READY!"

docker exec "$CONTAINER" python3 -c '
import torch
print("PyTorch:", torch.__version__)
print("HIP:", torch.version.hip)
print("GPU:", torch.cuda.get_device_name(0))
print("Available:", torch.cuda.is_available())
'

echo "[Firefox] Opening ComfyUI..."

firefox --no-remote -P comfyui \
    "http://127.0.0.1:$PORT/" &

FIREFOX_PID=$!

wait "$FIREFOX_PID" || true

echo "[Firefox] Closed."

掲載用の改良版全体については、別途動作確認が必要である。

また、コンテナに–rmを指定しているため、異常終了するとコンテナが自動削除され、後からdocker logsでログを取得できない場合がある。トラブル調査時には一時的に–rmを外すとよい。

Firefox専用プロファイルについて

スクリプトでは以下のコマンドを使用している。

firefox --no-remote -P comfyui \
  "http://127.0.0.1:8189/"

これはcomfyuiという名前のFirefoxプロファイルが作成済みであることを前提としている。

未作成の場合は、Firefoxのプロファイル管理から事前に作成しておく必要がある。

8. 1024×1024画像生成の実測結果

今回のワークフローは、単純な一段階生成ではない。

512×512ピクセルで画像を生成し、Latent Upscaleで2倍に拡大した後、再度サンプリングする構成である。

処理 設定
初期生成 512×512
初期サンプリング 36ステップ
Latent Upscale 2倍
二段階目サンプリング 18ステップ
最終解像度 1024×1024
VAEデコード Tiled VAE

実測結果は以下のとおり。

環境 生成時間
従来環境 500秒超
Docker+ROCm 10.1.0 約130秒

500秒を基準にすると、約3.85倍の速度に相当する。

ただし、これは筆者の環境で観測した結果であり、厳密に条件を統一したベンチマークではない。

ROCmだけでなく、PyTorch、ComfyUI、VRAM管理などの構成も異なるため、性能向上をROCmのバージョン変更だけによるものと断定することはできない。

9. Dockerで生成した画像がroot所有になる

画像生成が成功した後、ファイル管理上の問題が発生した。

最初はDockerコンテナをrootユーザーで実行していたため、生成画像の所有者とグループがrootになっていた。

これを解決するため、Docker起動時にホスト側ユーザーのUIDとGIDを指定した。

--user "$(id -u):$(id -g)"

GPUへのアクセス権限を維持するため、renderとvideoのグループも追加する。

--group-add "$RENDER_GID" \
--group-add "$VIDEO_GID"

さらに、コンテナ内で使用するホームディレクトリとキャッシュディレクトリを指定した。

-e HOME=/tmp \
-e XDG_CACHE_HOME=/tmp/comfyui-cache

変更後、新しく生成した画像ファイルの所有者とグループがホスト側ユーザーのものになっていることを確認した。

これにより、生成画像を通常のユーザー権限で管理できるようになった。

10. ワークフローが一覧に表示されるのに開けない

コンテナの実行ユーザーを変更した後、別の問題が発生した。

保存済みワークフローは一覧に表示されるものの、クリックしても開けない。

さらに、画像生成を実行すると次のエラーが表示された。

Prompt has no outputs

当初は出力ノードが欠落したように見えた。

しかし、ファイルの所有権を調べると、以前rootで実行していた際に作成されたJSONが残っていた。

-rw------- 1 root root ... workflow.json

一方、ComfyUIはUID 1000の一般ユーザーとして実行されていた。

つまり、rootだけが読み取れるワークフローJSONにアクセスできなかったのである。

解決方法

ホスト側で、ワークフローディレクトリの所有権を修正した。

sudo chown -R "$(id -u):$(id -g)" \
  "$HOME/Apps/ComfyUI/user/default/workflows"

修正後、保存済みワークフローをComfyUIのGUIから正常に開けることを確認した。

生成画像の所有権も正常化されていたため、ワークフローの読み込みと生成ファイルの管理という2つの問題が解消した。

なお、Prompt has no outputsは一般には出力ノードが存在しない場合にも発生する。今回のケースでは、ワークフローを正常に読み込めない状態とあわせて発生していた。

11. トラブルシューティングまとめ

症状 原因・対処
GPUにアクセスできない /dev/kfd、/dev/dri、グループ権限を確認
renderグループを指定できない ホスト側のGIDを数値で指定
VBAR allocation failed –disable-dynamic-vramで回避
VIDEO_GIDが未定義 getent group videoでGIDを取得
生成画像がroot所有になる –userでホスト側UID/GIDを指定
ワークフローが開けない root所有のJSONの所有権を修正
Prompt has no outputs 出力ノードとワークフローの読み込み状態を確認

今回の経験で重要だったのは、問題をROCm、PyTorch、GPUデバイス、VRAM管理、Linuxのファイル権限に分けて切り分けることだった。

GPUの動作が正常でも、ファイルのアクセス権限によってComfyUIの操作が失敗することがある。

逆に、ファイル権限の問題を解決するためにROCmやPyTorchを変更する必要はない。

おわりに

Radeon 780Mのような内蔵GPUでも、DockerとROCmを適切に組み合わせれば、ComfyUIによる1024×1024ピクセルの画像生成を実用的な時間で実行できた。

今回の環境では、従来500秒以上かかっていた処理が約130秒で完了した。

もちろん、GPUを認識させるだけでは終わらない。

DynamicVRAMのエラー、GPUデバイスのアクセス権限、Dockerコンテナ内のユーザー管理、保存済みワークフローの所有権など、実際の運用で初めて見えてくる問題もあった。

それでも、既存のROCm 7.2環境を維持しながら、新しいROCm 10.1.0環境を構築できたのは大きな収穫だった。

AMD内蔵GPUでも、まだまだできることはある。

この記事が、同じようにRadeon 780Mで画像生成環境を構築しようとしている人の参考になれば幸いである。

コメント

タイトルとURLをコピーしました
~