☰
在 Rust 中运行 Stable Diffusion:candle-stable-diffusion 完整使用指南
2026/10/2 2:00:06 网站建设 项目流程
  • 人工智能
  • 大模型
  • 机器学习
  • 深度学习
  • 本地部署
  • 模型推理服务

【免费下载链接】candle

Minimalist ML framework for Rust

项目地址:https://gitcode.com/GitHub_Trending/ca/candle
点击查看免费下载

stable-diffusion是 candle 仓库中一个将 Hugging Face Diffusers 生态移植到 Rust/Candle 的端到端示例,支持 Stable Diffusion v1.5、v2.1、XL 1.0 以及 XL Turbo 四种模型版本。本文将以 candle-examples/examples/stable-diffusion/README.md 为核心,结合 main.rs 与 stable_diffusion 模块 源码,完整讲解从权重下载、命令行运行、调度器选择到 flash-attention 加速和内存优化的全过程,读完即可在 GPU 或 CPU 上自行生成高质量图像。

图:由 Stable Diffusion XL 在 Rust/Candle 下生成的"手持蜡烛的锈蚀机器人",出自 assets/stable-diffusion-xl.jpg。

项目定位:用 Rust 复刻 Diffusers API

stable-diffusion示例是 diffusers-rs 目录:

  • clip.rs:CLIP 文本编码器,负责把 prompt 编码为条件向量;
  • unet_2d.rs/unet_2d_blocks.rs:UNet 2D 条件去噪网络(含跨注意力);
  • vae.rs:AutoEncoderKL,负责图像与潜空间(latent space)之间的编解码;
  • schedulers.rs:调度器抽象接口,以及ddim.rs、euler_ancestral_discrete.rs、uni_pc.rs、ddpm.rs等具体实现。

从源码结构可以推断,整个生成流程遵循经典扩散管线:文本编码 → 潜空间加噪 → 多步去噪 → VAE 解码为图像,与 Python Diffusers 的 API 设计一一对应。

支持的模型版本与权重获取

本示例支持以下版本(对应 main.rs 中的StableDiffusionVersion枚举):

版本--sd-version取值对应 Hugging Face 仓库
Stable Diffusion v1.5v1-5runwayml/stable-diffusion-v1-5
Stable Diffusion v2.1v2-1stabilityai/stable-diffusion-2-1
Stable Diffusion XL 1.0xlstabilityai/stable-diffusion-xl-base-1.0
SDXL Turboturbostabilityai/sdxl-turbo

此外,源码中还定义了v1-5-inpaint、v2-inpaint、xl-inpaint三个修图(inpainting)版本(对应仓库stable-diffusion-v1-5/stable-diffusion-inpainting、stabilityai/stable-diffusion-2-inpainting、diffusers/stable-diffusion-xl-1.0-inpainting-0.1),用于带蒙版的局部重绘场景。

权重无需手动下载。首次运行时,程序会通过 candle-examples/src/hub.rs 中的Api(基于hf-hub封装)自动从 Hugging Face Hub 拉取所需文件,并按仓库结构分别下载unet/、vae/、text_encoder/(XL 还有text_encoder_2/)下的.safetensors权重以及tokenizer.json。若希望离线使用或指定自有权重,可通过--unet-weights、--clip-weights、--clip2-weights、--vae-weights、--tokenizer传入本地文件路径(见下文参数表);运行--help可以查看全部可用选项。

运行第一个示例

在仓库根目录执行以下命令即可用 CUDA + cuDNN 在 GPU 上生成图像:

cargo run --example stable-diffusion --release --features=cuda,cudnn \ -- --prompt "a cosmonaut on a horse (hd, realistic, high-def)"

运行结束后,默认在当前目录生成sd_final.png。若没有 NVIDIA GPU,可去掉--features=cuda,cudnn并加--cpu改用 CPU 推理(速度会慢很多);macOS 用户可尝试--features=metal使用 Metal 后端。

体验 SDXL Turbo:一步成像

Turbo 版本基于对抗蒸馏(adversarial distillation)训练,去噪步数大幅减少,生成速度远快于前几个版本。仅需增加一个--sd-version turbo参数:

cargo run --example stable-diffusion --release --features=cuda,cudnn \ -- --prompt "a cosmonaut on a horse (hd, realistic, high-def)" --sd-version turbo

这一加速的根源在于源码中的默认配置:从 mod.rs 可见,普通版本(v1-5 / v2-1 / xl)默认n_steps = 30,而 Turbo 默认仅n_steps = 1,同时默认引导系数guidance_scale从 7.5 降为 0(蒸馏模型本身已集成引导,无需再对无条件分支做加权外推)。

