[StableDiffusion on GCP]GCEでも新GPUのNVIDIA L4がしたい!

<img width=640 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91710/891d202c-5aa9-1b5c-de51-403bde765cc2.png" />

StableDiffusionを使いたい、けどPCは買いたくない、どうせなら古いT4じゃなくて新しいL4が使いたい
よろしい、ならばクラウドでマシン立てれば良いよね、ってことでGCEで`Stable-diffusion-webui automatic1111` を立てたので手順を書いておきます。

### GPUどれ使えば良いの問題
自分でマシンを買うならビデオカードはNVIDIAの`4090X`が一番良いらしく、`4080`とか`3080`とか番号でだいたいスペックの良し悪しさは見当がつきますしたくさんの記事があります。

ところがサーバー用のGPUとなるとGPUが使えるインスタンス情報や価格表はあるものの
`T4`, `A100`, `V100`, `k80`, `P100` ... どれを使えば良いのかよくわかりません。

(↓一応公式のドキュメントはあるが、、、)

https://cloud.google.com/compute/gpus-pricing?hl=ja

https://cloud.google.com/compute/docs/gpus?hl=ja



一番安いのは `T4` ですしググると出てくるのは`T4`がほとんどです。
(以前、gstreamerでGKEでGPUエンコードするプログラムを動かした時もT4を使っていました。というかGKEではT4のみだったはず)

しかし他のGPUでコスパが良くてそこそこ使える物はないのでしょうか。

## サーバー用GPUの状況まとめ記事があった!


大変ありがたいことにこちらの記事にスペックがまとまっていました。
世代別と性能のリストが載っているので全体像が掴みやすいです。
ハイエンドはH100(まだ普及してない) -> A100 -> V100 -> P100 -> K80 の流れですね。

https://qiita.com/yukoba/items/10d0ba3fb1d19a6ab6a5


## T4よりもL4を使ってみたい

> 廉価なGPUの系列はT4→A10→L4になっています。

上の方が新しい世代なので、普段は `L4` を使えは良さそうです。

# GCEでインスタンスを立てる

さて、T4であれば `Deep Learning VM` というドライバやら一通り入っている公式のVMがあるんですが、これのドライバのバージョンが少し古くて使えません。 (L4は530が必要) 
なので `Debian11` で自分で環境を作る必要があります。

## 課金を有効にしてGPU割り当てをする

あらかじめプロジェクトの課金設定と、IAM -> 割り当て　からGPUの割り当て数を1にして申請しておきます。
用途は `For machine larning` としておいたら数分くらいで承認されました。

フィルタ項目は 割り当て -> GPUs(all region) で項目を選択し、右上の「割り当てを編集」ボタンを押すと申請できます。(少し分かりづらい)
<img width=480 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91710/98233681-7436-a84f-16f0-0c7adb51d796.png">


## ファイアウォールを開ける

7860ポートを自分のIPだけ開けるルールを追加します。

## インスタンスを作成する

`Compute Engine` からインスタンス作成を始めます。
GPU選択が分かりづらいのでスクショ貼っときます。

### インスタンスタイプは GPUタブから選ぶ

まずはリージョンより先にすぐ下の「マシンの構成」のGPUタブを選んで `NVIDIA L4` を選択しておきます。
そうするとリージョンを選択したときに対応しているかいないかがわかります。

リージョンはかなり限られるので、`us-central1-a` (もしくはb) が良いかと思います。
起動してみるとGPUがリソース枯渇していることがよくあります。

<img width=480 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91710/22468af5-86ed-b619-6f39-f8cff717b583.png" />

まだ設定は続きます。

### ブートディスクからDebianを選択

ブートディスクの変更からOSとディスク容量を設定します。
OSは `Deep Learning VM` ではなく `Debian 11` にします。
要領はすぐに足りなくなるので100GB以上にします。

<img width=480 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91710/01b1e11f-6895-1d42-c005-1173e5529348.png" />

あとは先ほどファイアフォールに追加したネットワークラベルを適用しておきます。

# インストール手順

やること自体は少ないですが、ハマると時間が溶けます😭

## 依存パッケージ

基本的にはパッケージマネジャーで管理します。

```shell
$ sudo apt-get update
$ sudo apt-get install build-essential

### これを入れないと nvidia-smi しても認識されない
### カーネルがアップデートされたらこちらも忘れずに!
$ sudo apt-get install linux-headers-$(uname -r)

$ sudo apt-get install apt-file
$ sudo apt-file update
$ sudo apt-get install -y software-properties-common
$ sudo apt-add-repository contrib
```

