stable-diffusion.cpp - C/C++で実装された Diffusion モデル推論
(github.com/leejet)- SD、Flux、Wan 系を含むDiffusion モデル推論を純粋な C/C++ で実行するツールであり、外部依存のない軽量実装を志向している
- 実装は ggml ベースで、llama.cpp と同じ方式で動作する Plain C/C++ 構造
- 対応モデルの範囲は画像モデル、画像編集モデル、動画モデルに分かれ、SD1.x、SD2.x、SDXL、SD3/SD3.5、FLUX、Qwen Image、Wan2.1/Wan2.2、LTX-2.3 などを対象とする
- 機能範囲には PhotoMaker、SD 1.5 向け Control Net、stable-diffusion-webui 方式の LoRA、LCM/LCM-LoRA、TAESD ベースの latent decoding、ESRGAN アップスケール、negative prompt、トークン重み付け tokenizer のサポートが含まれる
- 実行バックエンドは CPU、CUDA、Vulkan、Metal、OpenCL、SYCL で、CPU は x86 アーキテクチャの AVX、AVX2、AVX512 対応を含む
- 対応プラットフォームは Linux、Mac OS、Windows、Android で、Android は Termux と Local Diffusion を通じた実行方式
- 重み形式は
.ckpt、.pth、.pt、.safetensors、.ggufをサポートし、変換モードではモデル重みを.ggufまたは.safetensorsに変換する - 基本的な利用フローは releases page から事前ビルド済みバイナリを取得するか、ソースからビルドした後、モデル重みをダウンロードして
./bin/sd-cli -m ../models/v1-5-pruned-emaonly.safetensors -p "a lovely cat"の形で画像生成を実行する - メモリ使用最適化機能として Flash Attention と VAE tiling processing を提供し、ランタイムやパラメータのバックエンド構成および性能改善は別ガイドの対象
- 再現性オプションは
--rng cudaと--rng cpuに分かれており、それぞれstable-diffusion-webuiの GPU RNG および ComfyUI RNG との一貫性を目指している - PNG 出力には生成パラメータを webui 互換のテキスト文字列として埋め込む
- Golang、C#、Python、Rust、Flutter/Dart 向けのラッパープロジェクトがあり、Jellybox、Local Diffusion、LocalAI、KoboldCpp などは
stable-diffusion.cppを画像生成バックエンドとして利用している - プロジェクトは活発に開発中であり、API とコマンドラインオプションは頻繁に変更される可能性がある
1件のコメント
Hacker News のコメント
Llama.cpp/ggml は LLM にとりわけよく合っている
メモリ要件が大きく、量子化が効果的で、トークン生成が驚くほど直列的かつメモリ帯域幅に縛られるため CPU に向いており、ggml 独特の CPU/GPU パイプライン推論にはさらに適している
しかし Stable Diffusion は違う。量子化はそこまでうまく効かず、UNet は計算量が非常に大きく、バッチ画像生成は単一ユーザーにとっても効果的で有用だ。そのため GPU/内蔵 GPU により向いており、Python 実装のハックしやすさから大きな恩恵を受けている
Stable Diffusion では、機械学習コンパイルで実行ファイルを作る方向が正しいと思う。AITemplate はすでに非常に高速で https://github.com/VoltaML/voltaML-fast-stable-diffusion、TVM Vulkan も誰かがデモ実装をきちんと完成させれば非常に有望だ https://github.com/mlc-ai/web-stable-diffusion
そのうえ、純粋な PyTorch 実装のハックしやすさも大部分は維持される
たとえばコンパイル時に
GGML_CUBLASがサポートされ、純粋な C/C++ と比べてかなり良い速度向上が得られる多少時間がかかっても、古いノート PC で実行できる
torch.compileでもかなり良い速度向上が見られ、自分で作業した覚えがある数値を見つけられるか確認してみる
CLIP まで実装したとは素晴らしい
それだけを抜き出して WebAssembly 実装としてコンパイルしても面白そうだ
追記: すでに誰かが https://github.com/monatis/clip.cpp を作っているようだ。あとは WebAssembly 化すればいい
どこかの秘密の金庫の中に、すでにさらに発展した CLIP 級モデルがあるかもしれないと思うと残念だ
追記: CLIP-2 のことを言っているのではなく、CLIP と同じくらい重要な進歩のことを言っている
設定が信じられないほど簡単だったので、初めてすぐ試してみた
どの程度の速度が出るのが普通なのか気になる
Linux で
cmake .. -DGGML_OPENBLAS=ONを使い、AMD Ryzen 7 5700G 上で実行した。外付け GPU はなく、内蔵グラフィックスだけがある./bin/sd -m ../models/sd-v1-4-ggml-model-f32.bin -p "a lovely cat"を実行すると、サンプリングステップごとに約 12 秒かかり、全体のサンプリングには 246.40 秒かかったこれが期待される性能なのか気になる
追記: OpenBLAS がインストールされていなかったので、そのフラグは効果がなかった
当時はほぼすべての解決策が Python 依存関係の山を要求し、インストールに時間がかかりすぎた末に結局ディスク容量不足で失敗していた
本当に、文字どおり数 GB のディスク容量を 799KB のバイナリ 1 つで置き換えている。おまけに、最速に見える Q8_0 形式を使えばデータも約 2.3GB 節約できる
ただし、デフォルトの 512x512 画像サイズ以外ではバグがあるように見える。544x544 のような一部のサイズは assert 失敗を起こしがちで、512x512 より小さいサイズではときどき壊れた画像を作り、384x384 より小さいサイズではほぼ常にそうなる
[0] https://news.ycombinator.com/item?id=32555608
AI 関連の C/C++ 実装には何か特別な魅力がある
コードがきれいで直感的に感じられ、AI 分野全体が手に取れて学べるもののように見える
Python エコシステムがあまりに雑然としているからだろうか?
Python 版も速度のために C や C++ のコードを使っているが、こちらではすべてが 1 つの言語でできている
きれいなコードを可能にする 3 つの要素が一緒に働いたというわけだ
機械学習方面の人たちが Python から離れ、ハードウェアを最適に活用でき、ビルドや実行のために特殊な環境を整える必要のない言語を使っているのを見るのはよい
まず元記事のプロジェクトは llama.cpp と同じく GPU を使わないが、Python の機械学習コードの大半は GPU を使う。GPU を最適に活用する Python コードを書くのは難しくない。GPU をビルドや実行のための特殊な環境と呼ぶことはできるかもしれないが、この問題には GPU のほうがはるかに向いていると見てよい
次に、元記事のプロジェクトも llama.cpp と同様、Stable Diffusion/LLaMA のような特定のモデルがうまく動くことが確認された後で、効率的で高度に特化したコードを作ったものだ。一方で Python が光るのは、適切なモデルをまだ見つけていないプロトタイピング段階である。C++ でこれほど簡単で快適なプロトタイピングはまだ見たことがない
CPU 上の機械学習領域で llama.cpp の人たちが成し遂げている素晴らしい仕事を貶めるつもりはない。ただ、解いている問題が完全に違う
内部は昔からすべて CUDA、C、C++ だった
Python はそれらすべてをつなぐ非常に効果的な接着剤にすぎない
面倒な問題なしにこれらのモデルを動かせた唯一の方法だ。差があまりにも大きい。CUDA と Linux の組み合わせもよくないし、AMD と Windows の組み合わせは悲惨だ。おそらく自分だけではないと思う
結局、全部メモリ帯域幅の問題だったのだろうか?
GPU の構造は計算能力だけでなく、作業用メモリを計算装置の近くに配置する構造でもある。各装置がグローバルメモリと同期されるローカルメモリを持っている。これが GPU がこうした作業に強い大きな理由なのだろうか?
C++ に見えるのに、なぜ C/C++ と表現したのだろう?
今日このリポジトリを見つけて持ってきて、Mac で
.dylibをビルドし、Dart の ffi-gen ツールで提供されているヘッダーファイルからバインディングを生成したFlutter と一緒に実験していて、サブプロセスを起動したくないので FFI を使っている
結果として、ひどい頭痛と壊れたアプリが残った。明日、頭がすっきりしているときに再挑戦するつもり
それでもこのリポジトリ自体は素晴らしく、M1 で f16 により 10 分以内に実行までできた
複数の量子化レベルの例を見ると、かなり印象的だ
f16 から q8_0 への変化は、品質劣化というより方向性の変化に近く見える。q5_1 の結果は q8_0 と見分けにくい
高精度モデルでは決定性を失うが、実際にはかなり使いものになる可能性がある
ベンチマークはある?
https://github.com/leejet/stable-diffusion.cpp/issues/1
cmake .. -DGGML_CUBLAS=ON -DCMAKE_CUDA_COMPILER=/opt/cuda/bin/nvccコマンドでコンパイルし、NVIDIA GeForce RTX 2060 SUPER を使用したモデルは FP16 に変換した
この選択では反復あたりの時間が 8.5〜9 秒の間で、画像 1 枚を作る全体時間は約 200 秒だ