画像生成 AI の C++ 実装である stable-diffusion.cpp と、その Python バインディングを紹介します。
stable-diffusion.cpp
LLM では PyTorch ベースの transformers ライブラリに対して、C++ で実装された llama.cpp があります。
同様に、画像生成では PyTorch ベースの diffusers ライブラリに対して、C++ で実装されたのが stable-diffusion.cpp です。
SD 1.x/2.x/XL/3/3.5, FLUX.1 dev/schnell に対応しています。
stable-diffusion.cpp は、llama.cpp と同じ ggml というライブラリを使用しています。CUDA や ROCm (HIP) などには ggml で対応しています。
自分でビルドしなくても、バイナリが配布されています。
Windows で Radeon を使用している場合、WebUI 系では FLUX.1 の生成速度が十分でないため、記事執筆時点では stable-diffusion.cpp が最速だと思われます。
使用方法
コマンドとしてモデルやプロンプトを指定して画像を生成します。
sd -m v1-5-pruned-emaonly.safetensors -p "a lovely cat"
Radeon RX 7600 XT (HIP SDK 5.5.1) での生成時間(モデル読み込みを除く): 16.10s (1.49it/s)
モデルの自動ダウンロード機能はないため、Hugging Face などから自分でダウンロードする必要があります。
FLUX.1
FLUX.1 は量子化した GGUF が用意されています。
これによりメモリ使用量を削減することができます。
sd --diffusion-model flux1-schnell-q4_k.gguf --vae ae.safetensors --clip_l clip_l.safetensors --t5xxl t5xxl_fp16.safetensors -p "a lovely cat holding a sign says 'flux.cpp'" --cfg-scale 1.0 --sampling-method euler --steps 4
Radeon RX 7600 XT (HIP SDK 5.5.1) での生成時間(モデル読み込みを除く): 23.68s (2.99s/it)
使い方の詳細は、公式ドキュメントを参照してください。
Python バインディング
llama.cpp に対して llama-cpp-python があるように、stable-diffusion.cpp にも stable-diffusion-cpp-python があります。
pip でのインストール時に stable-diffusion.cpp をビルドする仕組みになっています。そのため事前にビルド環境を準備する必要があります。
Windows での Radeon (HIP) では問題があります。解決策は以下の Issue を参照してください。
メリット
stable-diffusion.cpp はコマンドとして実行しますが、起動ごとにモデルを読み込むため、オーバーヘッドがばかになりません。
Python バインディングを使用すれば、モデルを一度だけ読み込んで、複数の画像が生成できるようになります。
これは非常に有用なため、作者に感謝の意を伝えました。
例を示します。
from stable_diffusion_cpp import StableDiffusion
stable_diffusion = StableDiffusion(
diffusion_model_path="flux1-schnell-q3_k.gguf",
clip_l_path="clip_l.safetensors",
t5xxl_path="t5xxl_fp16.safetensors",
vae_path="ae.safetensors",
)
prompts = [
("flux1-cat.png", "a lovely cat holding a sign says 'flux.cpp'"),
("flux1-dog.png", "a lovely dog holding a sign says 'flux.cpp'"),
]
for fn, prompt in prompts:
output = stable_diffusion.txt_to_img(
prompt=prompt,
sample_steps=4,
cfg_scale=1.0, # a cfg_scale of 1 is recommended for FLUX
sample_method="euler", # euler is recommended for FLUX
)
output[0].save(fn)
参考