Linux ROCm経由でのRyzen 5600G GPUによるStable Diffusion WebUIの利用

# 画像生成AI Stable Diffusion
画像生成AIのStable Diffusionの統合環境である[Stable Diffusion WebUI(AUTOMATIC1111版)](https://github.com/AUTOMATIC1111/stable-diffusion-webui)を、AMDのLinux用GPGPU実行環境[ROCm](https://github.com/RadeonOpenCompute/ROCm)を使ってRyzen 5600GのGPUで動かしてみました。

Ryzen 5600Gでは512x512画像1枚生成するのにCPUで2分弱かかるのに対して、GPUでは1分弱なので2倍の速さで生成できます。外付けGPUのGeforce 3060で生成すると4秒ぐらいなのであまり実用的ではないのですが、Ryzen APUでのROCmの活用例として参考にどうぞ。

BIOSの変更が不要な方法を公開しました(2024/4/24)。

https://qiita.com/asfdrwe/items/7ba1aa2251b3e34c9f8a

## 動作確認した機器構成
|種類|内容|
|----------|---------------------------------|
|CPU       | Ryzen 5600G                     |
|マザーボード| ASRock B450M-HDV (BIOS 4.70)    |
|メモリ     | CFD W4U3200CS-16G (16GB×2=32GB) |
|OS        |Fedora 38 (Native実行、wsl2では動かない) |

## 準備
### VRAMを手動で割り当て
通常はGPUが使用するVRAMをOSが自動で割り当ててくれるのですが、今回の場合うまく動かないので、UEFIで事前に手動で16GB(または8GB)割り当ててください。

マザーボードがASRock B450M-HDVのBIOS 4.70の場合、
Advanced→AMD CBS→NBIO Common Options→GFX Configurationとたどり
iGPU ConfigurationをAUTOからUMA_SPECIFIEDにし、新しく出てきた
UMA Frame Buffer Sizeを16Gにしてください。

他のマザーボードでも同様の設定があるはずなので、マザーボードの説明書を見て手動でVRAMを割り当ててください。

### Linuxを起動しVRAMを確認
Linuxを起動してください。

`dmesg`コマンドでカーネルログを見てVRAMに16GB割り当てられていているか確認してください。

```
$ dmesg | grep amdgpu
...
[    3.892557] [drm] amdgpu: 16384M of VRAM memory ready
[    3.892558] [drm] amdgpu: 7923M of GTT memory ready.
...
```

`free`コマンドでも使用可能なメモリが16GB減っているか確認できます。

自動で割り当てている場合
```
               total        used        free      shared  buff/cache   available
Mem:        32200736     4484088    12980408      177152    14736240    27085884
Swap:        8388604           0     8388604
```

手動で16GB割り当てた場合
```
               total        used        free      shared  buff/cache   available
Mem:        16226344     2297556    11507368       25220     2421420    13612388
Swap:        8388604           0     8388604
```

### 必要なパッケージのインストール
`dnf`コマンドでrocminfo等のrocm関係のパッケージをインストールしてください。

```
$ sudo dnf install rocminfo rocm-smi rocm-device-libs
```


`git`も使うので入っていなければインストールしてください。
```
$ sudo dnf install git
```

### /dev/kfdのパーミッション設定
ROCmでは/dev/kfd経由でGPUにアクセスします。一般ユーザからアクセス可能にするために`usermod`コマンドでROCmを使用するユーザ(今回はasfdrwe)をrenderグループに入れてください。

```
$ sudo usermod -aG render $USER
```

group、group-ファイルを見てrenderグループに入っているか確認してください。

```
$ grep $USER /etc/group*
/etc/group:wheel:x:10:asfdrwe
/etc/group:video:x:39:asfdrwe
/etc/group:render:x:105:asfdrwe
/etc/group:asfdrwe:x:1000:
/etc/group-:wheel:x:10:asfdrwe
/etc/group-:video:x:39:asfdrwe
/etc/group-:asfdrwe:x:1000:
```

### rocminfoでのROCmの動作確認
`rocminfo`コマンドでROCmの実行環境の確認ができます。正常に動作するか確認してください。

`/dev/kfd`のパーミッションが不適切だと実行に失敗します。失敗するなら`ls -l /dev/kfd`でrenderグループが読み書きできるか確認して`sudo chmod g+rw /dev/kfd`等でパーミッションを設定してください。

```
$ rocminfo
ROCk module is loaded
=====================    
HSA System Attributes    
=====================    
Runtime Version:         1.1
System Timestamp Freq.:  1000.000000MHz
Sig. Max Wait Duration:  18446744073709551615 (0xFFFFFFFFFFFFFFFF) (timestamp count)
Machine Model:           LARGE                              
System Endianness:       LITTLE                             

==========               
HSA Agents               
==========               
*******                  
Agent 1                  
*******                  
  Name:                    AMD Ryzen 5 5600G with Radeon Graphics
  Uuid:                    CPU-XX                             
  Marketing Name:          AMD Ryzen 5 5600G with Radeon Graphics
  Vendor Name:             CPU                                
  Feature:                 None specified                     
  Profile:                 FULL_PROFILE                       
  Float Round Mode:        NEAR                               
  Max Queue Number:        0(0x0)                             
  Queue Min Size:          0(0x0)                             
  Queue Max Size:          0(0x0)                             
  Queue Type:              MULTI                              
  Node:                    0                                  
  Device Type:             CPU                                
  Cache Info:              
    L1:                      32768(0x8000) KB                   
  Chip ID:                 0(0x0)                             
  ASIC Revision:           0(0x0)                             
  Cacheline Size:          64(0x40)                           
  Max Clock Freq. (MHz):   3900                               
  BDFID:                   0                                  
  Internal Node ID:        0                                  
  Compute Unit:            12                                 
  SIMDs per CU:            0                                  
  Shader Engines:          0                                  
  Shader Arrs. per Eng.:   0                                  
  WatchPts on Addr. Ranges:1                                  
  Features:                None
  Pool Info:               
    Pool 1                   
      Segment:                 GLOBAL; FLAGS: FINE GRAINED        
      Size:                    32200752(0x1eb5830) KB             
      Allocatable:             TRUE                               
      Alloc Granule:           4KB                                
      Alloc Alignment:         4KB                                
      Accessible by all:       TRUE                               
    Pool 2                   
      Segment:                 GLOBAL; FLAGS: KERNARG, FINE GRAINED
      Size:                    32200752(0x1eb5830) KB             
      Allocatable:             TRUE                               
      Alloc Granule:           4KB                                
      Alloc Alignment:         4KB                                
      Accessible by all:       TRUE                               
    Pool 3                   
      Segment:                 GLOBAL; FLAGS: COARSE GRAINED      
      Size:                    32200752(0x1eb5830) KB             
      Allocatable:             TRUE                               
      Alloc Granule:           4KB                                
      Alloc Alignment:         4KB                                
      Accessible by all:       TRUE                               
  ISA Info:                
*******                  
Agent 2                  
*******                  
  Name:                    gfx90c                             
  Uuid:                    GPU-XX                             
  Marketing Name:          AMD Radeon Graphics                
  Vendor Name:             AMD                                
  Feature:                 KERNEL_DISPATCH                    
  Profile:                 BASE_PROFILE                       
  Float Round Mode:        NEAR                               
  Max Queue Number:        128(0x80)                          
  Queue Min Size:          64(0x40)                           
  Queue Max Size:          131072(0x20000)                    
  Queue Type:              MULTI                              
  Node:                    1                                  
  Device Type:             GPU                                
  Cache Info:              
    L1:                      16(0x10) KB                        
    L2:                      1024(0x400) KB                     
  Chip ID:                 5688(0x1638)                       
  ASIC Revision:           0(0x0)                             
  Cacheline Size:          64(0x40)                           
  Max Clock Freq. (MHz):   1900                               
  BDFID:                   2304                               
  Internal Node ID:        1                                  
  Compute Unit:            7                                  
  SIMDs per CU:            4                                  
  Shader Engines:          1                                  
  Shader Arrs. per Eng.:   1                                  
  WatchPts on Addr. Ranges:4                                  
  Features:                KERNEL_DISPATCH 
  Fast F16 Operation:      TRUE                               
  Wavefront Size:          64(0x40)                           
  Workgroup Max Size:      1024(0x400)                        
  Workgroup Max Size per Dimension:
    x                        1024(0x400)                        
    y                        1024(0x400)                        
    z                        1024(0x400)                        
  Max Waves Per CU:        40(0x28)                           
  Max Work-item Per CU:    2560(0xa00)                        
  Grid Max Size:           4294967295(0xffffffff)             
  Grid Max Size per Dimension:
    x                        4294967295(0xffffffff)             
    y                        4294967295(0xffffffff)             
    z                        4294967295(0xffffffff)             
  Max fbarriers/Workgrp:   32                                 
  Pool Info:               
    Pool 1                   
      Segment:                 GLOBAL; FLAGS: COARSE GRAINED      
      Size:                    524288(0x80000) KB                 
      Allocatable:             TRUE                               
      Alloc Granule:           4KB                                
      Alloc Alignment:         4KB                                
      Accessible by all:       FALSE                              
    Pool 2                   
      Segment:                 GROUP                              
      Size:                    64(0x40) KB                        
      Allocatable:             FALSE                              
      Alloc Granule:           0KB                                
      Alloc Alignment:         0KB                                
      Accessible by all:       FALSE                              
  ISA Info:                
    ISA 1                    
      Name:                    amdgcn-amd-amdhsa--gfx90c:xnack-   
      Machine Models:          HSA_MACHINE_MODEL_LARGE            
      Profiles:                HSA_PROFILE_BASE                   
      Default Rounding Mode:   NEAR                               
      Default Rounding Mode:   NEAR                               
      Fast f16:                TRUE                               
      Workgroup Max Size:      1024(0x400)                        
      Workgroup Max Size per Dimension:
        x                        1024(0x400)                        
        y                        1024(0x400)                        
        z                        1024(0x400)                        
      Grid Max Size:           4294967295(0xffffffff)             
      Grid Max Size per Dimension:
        x                        4294967295(0xffffffff)             
        y                        4294967295(0xffffffff)             
        z                        4294967295(0xffffffff)             
      FBarrier Max Size:       32                                 
*** Done ***             
```

ROCmからAgent 1はNameがRyzen 5 5600GのCPUで、Agent 2はNameがgfx90cのGPUとして認識されています。

## Stable Diffusion WebUIのインストール
### venvでPythonの仮想環境を構築
以下`~/`で作業します。作業場所はどこでも問題ないはずです。

まず`~/stablediffusion`にvenvで仮想環境を構築します。

```
$ cd ~
$ python3 -m venv stablediffusion
```

### ROCm対応pytorchをインストール
`~/stablediffusion`に移動し仮想環境を有効にします。

```
$ cd stablediffusion
$ . bin/activate
```

先にpipやwheelのアップデートをしておきます。
```
$ python -m pip install --upgrade pip wheel
```

通常のpytorchや必要なパッケージを一回インストールし、pytorchをアンインストールしたあとROCm対応pytorchを入れます。とりあえず2023/7/15時点でrocm5.4.2用が最新のようなのでそれを入れます。

```
$ pip install --upgrade diffusers transformers scipy ftfy
$ pip uninstall torch
$ pip install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/rocm5.4.2
```

### Stable Diffusion WebUIをインストール
`git`コマンドでStable Diffusion WebUIをインストールします。

```
$ git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui
```

## Stable Diffusion WebUIの実行
まず`stable-diffusion-webui`に移動します。

```
$ cd stable-diffusion-webui
```

環境変数`HSA_OVERRIDE_GFX_VERSION`と`DEVICE`を設定してください。そのままではpytorchが5600GのGPUであるgfx90cに対応していないので、gfx900(vega10)として動作させるために`HSA_OVERRIDE_GFX_VERSION`を9.0.0に設定しています([LLVMによるとgfx90cとgfx900の命令セットは同じらしい](https://llvm.org/docs/AMDGPU/AMDGPUAsmGFX900.html))。`DEVICE`はhip([ROCmの標準API](https://github.com/ROCm-Developer-Tools/HIP))にします(`DEVICE`は設定しなくても動きますが)。

```
$ export HSA_OVERRIDE_GFX_VERSION=9.0.0
$ export DEVICE=hip
```

Stable Diffusion WebUIを`webui.sh`で実行します。

```
$ ./webui.sh
```

初回はStable Diffusion WebUIに必要なパッケージのインストールがされるので時間がかかります。次回以降はもっと早く起動します。正常に実行できている場合 http://127.0.0.1:7860 にアクセスするよう表示されるはずです。

```
...
Running on local URL:  http://127.0.0.1:7860

To create a public link, set `share=True` in `launch()`.
...
```

### Stable Diffusion WebUIで画像生成
ブラウザで http://127.0.0.1:7860 にアクセスしてください。Stable Diffusion WebUIが表示されるはずです。

最初にSetting→Live Previewsで『Show live previews of the created image』のチェックをはずして設定を保存してください。そのままだと生成が遅くなります。

次にtxt2imgタブの入力欄にsky等適当なプロンプトを入れて右のGenerateボタンを押せば画像が生成されるはずです。

あとは自由にプロンプトを与えて画像を生成してみてください。

### 設定がおかしい場合のエラー例
手動でVRAMを割り当てていない場合512MBしか使えないので、モデルを読み込めないエラーを出すはずです。

```
...
torch.cuda.OutOfMemoryError: HIP out of memory. Tried to allocate 30.00 MiB (GPU 0; 512.00 MiB total capacity; 365.53 MiB already allocated; 56.00 MiB free; 392.00 MiB reserved in total by PyTorch) If reserved memory is >> allocated memory try setting max_split_size_mb to avoid fragmentation.  See documentation for Memory Management and PYTORCH_HIP_ALLOC_CONF


Stable diffusion model failed to load
Applying attention optimization: Doggettx... done.
```

HSA_OVERRIDE_GFX_VERSIONを設定していない場合、rocmblasがこんなエラーを出すはずです。

```
...

rocBLAS error: Cannot read /home/asfdrwe/stablediffusion/lib64/python3.11/site-packages/torch/lib/rocblas/library/TensileLibrary.dat: Illegal seek
./webui.sh: 241 行:  8588 中止                  (コアダンプ) "${python_cmd}" "${LAUNCH_SCRIPT}" "$@"
```

これらのエラーが出た場合はそれぞれ必要な設定ができているか確認してください。

### CPUでStable Diffusion WebUIを実行する場合
`webui.sh`は環境変数`COMMANDLINE_ARGS`で制御できます。次のオプションを指定すればCPUでStable Diffusion WebUIを実行できます。

```
$ export COMMANDLINE_ARGS="--use-cpu all --no-half --no-half-vae --skip-torch-cuda-test"
$ ./webui.sh
```

### その他の設定
Stable Diffusion WebUIには[様々なオプション](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Command-Line-Arguments-and-Settings)があって、環境変数や`COMMANDLINE_ARGS`経由で指定できるのですが、`--upcast-sampling--opt-sub-quad-attention`については遅くなる上にメモリの消費も増えます。

`export COMMANDLINE_ARGS=--upcast-sampling--opt-sub-quad-attention`の場合
```
Time taken: 1m 4.52s

Torch active/reserved: 3726/3956 MiB, Sys VRAM: 4020/8192 MiB (49.07%)
```

`COMMANDLINE_ARGS`に何も指定しない場合
```
Time taken: 56.68s

Torch active/reserved: 3542/3700 MiB, Sys VRAM: 3764/8192 MiB (45.95%)
```

`--no-half --no-half-vae`の場合は生成できなくなるはずです。

何かいいオプションがあれば教えてください。

## 参考ページ
- https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Install-and-Run-on-AMD-GPUs
- https://rentry.co/sd-nativeisekaitoo
- https://www.gabriel.urdhr.fr/2022/08/28/trying-to-run-stable-diffusion-on-amd-ryzen-5-5600g/
- https://g-pc.info/archives/32244/
- https://www.coelacanth-dream.com/posts/2020/06/22/amdgpu-gpuid-mean/
- https://blog.ingage.jp/entry/2022/07/12/080000