Macbook Air M2(mem16GB)で環境作ってStable-Diffusionを試す（2022/8/24版）

# この記事は古くなったので新しい記事へどうぞ 【9/6加筆】 
-　参考ページとしていた magnusviri氏による一時的なapple-silicon-mps-supportブランチはメイン（？）の方にマージされました。
-　2022年9月時点でのインストール方法については以下の記事をどうぞ
 - [Macbook Air M2（mem16GB）のローカル環境でStable Diffusionを動かす（2022.9.6版）](https://qiita.com/hevo2/items/c9c611a5f918d36732f3)

# 長いのでまとめると
- 試行錯誤しながら書いたメモをコピペ。読みづらいのはご容赦ください。
- Macbook Air M2(メモリ16GB)、（おそらく）GPUを使用、学習モデルはsd-v1-4.ckptを使用。
- 初めての実行で以下のコマンドを入力後、だいたい1時間（57分くらい）で6つの画像が出力されました。
- % python scripts/txt2img.py --prompt "a photograph of an cat into a bottle" --plms
![grid-0000.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47569/75511720-c91f-db2e-a11e-e7d50fb36b98.png)

# 参考ページ
- Stable-Diffusion公式Git
	- https://github.com/CompVis/stable-diffusion
- ~~Stable-Diffusionのapple-silicon-mps-supportブランチ~~
	- - ~~https://github.com/magnusviri/stable-diffusion/tree/apple-silicon-mps-support~~
- 学習データの配布サイト
	- https://huggingface.co/CompVis/stable-diffusion-v-1-4-original


# gitは必須。コンパイル用にRustも必要
``` zsh
% brew install git rust
```


# minicondaでやってみた
``` zsh
% brew install miniconda
% conda -V
4.12.0
% conda init zsh
% source ~/.zshrc
% conda install -c conda-forge onnx
```
- sourceで読み込んだ後、現在minicondaの(base)環境にいることを確認してください。シェルのプロンプトに(base)と書かれているはずです。
- anacondaを使用すればこんなに苦労しない可能性があります。（要検討）
- base環境のときに、onnxをcondaパッケージでインストールしておくこと。pipでonnxをソースからインストールしようとするとこけます（バージョン依存関係と思われますが面倒なので追ってません）。


# stable-diffusionのM1/M2Macbook用ブランチをクローン
``` zsh
% git clone https://github.com/magnusviri/stable-diffusion.git
% cd stable-diffusion
% git checkout apple-silicon-mps-support
```

# 設定ファイル確認。書き換え（imwatermarkエラー対策）
- 「environment-mac.yaml」の内容を確認して、「- pip: 」エントリーに並んでいるmodule群の中に、「invisible-watermark」がなかったら追加する
- たとえば、「- opencv-python」の行のすぐ下に「- invisible-watermark」と追加するとよいかも。
- 「importError: cannot import name 'WatermarkEncoder' from 'imWatermark'」というエラーが出たら、その原因は「invisible-watermark」がライブラリが入っていないためだと思われます。「imwatermark」ライブラリではないようです。・・・罠かな？


# 設定ファイルを使って環境構築。そして切替
``` zsh
% conda env create -f environment-mac.yaml
% conda activate ldm
```

- 「/opt/homebrew/Caskroom/miniconda/base/envs/ldm」というディレクトリ作って環境を構築するので、もしこの環境構築途中でエラーで止まったら、このldmディレクトリを消して再度実行すること
- ldm環境に切り替えるとシェルのプロンプトの表示が(base)から(ldm)に変わりました


# 別途ダウンロードした学習モデルを定位置に配置
```
% mkdir ./models/ldm/stable-diffusion-v1/
% mv ~/Downloads/sd-v1-4.ckpt ./models/ldm/stable-diffusion-v1/models.ckpt
```


# txt2img.pyスクリプト実行でこけるので手で書き換え
- Patchコマンドを使ってもいいけど、今回は手で書き換えました。具体的には、カレントフォルダの「Patchfile」の中身を参照
- 対象：
	- /opt/homebrew/Caskroom/miniconda/base/envs/ldm/lib/python3.10/site-packages/torch/nn/functional.py の2511行目あたり
	- パスは微妙に違うかもしれないので自分で探すこと

変更前
```
return torch.layer_norm(input, normalized_shape, weight, bias, eps, torch.backends.cudnn.enabled)
```

変更後（inputほにゃららの一部分だけ書き換え）
```
return torch.layer_norm(input.contiguous(), normalized_shape, weight, bias, eps, torch.backends.cudnn.enabled)
```

# さあ実行しよう
```
% python scripts/txt2img.py -e "a photograph of a cat into a bottle" -plms
```

# かかる時間
- Macbook Air M2(メモリ16GB)、GPUを使用、学習モデルはsd-v1-4.ckptを使用。画像6枚1セットの生成でだいたい1時間コース
- アクティビティモニタで内蔵GPUを使っている様子が見えるが、まだ余力はありそう。
- メモリを18GBくらい使っているのでSSDへのSwapが処理速度低下の主要因かな。

# TODO
- minicondaではなくてanacondaで環境を構築するともっと楽な可能性がある
- ~~torchのnightly buildを使った上で、ソースコードの書き換えを行うことでMacbookのGPUを使えるらしいので今度試す~~
- 倍精度ではなく単精度のを使うともっと早いかも。すでにoptimizeされたbranchがいくつかありそう？　今度試す。

# 知りたいこと
- plmsオプションってなあに？