命令行参数全解析

以下参数均可在 main.rs 的Args结构中找到定义,覆盖 README 所述全部选项并额外列出源码中支持的进阶参数:

参数说明默认值
--prompt用于生成图像的提示词"A very realistic photo of a rusty robot walking on a sandy beach"
--uncond-prompt可选的负向提示(无条件 prompt),用于引导系数计算空字符串
--sd-version模型版本,取值v1-5/v2-1/xl/turbov2-1
--cpu强制使用 CPU 而非 GPU关闭
--height/--width生成图像的高宽,必须能被 8 整除(源码中assert_eq!(height % 8, 0)强制校验)随版本不同:v1-5 为 512×512,v2-1 为 768×768,XL/Turbo 为 1024×1024(Turbo 为 512×512)
--n-steps扩散去噪步数普通版本 30,Turbo 1
--num-samples迭代生成的样本数1
--bsize同时生成的样本数(批大小)1
--final-image输出图片文件名sd_final.png
--use-flash-attn启用 flash-attention 加速关闭
--use-f16使用 FP16 权重与半精度推理关闭
--guidance-scale引导系数(CFG 权重)普通版本 7.5,Turbo 0
--seed随机种子,复现结果用;不指定时自动生成随机种子并在终端打印随机
--sliced-attention-size切分注意力的大小,0 表示自动切分(默认关闭),用于显存受限场景关闭
--intermediary-images每个去噪步骤都输出一张中间图像(文件名带-N后缀)关闭
--tracing启用 tracing,生成trace-timestamp.json供 Chrome tracing 分析关闭
--unet-weights/--clip-weights/--clip2-weights/--vae-weights/--tokenizer指定本地.safetensors权重与 tokenizer 文件,跳过 Hub 下载自动下载

当num_samples > 1时,输出文件会按basename.{idx}.png规则命名(见output_filename函数)。--num-samples与--bsize的区别在于:前者是串行迭代生成多张图,后者是单次去噪中并行生成一批图。

关于--use-f16有个值得注意的细节:SDXL/Turbo 在 FP16 下会改用社区修复版 VAE 仓库madebyollin/sdxl-vae-fp16-fix,这是为了规避 SDXL 官方 VAE 在 FP16 下数值溢出的已知问题(mod.rs 中的注释引用了相关 issue)。

调度器:DDIM 与 Euler Ancestral

调度器决定"噪声如何逐步去除",直接权衡生成速度与画质。本示例的默认调度器配置(mod.rs):

  • v1.5、v2.1、XL 1.0:默认使用DDIM(Denoising Diffusion Implicit Model)调度器,即ddim::DDIMSchedulerConfig。DDIM 通过隐式采样可以在更少的步数下获得不错的画质;
  • XL Turbo:默认使用Euler Ancestral 调度器(euler_ancestral_discrete::EulerAncestralDiscreteSchedulerConfig),并配合timestep_spacing = Trailing的时间步划分,与 Turbo 蒸馏模型的训练设置保持一致。

调度器在代码层面被抽象为SchedulerConfig/Scheduler两个 trait(schedulers.rs),接口包括timesteps()(生成时间步序列)、add_noise()(向潜变量加噪)、init_noise_sigma()(初始噪声标准差)、scale_model_input()(缩放模型输入)与step()(单步去噪)。主循环在 main.rs 中按序调用:先scheduler.scale_model_input归一化输入,UNet 前向预测噪声,再按guidance_scale对条件/无条件两支预测做加权融合,最后scheduler.step更新潜变量,如此往复直到所有时间步完成。

使用 flash-attention 加速

自注意力在扩散模型中计算量占比很高,启用 flash-attention 可以显著提速并降低显存占用,代价是编译时间较长。需要同时满足两个条件(缺一不可):

  1. 特性开关:编译时加--features flash-attn(该特性在 candle-examples/Cargo.toml 中定义为["cuda", "candle-transformers/flash-attn", "dep:candle-flash-attn"],即依赖candle-flash-attn这个 CUDA kernel 库);
  2. 运行时开关:命令行加--use-flash-attn。
cargo run --example stable-diffusion --release --features=cuda,cudnn,flash-attn \ -- --prompt "a cosmonaut on a horse (hd, realistic, high-def)" --use-flash-attn

