はじめに
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で画像生成環境を構築しようとしている人の参考になれば幸いである。


コメント