## docker を入れる

docker と compose ブラグインをインストールします。
`docker-compose` は公式のプラグインに取り込まれたようです。
この辺りはしょっちゅう変わる気がするので下手にぐぐるより素直に公式の手順に従いましょう。

https://docs.docker.com/engine/install/debian/

## NVIDA ドライバー (CUDA)インストール

nvidiaのドライバーをインストールします。
ググるとドライバーをウェブサイトからインストールする手順が多いですが、nvidiaのパッケージを使います。

公式の物凄くわかりづらいインストール手順があるのでそれに従いましょう。
なんかびっくりするほど見辛くてわかりづらいですが、やっていることは下記のコマンドだけなんです。

(↓わかりづらい公式ペーシなので次のリンクを参照)

https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#debian

こっちは環境を選択していくとコマンドを生成してくれます。
バージョンはすぐに変わるのでむしろここをみた方が良いです。

https://developer.nvidia.com/cuda-downloads?target_os=Linux&target_arch=x86_64&Distribution=Ubuntu&target_version=22.04&target_type=deb_network

:::note info
Debian12の場合は以下を追加します
sudo vim /etc/apt/sources.list
```
deb http://deb.debian.org/debian/ bookworm main contrib non-free non-free-firmware
deb-src http://deb.debian.org/debian/ bookworm main contrib non-free non-free-firmware
```
:::

```shell
sudo apt-key del 7fa2af80
wget https://developer.download.nvidia.com/compute/cuda/repos/debian11/x86_64/cuda-keyring_1.0-1_all.deb
sudo dpkg -i cuda-keyring_1.0-1_all.deb
sudo apt-get -y install cuda
```

## nvidia-docker2を入れる

サイトによっては `nvidia-container-toolkit` だったりしますが、`nvidia-docker2` をパッケージインストールします。

公式ぺーじはここですが、、

https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html#installing-on-ubuntu-and-debian

結局これを叩けばOK

```shell
distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
      && curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
      && curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \
            sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
            sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt update
sudo apt install -y nvidia-docker2
```

## Python 3.11.3

stable-diffusionを動かすだけならpythonインストールは不要だが(dockerに入っているので)、ツール類で使うので入れておく。

```shell
$ wget https://www.python.org/ftp/python/3.11.3/Python-3.11.3.tgz
$ tar xvf Python-3.11.3.tgz
$ cd Python-3.11.3/
$ ./configure --enable-optimizations
$ make altinstall -j 8
```

## stable-diffusion-webui-dockerを起動する

```shell
git clone https://github.com/AbdBarho/stable-diffusion-webui-docker
cd stable-diffusion-webui-docker
docker compose --profile download up --build
docker compose --profile auto up --build
```

### アクセスして確認

ブラウザから `グローバルIP:7860` でアクセスできればOK

<img width=480 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91710/50c39ff8-a82a-f425-2948-02d1fd828a68.png" />

# おまけ

データを置くディレクトリがローカル版と少し違うので参考まで。

### モデルなどのインストール

modelはここにおきます。

```shell
cd stable_diffusion/stable-diffusion-webui-docker/data/StableDiffusion
```

controlnetのモデルはここ。

```shell
cd stable_diffusion/stable-diffusion-webui-docker/data/config/auto/extensions/sd-webui-controlnet/models

sudo wget https://huggingface.co/lllyasviel/ControlNet-v1-1/resolve/main/control_v11p_sd15_canny.pth
sudo wget https://huggingface.co/lllyasviel/ControlNet-v1-1/resolve/main/control_v11f1p_sd15_depth.pth
sudo wget https://huggingface.co/lllyasviel/ControlNet-v1-1/resolve/main/control_v11p_sd15_openpose.pth
sudo wget https://huggingface.co/lllyasviel/ControlNet-v1-1/resolve/main/control_v11p_sd15_seg.pth
sudo wget https://huggingface.co/lllyasviel/ControlNet-v1-1/resolve/main/control_v11p_sd15_softedge.pth
```

出力した画像はここ

```shell
$ ls -l ~/stable-diffusion-webui-docker/output

drwxr-xr-x 2 root root 4096 Jun 16 15:43 extras
drwxr-xr-x 6 root root 4096 Jun 18 11:45 img2img
drwxr-xr-x 4 root root 4096 Jun 18 07:40 txt2img
```