由于 flash-attention 内核需要针对不同 head 维度与精度编译大量 CUDA 变体(可在 candle-flash-attn/kernels/ 中看到按hdim、fp16/bf16、causal组合生成的众多.cu文件),建议设置环境变量CANDLE_FLASH_ATTN_BUILD_DIR指向固定目录以缓存编译产物,避免每次重新编译:

export CANDLE_FLASH_ATTN_BUILD_DIR=/home/user/.candle

硬件前提:flash-attention-v2 仅兼容 Ampere、Ada 或 Hopper 架构的 NVIDIA GPU(如 A100/H100、RTX 3090/4090),旧架构无法使用。

图像到图像(img2img)与局部重绘(Inpainting)

README 中"Image to Image Pipeline"一节标记为占位内容,但对应能力已在 main.rs 中完整实现,这里结合源码补充说明:

img2img:基于输入图像生成变体

通过--img2img <图片路径>传入初始图像,程序会执行image_preprocess:先将宽高向下取整到 32 的倍数,用 CatmullRom 滤波缩放,再归一化到[-1, 1]并转为[1, 3, H, W]张量(main.rs),随后用 VAE 编码为初始潜变量。

--img2img-strength(取值 0~1,默认 0.8)控制对原图的保留程度:值越大变换越剧烈,为 1 时完全丢弃原图信息、退化为纯文生图。从源码看,强度通过跳过去噪前若干步实现:t_start = n_steps - (n_steps * strength) as usize(main.rs),并在起始步按对应时间步为初始潜变量添加噪声(scheduler.add_noise)。

cargo run --example stable-diffusion --release --features=cuda,cudnn \ -- --prompt "a cosmonaut on a horse" --img2img input.png --img2img-strength 0.8

Inpainting:蒙版区域重绘

选择 inpainting 版本(v1-5-inpaint等)时必须同时提供--mask-path <蒙版图>和--img2img <原图>(源码中分别报错提示缺失)。流程(main.rs)为:

  1. mask_preprocess把蒙版转为单通道灰度张量,白/黑分别表示"待重绘/保留"区域;
  2. 用蒙版遮罩原图得到masked_img,经 VAE 编码为mask_latents;
  3. UNet 输入通道数从 4 扩为 9(潜变量、蒙版、蒙版潜变量拼接,见in_channels = 9的分支);
  4. 去噪结束后,若加了--only-update-masked,则只把蒙版区域之外的像素还原为原图潜变量(latents * mask + latent_to_keep * (1-mask)),保证背景不变化。

常见问题:内存与显存优化

官方 FAQ 明确指出:默认配置(v2-1 768×768)需要超过 8GB 显存的 GPU。显存不足时可按优先级采取以下措施:

  1. 缩小分辨率:--height/--width调小可显著降低显存占用,注意必须是 8 的倍数(源码断言强制约束);
  2. 切分注意力:--sliced-attention-size <N>将大尺寸注意力切成小块计算,是显存受限场景的有效手段;
  3. 半精度:--use-f16使用 FP16 权重与计算,显存占用接近减半(SDXL 会自动搭配 FP16 修复版 VAE);
  4. 启用 flash-attention:--use-flash-attn在提速的同时降低显存峰值(前提是 Ampere 及以上 GPU);
  5. 最后兜底:--cpu用 CPU 推理,速度显著变慢但无需 GPU。

另外,使用--seed可固定随机种子复现同一结果;主程序在未指定种子时也会打印所用种子,便于事后追溯。若开启--tracing,可结合 Chrome 的chrome://tracing对 UNet 各阶段耗时做性能分析。

小结

candle-stable-diffusion是理解"如何用纯 Rust 实现现代扩散模型推理"的最佳切入点:从 README 的启动命令出发,到 main.rs 的完整管线,再到 candle-transformers/src/models/stable_diffusion/ 的模型实现,整个链路清晰可读。它既可作为开箱即用的文生图工具,也可作为基于 Candle 二次开发扩散应用的参考模板——无论是替换调度器、接入新的模型仓库,还是移植 img2img / inpainting 能力到自有管线,都能从这套代码中直接获得实现路径。

  • 人工智能
  • 大模型
  • 机器学习
  • 深度学习
  • 本地部署
  • 模型推理服务

【免费下载链接】candle

Minimalist ML framework for Rust

项目地址:https://gitcode.com/GitHub_Trending/ca/candle
点击查看免费下载
上一篇:Fang异步任务处理详解:基于PostgreSQL的高效队列实现
下一篇:野火IM iOS二次开发指南:定制属于你的专属即时通讯App,3步实现个性化界面

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询