stable-diffusion.cpp - Suy luận mô hình Diffusion được triển khai bằng C/C++
(github.com/leejet)- Đây là công cụ chạy suy luận mô hình Diffusion bằng C/C++ thuần túy, bao gồm các dòng SD, Flux và Wan, hướng tới một triển khai gọn nhẹ không có phụ thuộc bên ngoài
- Phần triển khai dựa trên ggml và có cấu trúc Plain C/C++ hoạt động theo cách tương tự llama.cpp
- Phạm vi mô hình được hỗ trợ được chia thành mô hình ảnh, mô hình chỉnh sửa ảnh và mô hình video, nhắm tới SD1.x, SD2.x, SDXL, SD3/SD3.5, FLUX, Qwen Image, Wan2.1/Wan2.2, LTX-2.3, v.v.
- Phạm vi tính năng hỗ trợ gồm PhotoMaker, Control Net cho SD 1.5, LoRA theo cách của stable-diffusion-webui, LCM/LCM-LoRA, giải mã latent dựa trên TAESD, upscale ESRGAN, negative prompt và tokenizer hỗ trợ trọng số token
- Các backend thực thi gồm CPU, CUDA, Vulkan, Metal, OpenCL và SYCL; CPU bao gồm hỗ trợ AVX, AVX2 và AVX512 trên kiến trúc x86
- Các nền tảng được hỗ trợ là Linux, Mac OS, Windows và Android; trên Android, cách chạy là thông qua Termux và Local Diffusion
- Các định dạng trọng số được hỗ trợ là
.ckpt,.pth,.pt,.safetensors,.gguf; chế độ chuyển đổi sẽ chuyển trọng số mô hình sang.ggufhoặc.safetensors - Quy trình sử dụng cơ bản là tải binary dựng sẵn từ releases page hoặc build từ source, sau đó tải trọng số mô hình và chạy tạo ảnh theo dạng
./bin/sd-cli -m ../models/v1-5-pruned-emaonly.safetensors -p "a lovely cat" - Các tính năng tối ưu sử dụng bộ nhớ gồm Flash Attention và VAE tiling processing; việc tinh chỉnh backend batch khi chạy, tham số và cải thiện hiệu năng được tách thành hướng dẫn riêng
- Các tùy chọn tái lập kết quả được chia thành
--rng cudavà--rng cpu, lần lượt hướng tới tính nhất quán với GPU RNG củastable-diffusion-webuivà RNG của ComfyUI - Đầu ra PNG sẽ nhúng các tham số tạo sinh dưới dạng chuỗi văn bản tương thích webui
- Có các dự án wrapper cho Golang, C#, Python, Rust và Flutter/Dart; Jellybox, Local Diffusion, LocalAI, KoboldCpp, v.v. sử dụng
stable-diffusion.cpplàm backend tạo ảnh - Dự án đang được phát triển tích cực và API cũng như các tùy chọn dòng lệnh có thể thay đổi thường xuyên
1 bình luận
Các ý kiến trên Hacker News
Llama.cpp/ggml đặc biệt phù hợp với LLM
Yêu cầu bộ nhớ lớn, lượng tử hóa hiệu quả, việc sinh token có tính tuần tự đáng ngạc nhiên và bị giới hạn bởi băng thông bộ nhớ nên rất hợp với CPU, thậm chí còn hợp hơn với kiểu suy luận pipeline CPU/GPU đặc trưng của ggml
Nhưng Stable Diffusion thì khác. Lượng tử hóa không hiệu quả đến mức đó, UNet có khối lượng tính toán rất lớn, và tạo ảnh theo batch vẫn hiệu quả, hữu ích ngay cả với một người dùng đơn lẻ. Vì vậy nó phù hợp hơn với GPU/GPU tích hợp, và hưởng lợi lớn từ khả năng hack linh hoạt của bản triển khai Python
Với Stable Diffusion, tôi nghĩ hướng đúng là dùng biên dịch machine learning để tạo file thực thi. AITemplate đã rất nhanh rồi https://github.com/VoltaML/voltaML-fast-stable-diffusion, TVM Vulkan cũng rất hứa hẹn nếu ai đó hoàn thiện tử tế bản demo https://github.com/mlc-ai/web-stable-diffusion
Hơn nữa, phần lớn khả năng hack linh hoạt của bản PyTorch thuần vẫn được giữ lại
Ví dụ khi biên dịch có hỗ trợ
GGML_CUBLAS, và đạt mức tăng tốc khá ổn so với C/C++ thuầnDù mất chút thời gian, vẫn có thể chạy trên laptop cũ
torch.compilecũng cho mức tăng tốc khá tốt, và tôi nhớ mình từng trực tiếp làm việc đóTôi sẽ xem có tìm được số liệu không
Thật tuyệt khi họ còn triển khai cả CLIP
Chỉ riêng việc tách nó ra rồi biên dịch thành bản WebAssembly cũng đã hay rồi
Sửa: có vẻ đã có người tạo https://github.com/monatis/clip.cpp rồi. Giờ chỉ cần WebAssembly hóa nó
Nghĩ đến khả năng đâu đó trong két bí mật đã có một mô hình tầm CLIP tiên tiến hơn thật đáng tiếc
Sửa: ý tôi không phải là CLIP-2, mà là một bước tiến có mức độ quan trọng ngang với CLIP
Việc thiết lập dễ đến khó tin nên đây là lần đầu tôi thử ngay
Tôi tò mò không biết tốc độ bao nhiêu mới là bình thường
Trên Linux, tôi chạy trên AMD Ryzen 7 5700G với
cmake .. -DGGML_OPENBLAS=ON, không có GPU rời mà chỉ có đồ họa tích hợpKhi chạy
./bin/sd -m ../models/sd-v1-4-ggml-model-f32.bin -p "a lovely cat", mỗi bước sampling mất khoảng 12 giây, toàn bộ quá trình sampling mất 246,40 giâyTôi muốn biết đây có phải hiệu năng kỳ vọng không
Sửa: OpenBLAS chưa được cài nên cờ đó không có tác dụng
Khi đó hầu như mọi giải pháp đều đòi một đống phụ thuộc Python, cài đặt mất quá lâu rồi cuối cùng thất bại vì hết dung lượng ổ đĩa
Thật sự, đúng nghĩa đen là thay thế vài gigabyte dung lượng ổ đĩa bằng một binary 799KB. Thêm nữa, nếu dùng định dạng Q8_0 có vẻ nhanh nhất, dữ liệu cũng tiết kiệm được khoảng 2,3GB
Tuy nhiên ngoài kích thước ảnh mặc định 512x512 thì có vẻ có lỗi. Một số kích thước như 544x544 thường gây lỗi assert, các kích thước nhỏ hơn 512x512 đôi khi tạo ảnh rác, còn nhỏ hơn 384x384 thì gần như lúc nào cũng vậy
[0] https://news.ycombinator.com/item?id=32555608
Các bản triển khai C/C++ liên quan đến AI có một sức hút đặc biệt nào đó
Code trông gọn gàng và trực quan, khiến toàn bộ lĩnh vực AI có vẻ như có thể nắm bắt và học được
Có phải vì hệ sinh thái Python quá lộn xộn không?
Phiên bản Python cũng dùng code C và C++ để tăng tốc, nhưng ở đây tất cả đều nằm trong một ngôn ngữ
Có thể nói ba yếu tố tạo ra code gọn gàng đã cùng phát huy tác dụng
Thật vui khi thấy những người làm machine learning rời khỏi Python và dùng một ngôn ngữ có thể tận dụng phần cứng tối ưu, lại không cần phải dựng môi trường đặc biệt để build/chạy
Trước hết, dự án trong bài gốc không dùng GPU giống như llama.cpp, trong khi phần lớn mã machine learning bằng Python đều dùng GPU. Viết mã Python tận dụng GPU tối ưu không khó. Có thể gọi GPU là một môi trường đặc biệt để build/chạy, nhưng với bài toán này thì GPU phù hợp hơn rất nhiều
Thứ hai, dự án trong bài gốc cũng giống llama.cpp: sau khi đã xác nhận rằng một mô hình cụ thể như Stable Diffusion/LLaMA hoạt động tốt, họ mới viết mã hiệu quả và chuyên biệt hóa cao. Ngược lại, nơi Python tỏa sáng là giai đoạn prototyping khi vẫn chưa tìm được mô hình phù hợp. Tôi vẫn chưa thấy việc prototyping trong C++ dễ và tiện đến mức đó
Tôi không có ý hạ thấp công việc tuyệt vời mà nhóm llama.cpp đang làm trong mảng machine learning trên CPU. Chỉ là vấn đề họ giải quyết hoàn toàn khác nhau
Bên trong từ lâu đã toàn là CUDA, C, C++
Python chỉ là một lớp keo kết dính rất hiệu quả để nối tất cả lại với nhau
Đây là cách duy nhất tôi từng chạy được các mô hình này mà không gặp vấn đề đau đầu. Khác biệt quá lớn. CUDA với Linux cũng không ổn lắm, còn AMD với Windows thì thảm họa. Có lẽ không chỉ mình tôi gặp vậy
Rốt cuộc tất cả chỉ là vấn đề băng thông bộ nhớ thôi sao?
Kiến trúc GPU không chỉ có năng lực tính toán, mà còn đặt bộ nhớ làm việc gần các đơn vị tính toán. Mỗi đơn vị có bộ nhớ cục bộ được đồng bộ với bộ nhớ toàn cục. Đây có phải là một lý do lớn khiến GPU mạnh với các tác vụ kiểu này không?
Nhìn có vẻ là C++, vậy sao lại gọi là C/C++?
Hôm nay tôi thấy repo này, kéo về và build
.dylibtrên Mac, rồi dùng công cụ ffi-gen của Dart để tạo binding từ file header được cung cấpTôi đang thử nghiệm cùng Flutter và dùng FFI để khỏi phải khởi chạy subprocess
Kết quả là một cơn đau đầu dữ dội và một ứng dụng hỏng. Mai tỉnh táo hơn sẽ thử lại
Dù vậy bản thân repo này rất tuyệt, và trên M1 chạy được với f16 trong chưa tới 10 phút
Nhìn các ví dụ về nhiều mức lượng tử hóa thì khá ấn tượng
Chuyển từ f16 sang q8_0 trông giống thay đổi về hướng hơn là mất chất lượng. Kết quả q5_1 trông khó phân biệt với q8_0
Ở các mô hình độ chính xác cao thì mất tính quyết định, nhưng thực tế có khả năng vẫn khá dùng được
Có benchmark không?
https://github.com/leejet/stable-diffusion.cpp/issues/1
cmake .. -DGGML_CUBLAS=ON -DCMAKE_CUDA_COMPILER=/opt/cuda/bin/nvccvà dùng NVIDIA GeForce RTX 2060 SUPERMô hình đã được chuyển sang FP16
Với lựa chọn này, thời gian mỗi iteration nằm trong khoảng 8,5–9 giây, và tổng thời gian để tạo một ảnh là khoảng 200 giây