img2img などでバッチ処理する場合、入力先と出力先を自分で指定できるので、docker-compose.yml にマウント情報を追記しておくと良いでしょう。

```yaml:docker-compose.yml
version: '3.9'

x-base_service: &base_service
    ports:
      - "7860:7860"
    volumes:
      - &v1 ./data:/data
      - &v2 ./output:/output
      - &v2 ./movies:/stable-diffusion-webui/movies
      # ↑ ここを追加
```

LoRaとかLycorisとかembemdedingとかはdataフォルダの下におきます。

```shell
ls -l ~/stable-diffusion-webui-docker/data

drwxr-xr-x 2 root root 4096 Jun 13 11:49 Lora
drwxr-xr-x 2 root root 4096 Jun 13 11:49 LyCORIS
drwxr-xr-x 2 root root 4096 Jun 13 11:49 VAE
drwxr-xr-x 2 root root 4096 Jun 14 01:07 embeddings
```



# トラブルシューティング : 再起動したらGPUを認識しなくなった😢

`libcudann8` を入れたりなんやかんやしているとGPUを認識しなくなることがあります。

```shell
$ sudo nvidia-smi
NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running.

```

そんな場合は一度アンインストールして再インストールすると治ります。

```shell
# アンインストール
$ sudo apt-get --purge remove nvidia-*
$ sudo apt-get --purge remove cuda-*
$ sudo apt-get --purge remove nvidia-docker2
$ sudo apt-get --purge remove libcudnn8
$ sudo apt-get autoremove
```

autoremove までやると完全に削除できます。

ドライバなどをインストール

```shell
$ sudo apt-get install linux-headers-$(uname -r)
$ sudo apt-get -y install cuda
$ sudo apt-get install nvidia-docker2

# 念のため再起動
$ sudo reboot
```

これでGPUを認識してくれます。

```shell
$ sudo nvidia-smi
Sun Jun 18 05:19:44 2023
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 530.30.02              Driver Version: 530.30.02    CUDA Version: 12.1     |
|-----------------------------------------+----------------------+----------------------+
| GPU  Name                  Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf            Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                                         |                      |               MIG M. |
|=========================================+======================+======================|
|   0  NVIDIA L4                       On | 00000000:00:03.0 Off |                    0 |
| N/A   63C    P8               18W /  75W|      0MiB / 23034MiB |      0%      Default |
|                                         |                      |                  N/A |
+-----------------------------------------+----------------------+----------------------+

+---------------------------------------------------------------------------------------+
| Processes:                                                                            |
|  GPU   GI   CI        PID   Type   Process name                            GPU Memory |
|        ID   ID                                                             Usage      |
|=======================================================================================|
|  No running processes found                                                           |
+---------------------------------------------------------------------------------------+
```

カーネルバージョンが上がった場合は古い物は削除しておくと空き容量の節約になります。

```shell
# カーネルバージョンを確認
$ uname -r

# インストールされているカーネルを確認
$ dpkg --get-selections |grep linux

# 削除
$ sudo apt-get --dry-run autoremove --purge linux-{headers,image}-5.10.0-22
```

## すみません。去年10月は「StableDiffusionはまだまだ使えない」とか言ってました😅

新しい技術や話題のものを試すときによくあることでずか、
新しすぎる技術は少し試してみて、「まだまだ実用にならない」「エラーばがりで使い物にならない」と判断してしまうことがよくあります。

実は去年の10月頭にGoogle ColabでStableDiffusionを試していて、
「まあこんなもんか」と思ってました。
そのときに作った画像がこちら↓

![00001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91710/a2858d94-a594-5929-d324-9c7d3bc66ebf.png)


まだ WebUIとかもなくパラメータの存在も知らず、ただ `school girl` とか入れて何回か回してまともに出てきたのがこれでした。
どうやってこんな品質の画像を実用化するんだろうか、と。

で、今回Deforumで適当に作った画像がこれです↓

<img width=640 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91710/891d202c-5aa9-1b5c-de51-403bde765cc2.png" />

まだまだ、ひまわりの背丈が短かったり調整できそうなところも多いですが、割と簡単にこのクオリティのものができゃいます。
再現してみたい方は以下のパラメータでできると思います。

key|value
---|---
model|anything-v4-5
positive prompt|masterpiece, best quality, cute girl with calm expression, ahoge., shorcut brown hair, walking to forward, full body,  profile, left foot forward,  white onepiece,  big straw hat, surrounded by sunflowers, Afterglow,
negative prompt|EasyNegativeV2:1.2, nsfw, nude
seed|2403522789