Conda を使わないで、venv だけで Stable Diffusion を使うことができたので、ここに記録しておく。 試した環境は M1の macOS と Linux(Ubuntu) + CUDA です。
生成される画像は 512 x 512 ですが、ここでは 320 x 320 にリサイズして載せています。
M1/M2 Mac で StableDiffusion する方法は PyTorch モデルをそのまま使うのではなく、CoreML用に変換して StableDiffusion する方法があります。 この方法であれば、実用に耐えうる処理速度が得られるそうです。 詳しくはこちら https://huggingface.co/docs/diffusers/main/en/optimization/coreml をご覧ください。
やり方はここ How to use Stable Diffusion in Apple Silicon (M1/M2)に書いてあります。
macOS のバージョンは Ventura 13.4.1 です。Python のバージョンは以下のとおり。
$ python3 --version
Python 3.9.6
ここでは Terminal で Bash を使っている。(デフォルトの Zsh でもとくに変わりはないはず。)
適当なディレクトリでまずは、diffuers という名前で venv 環境を用意して activate します。
$ python3 -m venv diffusers
$ source diffusers/bin/activate
(diffusers) $
そして、このvenv環境に必要なモジュールを入れます。
(diffusers) $ pip install torch torchvision torchaudio
(diffusers) $ pip install diffusers transformers ftfy accelerate
touch 関連は、以下のページで Stable(2.0.1) / Mac / Pip / Python / Default を選択した結果表示されたコマンドです。
バージョン指定なしでインストールしたので、pip list して、どのバージョンが入ったのかを確認します。
(diffusers) $ pip list
Package Version
------------------ --------
accelerate 0.20.3
certifi 2023.5.7
charset-normalizer 3.1.0
diffusers 0.17.1
filelock 3.12.2
fsspec 2023.6.0
ftfy 6.1.1
huggingface-hub 0.15.1
idna 3.4
importlib-metadata 6.7.0
Jinja2 3.1.2
MarkupSafe 2.1.3
mpmath 1.3.0
networkx 3.1
numpy 1.25.0
packaging 23.1
Pillow 9.5.0
pip 23.1.2
psutil 5.9.5
PyYAML 6.0
regex 2023.6.3
requests 2.31.0
safetensors 0.3.1
setuptools 58.0.4
sympy 1.12
tokenizers 0.13.3
torch 2.0.1
torchaudio 2.0.2
torchvision 0.15.2
tqdm 4.65.0
transformers 4.30.2
typing_extensions 4.7.0
urllib3 2.0.3
wcwidth 0.2.6
zipp 3.15.0
あとは、Huggingface のオフィシャルページに説明のあるコードを多少手直しした main.py を用意。
from diffusers import DiffusionPipeline
model_id = "runwayml/stable-diffusion-v1-5"
pipe = DiffusionPipeline.from_pretrained(model_id)
pipe = pipe.to("mps")
# Recommended if your computer has < 64 GB of RAM
pipe.enable_attention_slicing()
prompt = "A cup of coffee, plain background, art by Hokusai."
image = pipe(prompt).images[0]
image.save("a-cup-of-coffee.png")
実行します。
(diffusers) $ python main.py
初回実行時はモデルのダウンロード処理などがあるので、回線速度にもよりますが相当に時間がかかります。 二回目実行時は、それがないので、そこそこ速いですが、それでもこの環境(M1 MacBook Air, 8G)では、 10分程度は時間がかったように思います。
デフォルトではステップ数 ( num_inference_steps ) が 50 になるようです。これを減らすことで(品質を犠牲に)処理時間を減らせるはずです。 詳細は後述。
あとで、Linux + CUDA でも試すつもりなので、seed 値を固定できるコードに書きかえた main.py:
import torch
from diffusers import DiffusionPipeline
model_id = "runwayml/stable-diffusion-v1-5"
seed = 45
device = "mps"
prompt = "A cup of coffee, plain background, art by Hokusai."
pipe = DiffusionPipeline.from_pretrained(model_id)
pipe = pipe.to(device)
# Recommended if your computer has < 64 GB of RAM
pipe.enable_attention_slicing()
generator = torch.Generator(device).manual_seed(seed)
with torch.autocast("cpu"):
image = pipe(prompt, guidance_scale=7.5, generator=generator).images[0]
image.save("a-cup-of-coffee_2.png")
生成された画像はこれ:
pipe する部分のコードを変更します。 オプションで num_inference_steps=15 を追加。
with less denoising steps: https://huggingface.co/blog/stable_diffusion
with torch.autocast("cpu"):
image = pipe(prompt, guidance_scale=7.5, num_inference_steps=15, generator=generator).images[0]
これで、デフォルトの50から15に処理ステップが減ります。その結果...
(diffusers) $ time python main.py
real 2m43.878s
user 0m11.868s
sys 0m45.493s
3分弱で処理が完了しました。どんな絵ができたんでしょうか?
うーん。たぶん denoising 15回ではまだ「早すぎ」だったんでしょうか。
seed 値を 50 に 15ステップで実行して生成した画像はこちら:
こちらは大丈夫でした。
では、次にこのコードを Linux(Ubuntu)環境でも実行してみます。
OS に CUDA の環境はできていることが前提として話を進めます。
GPU は RTX 3060 12G を使用。
準備されている環境は以下の通り。
$ nvidia-smi
Thu Jun 28 06:22:25 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 GeForce RTX 3060 On | 00000000:01:00.0 Off | N/A |
| 36% 28C P8 13W / 170W| 1MiB / 12288MiB | 0% Default |
| | | N/A |
+-----------------------------------------+----------------------+----------------------+
$ nvcc --version
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2023 NVIDIA Corporation
Built on Mon_Apr__3_17:16:06_PDT_2023
Cuda compilation tools, release 12.1, V12.1.105
Build cuda_12.1.r12.1/compiler.32688072_0
macOS のときと同じように diffusers という名前で venv をつくりました。
その上で以下のモジュールをその venv 環境に追加:
(diffusers) $ pip install diffusers==0.12.1 transformers==4.19.2 ftfy accelerate
とくに touch のモジュールは明示してインストールしていない。たぶん、依存するものとして一緒に入ったのでしょう。 pip list して、できあがった環境を確認。
(diffusers) $ pip list
Package Version
------------------------ ----------
accelerate 0.20.3
certifi 2023.5.7
charset-normalizer 3.1.0
cmake 3.26.4
diffusers 0.12.1
filelock 3.12.2
fsspec 2023.6.0
ftfy 6.1.1
huggingface-hub 0.15.1
idna 3.4
importlib-metadata 6.7.0
Jinja2 3.1.2
lit 16.0.6
MarkupSafe 2.1.3
mpmath 1.3.0
networkx 3.1
numpy 1.25.0
nvidia-cublas-cu11 11.10.3.66
nvidia-cuda-cupti-cu11 11.7.101
nvidia-cuda-nvrtc-cu11 11.7.99
nvidia-cuda-runtime-cu11 11.7.99
nvidia-cudnn-cu11 8.5.0.96
nvidia-cufft-cu11 10.9.0.58
nvidia-curand-cu11 10.2.10.91
nvidia-cusolver-cu11 11.4.0.1
nvidia-cusparse-cu11 11.7.4.91
nvidia-nccl-cu11 2.14.3
nvidia-nvtx-cu11 11.7.91
packaging 23.1
Pillow 9.5.0
pip 22.0.2
psutil 5.9.5
PyYAML 6.0
regex 2023.6.3
requests 2.31.0
setuptools 59.6.0
sympy 1.12
tokenizers 0.12.1
torch 2.0.1
tqdm 4.65.0
transformers 4.19.2
triton 2.0.0
typing_extensions 4.7.0
urllib3 2.0.3
wcwidth 0.2.6
wheel 0.40.0
zipp 3.15.0
実行するのは以下のコード main.py:
基本的に M1 mac で実行したコードと同じですが、cuda を使うように一部書きかえています。
import torch
from diffusers import DiffusionPipeline
model_id = "runwayml/stable-diffusion-v1-5"
seed = 45
device = "cuda"
prompt = "A cup of coffee, plain background, art by Hokusai."
pipe = DiffusionPipeline.from_pretrained(model_id, revision="fp16", torch_dtype=torch.float16)
pipe = pipe.to(device)
# Recommended if your computer has < 64 GB of RAM
pipe.enable_attention_slicing()
generator = torch.Generator(device).manual_seed(seed)
with torch.autocast("cuda"):
image = pipe(prompt, guidance_scale=7.5, generator=generator).images[0]
image.save("a-cup-of-coffee_3.png")
実行します。(時間を計測)
(diffusers) $ time python main.py
real 0m26.045s
user 0m22.063s
sys 0m3.261s
約30秒で生成できました。 さすがに GPU は速いですね。
生成された画像:
Diffusers ライブラリを使うメリットの一つは簡単にモデルをチェンジできることです。 プロンプトと seed 値は固定して、モデルだけを変えて画像を生成してみます。
model_id = "CompVis/stable-diffusion-v1-4"
生成された画像:
model_id = "stabilityai/stable-diffusion-2-1-base"
生成された画像:
venv のみで簡単に macOS と Linux で Stable Diffusion を使うことができました。
ちょっと試す程度なら M1 mac もありですが、本格的に使うにはやはり GPU が必要です。 とはいえ、一番非力な M1 mac で試しただけなので、 もし、M2 Pro とか Max ならばもっと速く生成できるのかもしれません。