【2024年最終】AMD APUでStable Diffusionを動かす(stable-diffusion-webui編)

# はじめに
[技術チャレンジ部](https://challenge-club.connpass.com/)のとも(Tomo)です。
画像生成AI花盛りなのに、全く試せておらず、素人です。
Dockerも素人です。変なこと言っていたらすいません。
ROCmは公式にはAPU非対応で、記事の内容は無保証です。

# きっかけ
だいぶ前に、Ryzen搭載の廉価ミニPCを買って、得した気分になろうとしました。邪です。
…が、現実は厳しい。起動後数日でリセットを繰り返し、にもかかわらずMemtest86+は完走。メモリ周辺のBIOS設定の変更など色々試したものの改善せず、しばらく放置。
これでは完全に文鎮になってしまう…。少し安くなったCrucialのメモリに交換したところ、症状が改善。
とはいえ、ミニPCの使い道は未定。でも使わないと価値は目減り…。
そこで、BIOS設定の内容を思い出します。APUなのでメインメモリからVRAMを最大16GBまで割り当てられます。これで8GBでは動かないモデルを動かせれば、せめてもの救いになるのでは? (何の)

# 環境
## ミニPC
- APU: AMD Ryzen 7735HS
    - CPUコア: ZEN3+
    - iGPUコア: RDNA2
- メモリ: 32GB
    - BIOS設定で16GBをGPUに割り当て
- SSD: 1TB

## ソフト選択
Radeon動かすなら[ROCm](https://www.amd.com/ja/products/software/rocm.html)、ROCmならまずはLinux、ということで、慣れたUbuntuでROCmを使うことにします。
[ROCmのCompatibility matrix](https://rocm.docs.amd.com/en/latest/compatibility/compatibility-matrix.html)を見て、とりあえず最新のUbuntu 24.04をハイパーバイザー無しでネイティブに、その上に最新のROCm 6.3.1を入れることにします。
今回使ったカーネルはUbuntu 24.04.1の6.8.0-51-generic #52-Ubuntuです。

## 画像生成AI
いろいろあると思いますが、全然分からないので、モデルは聞いたことがあって色々試せそうなStable Diffusionにします。
これを動かすUIも色々あると思いますが、おなじみっぽい[AUTOMATIC1111/stable-diffusion-webui](https://github.com/AUTOMATIC1111/stable-diffusion-webui)を入れてみることにします。

# インストール
## Ubuntu 24.04
AMDなのでプロプライエタリなドライバーは選択せず、Desktop版を普通にインストール。
swapはデフォルトで4GB。後で16GBに増やしました。

## ROCm
[本家](https://rocm.docs.amd.com/en/latest/)には、[各種ソフトのインストール手順](https://rocm.docs.amd.com/projects/install-on-linux/en/latest/)があります。
*recommended for new users*(自分のこと!)と書かれた[Quick startの手順](https://rocm.docs.amd.com/projects/install-on-linux/en/latest/install/quick-start.html)でインストール。
パッケージのサイズは大きいですが、特に迷うことなくインストール完了。
Secure bootが有効な状態でdkmsが走ったため、再起動後、shimで鍵(MOK)の設定が必要でした。不慣れな場合は手順を確認しておいたほうがよいかもです。
[Post-installの章](https://rocm.docs.amd.com/projects/install-on-linux/en/latest/install/post-install.html)があるのを今知りました…特に何もしませんでした。

## stable-diffusion-webui
[AMD向けの大変丁寧な手順](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Install-and-Run-on-AMD-GPUs)があるため、こちらを参照します。
[Docker内で実行する手順](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Install-and-Run-on-AMD-GPUs#running-inside-docker)では、`rocm/pytorch`のDockerイメージが参照されています。
stable-diffusion-webuiは、Python 3.10か3.11あたりが想定されているようで、現状の`rocm/pytorch:latest`はPython 3.10.15だったので、ちょうど良さそうです。
…というわけでDockerで実行することにします。…が、ここから色々起こります。

# 実行とエラー対応
## No module named 'pytorch_lightning.utilities.distributed'
```
ModuleNotFoundError: No module named 'pytorch_lightning.utilities.distributed'
```
というエラーで止まった場合、[こちら](https://github.com/AUTOMATIC1111/stable-diffusion-webui/issues/11458#issuecomment-1609900319)にある、

> just change pytorch_lightning.utilities.distributed to pytorch_lightning.utilities.rank_zero

を手で修正し解決。ROCmの時だけ?(詳細未確認)

## No module named 'timm'
```
ModuleNotFoundError: No module named 'timm'
```

が出た場合は、`pip install timm`でパッケージ追加し解決。


## Illegal seek for GPU arch : gfx1035
```
rocBLAS error: Cannot read /opt/rocm/lib/rocblas/library/TensileLibrary.dat: Illegal seek for GPU arch : gfx1035
```
が出た場合は、`HSA_OVERRIDE_GFX_VERSION=10.3.0`を付けて実行し解決。

## fatal: detected dubious ownership in repository
[Docker内で実行する手順](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Install-and-Run-on-AMD-GPUs#running-inside-docker)では、Docker内で`git clone`する手順になっていますが、Docker外で`git clone`したディレクトリをbind mountすると、ownerが異なりエラーとなるようです。
この場合、Docker内で`git config --global --add safe.directory /dockerx`などで解決。

# 実行手順
…という感じで色々起こるので、どうすればいいか試した結果、以下の手順で行うことにしました。

1. (オプション)`rocm/pytorch`のイメージを`docker pull`
2. stable-diffusion-webuiをDocker外で`git clone`
3. stable-diffusion-webuiを修正(`rank_zero`の件)
4. Pythonパッケージを追加したDockerイメージをビルド
5. (オプション)手元にモデルがあれば設置
6. `docker compose up`で起動
7. ブラウザでアクセス

## (オプション)`rocm/pytorch`のイメージを`docker pull`
71GBと大きいので、事前に取得してみました。気分の問題かと思います。
```shell
docker pull rocm/pytorch:latest
```

## stable-diffusion-webuiをDocker外で`git clone`
```shell
git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git
```

## stable-diffusion-webuiを修正(rank_zeroの件)
ワンライナーは適当なので問題が起こるかもしれません。`git diff`で確認されることをお勧めします。
```shell
find ./stable-diffusion-webui -type f -name "*.py" -exec sed -i -E 's|^(from pytorch_lightning\.utilities\.distributed)(.*)|from pytorch_lightning\.utilities\.rank_zero\2|' {} +
```

## Pythonパッケージを追加したDockerイメージをビルド
`Dockerfile`と`docker-compose.yaml`を設置。どちらも適当です。
```Dockerfile:Dockerfile
FROM rocm/pytorch:latest
COPY ./stable-diffusion-webui/requirements.txt /tmp/requirements.txt
RUN --mount=type=cache,target=/root/.cache/pip \
    python -m pip install --upgrade pip wheel && \
    pip install -r /tmp/requirements.txt timm
```

`docker-compose.yaml`は、[こちら](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Install-and-Run-on-AMD-GPUs)の`docker run`のオプションをベースに作成。不要な項目が含まれているかもしれません。
外部ホストからアクセスしたかったので`network_mode`を`host`にして`--listen`していますので、適宜修正下さい。
`PYTORCH_ROCM_ARCH`と`shm_size`の必要性は不明。

```yaml:docker-compose.yaml
services:
  stable-diffusion-webui:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - ./stable-diffusion-webui:/stable-diffusion-webui
    environment:
      - HSA_OVERRIDE_GFX_VERSION=10.3.0
      - PYTORCH_ROCM_ARCH=gfx1030
    cap_add:
      - SYS_PTRACE
    security_opt:
      - seccomp=unconfined
    devices:
      - /dev/kfd
      - /dev/dri
    group_add:
      - video
    shm_size: 16gb
    ipc: host
    network_mode: host
    working_dir: /stable-diffusion-webui
    entrypoint: /bin/sh -c "test -f ~/.gitconfig || git config --global --add safe.directory /stable-diffusion-webui &&
                python launch.py --listen --precision full --no-half"
```

そして、
```shell
docker compose build
```

## (オプション)手元にモデルがあれば設置
試行錯誤の度に取得するのはいまいちだったので、事前に取得してあるモデルをコピーしました。手元に無ければ初回起動時に取得されますが、大きいので時間がかかります。
```shell
cp v1-5-pruned-emaonly.safetensors ./stable-diffusion-webui/models/Stable-diffusion/
```

## `docker compose up`で起動
```shell
docker compose up -d
docker compose logs -f
```
時間がかかる処理があるのでログで様子を観察。

## ブラウザでアクセス
起動した感じになったら`http://IPアドレス:7860`にアクセス。

# 気づいたこと
デフォルトで入って動いたモデルに1.5の文字が。
stable-diffusion-webuiはStable Diffusion 3.5に[現状未対応?](https://github.com/AUTOMATIC1111/stable-diffusion-webui/discussions/16581)
ということで、次回、[ComfyUI編](https://qiita.com/tomo-v/items/6ef495ece6049c1d9e63)に続く!(年内間に合った!)