Stable DiffusionをSingularityで動かす


## はじめに
最近話題のStable Diffusionのインストールです。僕的にはStable DiffusionはGoogle翻訳以来のインパクトでした。イラストの制作の仕事は一変してしまうのでしょうね。この記事の目的はSingularityを使用して手間をかけずにStable Diffusionをインストールすることです。一度、defファイルを作ってしまえば同じ環境を用意できます。Google Colaboratoryを使用すると簡単にStable Diffusionを実行できます。しかし、モジュールの再ロードや実行時間の制約等の制限が多いためオンラインではなくローカルで動作させたいのです。一から導入するのは大変ですがインストールしてみてはいかがでしょうか。

## 環境
- ubuntu22.04(64bit)
- RAM8G(swapで16G)
- GPU NVIDIA GeForce RTX 1080
- singularity:3.10.2
- python3
- pip

## メモリは16G以上で実行すること
Stable Diffusionのコードを実行した時、PCがフリーズしたので、原因を探るのに１日消費してしまいました。原因は本体のメモリ容量でした。RAM 8Gにswap 8Gを追加して正常に動作しました。本体メモリが少ない人は注意しましょう。ここではswapの説明はしません。

## Singularityをインストールする
ubuntu22.04にSingularityをインストールします。↓を参考にしました。
>[SingularityをUbuntu 18.04 LTSにインストールしてNGC コンテナーを使う](https://server-gear.com/shop/index.php/blog/singularity/)

- CUDA Toolkit 11.7
- go1.18.4 linux/amd64
- singularity-ce version 3.10.2

go言語のバージョンは[singularity](https://github.com/sylabs/singularity/releases)のリリースに書かれているバージョンに合わせると良いでしょう。

## hugfaceに登録する
Stable Diffusionをローカル環境で動かすためには[Hugging Face](https://huggingface.co/)のアカウントを作る必要があります。

### hugfaceに登録
https://huggingface.co/blog/stable_diffusion

登録した、アカウント名とパスワードはあとで使用します。メモしましょう。

### 次にAccess Tokensを入手
https://huggingface.co/settings/tokens

アクセストークンもメモしましょう。




## stable-diffusion環境のディレクトリ構成
ホームディレクトリ下にmkdirで`diffusion`ディレクトリを作成します。`diffusion`ディレクトリ下に`models`ディレクトリと`work`ディレクトリを作成してください。`models`ディレクトリにckptファイルを保存します。`work`ディレクトリでコードを実行します。
```bash
mkdir diffusion
cd diffusion
mkdir -p models/sd1/
mkdir work
```
tree構造は以下のようになります。
```bash
tree -d -L 3 diffusion/

.
└── diffusion
    ├── models
    │   ├── sd1
    │   └── wd13
    └── work
        ├── logs
        ├── optimizedSD
        └── outputs

8 directories
```

## defファイルを用意する
NGCのpytorchコンテナを使用して、Stable Diffusion環境を作ります。最新バージョンは安定しない様なので、`pytorch:21.12-py3`を使用します。condaは使用しないで、pipだけでインストールします。

↓を参考にしました。
>[PIP環境でStable Diffusionを動作させる](https://zenn.dev/ihashiguchi/articles/e00b59b5a4481c)

VRAMが8GBと少ないので、フォーク版Stable Diffusionをインストールします。

こちらがリポジトリです
>[basujindal/stable-diffusion](https://github.com/basujindal/stable-diffusion)

defファイルを用意します。nano等のエディタを使用して
`pytorch.def`としてセーブします。

```docker
#docker dockerhub
Bootstrap: docker
#
From: nvcr.io/nvidia/pytorch:21.12-py3
#
%post
    #apt
    apt update 
    apt -y upgrade
    DEBIAN_FRONTEND=noninteractive apt-get install -y git git-lfs tzdata
    git lfs install
    #pip
    pip install albumentations==0.4.3 opencv-python==4.6.0.66 pudb==2019.2 \
    imageio==2.9.0 imageio-ffmpeg==0.4.2 pytorch-lightning==1.4.2 \
    omegaconf==2.1.1 test-tube>=0.7.5 streamlit>=0.73.1 einops==0.3.0 \
    torch-fidelity==0.3.0 transformers==4.19.2 torchmetrics==0.6.0 kornia==0.6 
    pip install -e git+https://github.com/CompVis/taming-transformers.git@master#egg=taming-transformers 
    pip install -e git+https://github.com/openai/CLIP.git@main#egg=clip
    git clone https://github.com/basujindal/stable-diffusion
    cd stable-diffusion
    git clone https://huggingface.co/CompVis/stable-diffusion-v-1-4-original
    pip install -e .
#
%environment
    export LC_ALL=C
#
%labels
    Author botchan
    Version v1.0.0
```
## defファイルをビルドする
`diffusion`ディレクトリにsifファイルを作成します。ターミナルで
```bash
sudo singularity build pytorch_21.12-sd1.sif pytorch.def
```
と打ちます。ビルドの途中で、アカウント名とアクセストークンを問われます。メモしたアカウント名とアクセストークンを入力しましょう。数十分、ビルドが終わるまで待ちます。

### モデルファイルの用意
モデルファイルを`models`ディレクトリにhuggingfaceからダウンロードします。アカウント名とパスワードが必要になります。urlの<アカウント名>と<アカウントパスワード>に適宜に入力してください。
```
wget https://<アカウント名>:<アカウントパスワード>@huggingface.co/CompVis/stable-diffusion-v-1-4-original/resolve/main/sd-v1-4.ckpt -O models/sd1/model.ckpt
```

## 実行コードの用意
`work`ディレクトリに移動します。ビルドでインストールされてた`stable-diffusion/optimizedSD`を`work`ディレクトリにコピーしましょう。
```bash
cd work
singularity exec --nv ../pytorch_21.12-sd1.sif cp -r /stable-diffusion/optimizedSD/ optimizedSD/
```

## txt2img.pyコードの実行
準備が整いました。`work`ディレクトリで以下のコードを実行します。

```bash
singularity exec --nv ../pytorch_21.12-sd1.sif python optimizedSD/optimized_txt2img.py --H 512 --W 512 --seed 27 --n_iter 2 --n_samples 10 --ddim_steps 50 --prompt "hanging gardens in medieval Europe" --ckpt ../models/sd1/model.ckpt
```
`outputs`フォルダ内にの画像が生成されれば成功です。


## 出力結果
![test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/690633/a04028be-7108-87c7-72af-2ae2d123eba5.png)
こんな簡単に描けてしまうなんてすごいですね！