AWS EC2 GPUインスタンスでStable Diffusionを使う

ローカルPCのGPUで[Stable Diffusion Web UI](https://github.com/AUTOMATIC1111/stable-diffusion-webui)を使って画像生成をしていましたが、高解像度になるとVRAMが足りない・・・このためにビデオカード買うのもなんだかなと思ったので、AWSの[GPUを搭載したEC2インスタンス](https://docs.aws.amazon.com/ja_jp/dlami/latest/devguide/gpu.html)でStable Diffusion Web UIを使ってみました。


# AWS 環境設定

## セキュリティグループの設定
コンソールから「EC2」と検索→クリックし、左タブの**セキュリティグループ**をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635079/3a8df2ba-2fbc-79de-fb2e-ba5d45a46a6b.png)

右上**セキュリティグループを作成**をクリックし、インバウンドルールを以下のように設定します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635079/50092b0c-7af2-ed76-2d0a-f99a89542fed.png" width=100%>


`SSH ポート番号22 0.0.0.0/0` はEC2をAWS コンソール上で接続して操作するのに必要で、
`カスタムTCP ポート番号7860 マイIP`はStable Diffusion Web UIを立ち上げたページにアクセスするのに必要です。


## インスタンス起動&設定

今回は[g5.xlargeインスタンス](https://aws.amazon.com/jp/ec2/instance-types/g5/)を用います。
g5 インスタンスは**AWS NVIDIA A10G Tensor Core GPU**を使用しており、GPUあたり24GBのVRAMが搭載されています。


私は[vCPU制限緩和の申請](https://aws.amazon.com/jp/premiumsupport/knowledge-center/ec2-on-demand-instance-vcpu-increase/)が必要でしたのでそれも行いました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635079/ee319450-75dc-50a3-dbc2-02a208f45d41.png" width=100%>


EC2→制限→制限計算ツールの**インスタンスタイプ**にg5と入れ、現在の制限が4未満だった場合、**g5シリーズのインスタンスを立ち上げることができません**。
画像右下の「オンデマンド制限の引き上げをリクエスト」からvCPU引き上げをリクエストしてください。

### インスタンス設定内容
以下のように設定します。

- OS -> Ubuntu Server 22.04
- instance -> g5.xlarge
- キーペア -> なし（AWSコンソール上からの接続しか使わない為）
- セキュリティグループ -> [セキュリティグループの設定](#セキュリティグループの設定)で作成したもの
- ボリューム -> 必要に応じて(最低でも30GBは欲しい)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635079/4f2713dd-3cea-825f-a64a-1cfa2bf45aa0.png" width=100%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635079/390e25d7-4bf3-26a1-98db-d7a776f760fd.png" width=100%>


起動後、インスタンスを選択し、「接続」から以下画面に飛べるので接続します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635079/79b982a3-875b-2a79-d84b-ad9daca955bb.png" width=100%>


![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3633353037392f38313064316536342d316561302d663862342d3662613.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635079/19c305b5-1f6b-5b70-6f4f-fe697fffe4ed.png)


このように画面コマンドを打てるようになったら成功です。




# Stable Diffusion Web UI動作環境設定

[stable-diffusion-webui-docker](https://github.com/AbdBarho/stable-diffusion-webui-docker)を使って環境を構築します。

## 各種インストール


GCC,Git,Docker,Docker Composeをインストールします。

```bash
$ sudo apt update
$ sudo apt install build-essential
$ gcc --version # gccインストールの確認
$ sudo apt install git
$ sudo apt install docker.io
$ sudo service docker start
$ docker --version # バージョンの確認
$ sudo mkdir -p /usr/local/lib/docker/cli-plugins 
$ export VER=2.15.1 # 環境変数 VERにDocker Composeのバージョンを入れる(20230321時点では2.15.1が最新)
$ sudo curl \
  -L https://github.com/docker/compose/releases/download/v${VER}/docker-compose-$(uname -s)-$(uname -m) \
  -o /usr/local/lib/docker/cli-plugins/docker-compose
$ sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose 
$ sudo ln -s /usr/local/lib/docker/cli-plugins/docker-compose /usr/bin/docker-compose 
$ docker-compose --version # docker compose バージョンの確認
```

Nvidia Driver,nvidia-container-toolkitをインストールします。
DRIVER_VERSION変数に入れるバージョンは[NvidiaのDriverバージョン確認](https://www.nvidia.com/Download/index.aspx?lang=en-us)をしてから入力します。


![Official Drivers _ NVIDIA.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635079/7741e8b7-9f00-9832-c247-e2b9320dd8c8.png)
入力の結果**525.85.12**でしたので、その値を入れています。




```
$ BASE_URL=https://us.download.nvidia.com/tesla
$ DRIVER_VERSION=525.85.12 # ドライバのバージョン確認が必要
$ curl -fSsl -O $BASE_URL/$DRIVER_VERSION/NVIDIA-Linux-x86_64-$DRIVER_VERSION.run
$ sudo sh NVIDIA-Linux-x86_64-$DRIVER_VERSION.run
```

この後画面が切り替わり以下のようになれば問題無しです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635079/18c2246c-ba1d-7faf-a037-3642dd1e74c3.png" width=100%>

2つほど警告が出ますがそのまま進めればインストール完了
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635079/5f31d876-3f7a-0ba4-59d7-d579e44a537f.png" width=100%>




Docker上でもGPUを認識させるために[nvidia-container-toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html)も入れます。



```
$ 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
$ sudo nvidia-ctk runtime configure --runtime=docker
$ sudo systemctl restart docker
$ nvidia-smi # GPU認識確認
```

`nvidia-smi`で以下のような画面になったらNvidiaのドライバーが入っています。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635079/61120ea5-0b03-443d-8abe-dc441e7f30fe.png" width=100%>






## stable-diffusion-webui-dockerセットアップ&起動





```bash
$ git clone https://github.com/AbdBarho/stable-diffusion-webui-docker
$ cd stable-diffusion-webui-docker
```

プルしてきた`docker-compose.yml`に一部追記します。
`CLI_ARGS=`に`--no-half-vae --precision full --no-half`を書き加えます。
```bash
$ vi docker-compose.yml
```
```vim:docker-compose.yml
auto: &automatic
   <<: *base_service
   profiles: ["auto"]
   build: ./services/AUTOMATIC1111
   image: sd-auto:49
   environment:
     - CLI_ARGS=--allow-code --medvram --xformers --enable-insecure-extension-access --api --no-half-vae --precision full --no-half # 引数を追加する
```


docker composeでモデルのダウンロードやセットアップを行います。
初回実行時は10分弱程度時間が掛かります。
```bash
$ sudo docker compose --profile download up --build
$ sudo docker compose --profile auto up --build
```

EC2コンソール接続の左下 パブリックIPに`:7860`を付け足してブラウザのURL入力欄に張り付けて読み込みます。


![Stable Diffusion.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635079/d5f94477-7329-aba4-8e40-94f39e0e9361.png)


このようにアクセスできたら成功です！（画像はGenerate後の結果）
Generateボタンを押せばEC2のGPUを使用して画像生成が始まります。詳しい操作方法はいろんなページを調べてみてください。




# その他

AWS CLI+S3で以下のようなこともしてみました。
`aws configure`でアクセスキーの入力をしています。必要な権限を持っているIAMユーザーのキーをお使いください。

## 他モデルの使用

S3に他モデルをアップロードして、AWS CLIを用いてデータのやり取りをします。


適当なバケットを作りそこにモデルやLora等アップロードし、syncコマンドでEC2インスタンスのボリュームへコピーします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635079/f028de29-cc0d-ee3b-698f-254c84813071.png" width=100%>

```bash
$ sudo apt install awscli
$ aws --version # aws cliバージョン確認
$ aws configure # アクセスキー設定

# chmodで権限を変更してからSync
$ cd data
$ sudo chmod 777 StableDiffusion
$ aws s3 sync s3://xxxxxxxxxxxx/expansion/model/ ./StableDiffusion
$ sudo chmod 777 Lora
$ aws s3 sync s3://xxxxxxxxxxxx/expansion/lora/ ./Lora
```

この後は再度[stable-diffusion-webui-dockerセットアップ&起動](#stable-diffusion-webui-dockerセットアップ&起動)の`sudo docker compose`の2行を実行しなおします。



## 生成画像をS3へ保存


生成画像はoutputフォルダに入っているので、S3の指定のバケットURIへSyncすればOKです。


```bash
$ aws s3 sync ./output s3://xxxxxxxxxxxx/generated-photos/
```

保存完了！
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635079/d342efbc-d061-ddac-0379-d8e5d128a719.png" width=100%>


# まとめ

EC2のGPU搭載インスタンスでStable Diffusionを使い画像を生成することができました。
ローカルPCのGPUを使わないので、画像生成中にゲームもできますし便利です！

VRAMも24GBあるため、高い解像度の画像生成もできそうです。
720x1280の出力では11GB程VRAMを消費していました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635079/ca7f1900-cc03-3af7-b2c9-bb9919700615.png" width=100%>



ここまで見ていただきありがとうございました。何か改善点や間違い等あればご指摘いただければと思いますm(__)m

## 参考ページ


https://docs.nvidia.com/datacenter/tesla/tesla-installation-notes/index.html

https://hirooka.pro/ubuntu-22-04-nvidia-container-toolkit-docker/

https://kacfg.com/aws-ec2-docker/


https://zenn.dev/karaage0703/articles/bf86fe4946417b