Skip to content

如何在 Core ML 上运行 Stable Diffusion

Core ML 是 Apple 框架支持的模型格式和机器学习库。如果你有兴趣在 macOS 或 iOS/iPadOS 应用中运行 Stable Diffusion 模型,本指南将向你展示如何将现有的 PyTorch 检查点转换为 Core ML 格式,并使用 Python 或 Swift 进行推理。

Core ML 模型可以利用 Apple 设备中所有可用的计算引擎:CPU、GPU 和 Apple 神经引擎(或 ANE,这是在 Apple Silicon Mac 和现代 iPhone/iPad 中可用的张量优化加速器)。根据模型和运行设备的不同,Core ML 还可以混合使用计算引擎,例如,模型的某些部分可以在 CPU 上运行,而其他部分则在 GPU 上运行。

Stable Diffusion Core ML 检查点

Stable Diffusion 权重(或检查点)存储在 PyTorch 格式中,因此在我们可以在原生应用中使用它们之前,需要将它们转换为 Core ML 格式。

幸运的是,Apple 工程师开发了 一个转换工具,基于 diffusers 将 PyTorch 检查点转换为 Core ML。

不过,在转换模型之前,请花点时间浏览 Hugging Face Hub——你感兴趣的模型可能已经以 Core ML 格式提供:

  • Apple 组织包括 Stable Diffusion 1.4、1.5、2.0 基础版和 2.1 基础版
  • coreml community 包括自定义微调模型
  • 使用此 过滤器 查找所有可用的 Core ML 检查点

如果你找不到你感兴趣的模型,我们建议你按照 Apple 提供的 将模型转换为 Core ML 的说明进行操作。

选择要使用的 Core ML 变体

Stable Diffusion 模型可以转换为不同的 Core ML 变体,这些变体适用于不同的用途:

  • 注意力块的类型。注意力操作用于“关注”图像表示中不同区域之间的关系,以及图像和文本表示之间的关系。注意力计算和内存密集,因此存在不同的实现,这些实现考虑了不同设备的硬件特性。对于 Core ML Stable Diffusion 模型,有两种注意力变体:

    • split_einsum(由 Apple 引入)针对 ANE 设备进行了优化,这些设备在现代 iPhone、iPad 和 M 系列计算机中可用。
    • “原始”注意力(diffusers 中使用的基实现)仅与 CPU/GPU 兼容,不支持 ANE。在某些情况下,使用 original 注意力在 CPU + GPU 上运行模型可能比在 ANE 上更快。请参阅 此性能基准 以及社区提供的 一些额外的测量数据 以获取更多详细信息。
  • 支持的推理框架。

    • packages 适用于 Python 推理。这可以用于在尝试将转换后的 Core ML 模型集成到原生应用之前进行测试,或者如果你希望探索 Core ML 性能但不需要支持原生应用。例如,具有 Web UI 的应用程序可以完美地使用 Python Core ML 后端。
    • compiled 模型是 Swift 代码的必需项。Hub 中的 compiled 模型将大型 UNet 模型权重拆分为多个文件,以兼容 iOS 和 iPadOS 设备。这对应于 转换选项 --chunk-unet。如果你希望支持原生应用,则需要选择 compiled 变体。

官方 Core ML Stable Diffusion 模型 包含这些变体,但社区提供的模型可能会有所不同:

coreml-stable-diffusion-v1-4
├── README.md
├── original
│   ├── compiled
│   └── packages
└── split_einsum
    ├── compiled
    └── packages

你可以下载并使用所需的变体,如下所示。

在 Python 中使用 Core ML 进行推理

安装以下库以在 Python 中运行 Core ML 推理:

bash
pip install huggingface_hub
pip install git+https://github.com/apple/ml-stable-diffusion

下载模型检查点

要在 Python 中运行推理,请使用存储在 packages 文件夹中的版本,因为 compiled 版本仅与 Swift 兼容。你可以选择使用 originalsplit_einsum 注意力机制。

以下是如何从 Hub 下载 original 注意力机制版本到名为 models 的目录中:

python
from huggingface_hub import snapshot_download

snapshot_download(repo_id="model-repo", local_dir="models", allow_patterns="packages/*")
Python
from huggingface_hub import snapshot_download
from pathlib import Path

repo_id = "apple/coreml-stable-diffusion-v1-4"
variant = "original/packages"

model_path = Path("./models") / (repo_id.split("/")[-1] + "_" + variant.replace("/", "_"))
snapshot_download(repo_id, allow_patterns=f"{variant}/*", local_dir=model_path, local_dir_use_symlinks=False)
print(f"Model downloaded at {model_path}")

推理[[python-inference]]

一旦你下载了模型的快照,就可以使用 Apple 的 Python 脚本来测试它。

shell
python -m python_coreml_stable_diffusion.pipeline --prompt "a photo of an astronaut riding a horse on mars" -i ./models/coreml-stable-diffusion-v1-4_original_packages/original/packages -o </path/to/output/image> --compute-unit CPU_AND_GPU --seed 93

使用 -i 标志将下载的检查点路径传递给脚本。--compute-unit 表示你希望用于推理的硬件。它必须是以下选项之一:ALLCPU_AND_GPUCPU_ONLYCPU_AND_NE。你还可以提供一个可选的输出路径和一个用于可重复性的种子。

推理脚本假设你使用的是 Stable Diffusion 模型的原始版本,CompVis/stable-diffusion-v1-4。如果你使用其他模型,必须 在推理命令行中使用 --model-version 选项指定其 Hub ID。这适用于已经支持的模型和你自己训练或微调的自定义模型。

例如,如果你想使用 stable-diffusion-v1-5/stable-diffusion-v1-5

shell
python -m python_coreml_stable_diffusion.pipeline --prompt "a photo of an astronaut riding a horse on mars" --compute-unit ALL -o output --seed 93 -i models/coreml-stable-diffusion-v1-5_original_packages --model-version stable-diffusion-v1-5/stable-diffusion-v1-5

Core ML 推理在 Swift 中

在 Swift 中运行推理比在 Python 中稍快,因为模型已经编译为 mlmodelc 格式。这在应用启动时加载模型时会有所体现,但如果你随后运行多个生成过程,则不应有明显差异。

下载

要在 Mac 上使用 Swift 运行推理,你需要其中一个 compiled 检查点版本。我们建议你使用类似于前面示例的 Python 代码将其下载到本地,但要选择其中一个 compiled 变体:

Python
from huggingface_hub import snapshot_download
from pathlib import Path

repo_id = "apple/coreml-stable-diffusion-v1-4"
variant = "original/compiled"

model_path = Path("./models") / (repo_id.split("/")[-1] + "_" + variant.replace("/", "_"))
snapshot_download(repo_id, allow_patterns=f"{variant}/*", local_dir=model_path, local_dir_use_symlinks=False)
print(f"Model downloaded at {model_path}")

推理[[swift-inference]]

要运行推理,请克隆 Apple 的仓库:

bash
git clone https://github.com/apple/ml-stable-diffusion
cd ml-stable-diffusion

然后使用 Apple 的命令行工具,Swift Package Manager

bash
swift run StableDiffusionSample --resource-path models/coreml-stable-diffusion-v1-4_original_compiled --compute-units all "a photo of an astronaut riding a horse on mars"

你必须在 --resource-path 中指定在上一步下载的检查点之一,确保它包含扩展名为 .mlmodelc 的编译 Core ML 捆绑包。--compute-units 必须是以下值之一:allcpuOnlycpuAndGPUcpuAndNeuralEngine

更多详情,请参阅 Apple 仓库中的说明

支持的 Diffusers 功能

Core ML 模型和推理代码不支持 🧨 Diffusers 的许多功能、选项和灵活性。以下是一些需要注意的限制:

  • Core ML 模型仅适用于推理。它们不能用于训练或微调。
  • 只有两个调度器被移植到 Swift,一个是 Stable Diffusion 默认使用的调度器,另一个是我们从 diffusers 实现中移植的 DPMSolverMultistepScheduler。我们建议你使用 DPMSolverMultistepScheduler,因为它在大约一半的步骤中产生相同的质量。
  • 负面提示、无分类器引导比例和图像到图像任务在推理代码中可用。高级功能如深度引导、ControlNet 和潜在上采样器尚未可用。

Apple 的 转换和推理仓库 和我们自己的 swift-coreml-diffusers 仓库旨在作为技术演示,以帮助其他开发者构建自己的项目。

如果你对任何缺失的功能有强烈需求,请随时打开一个功能请求,或者更好的是,提交一个贡献 PR 🙂。

原生 Diffusers Swift 应用

在你自己的 Apple 硬件上运行 Stable Diffusion 的一种简单方法是使用 我们的开源 Swift 仓库,该仓库基于 diffusers 和 Apple 的转换和推理仓库。你可以研究代码,使用 Xcode 编译并根据自己的需求进行调整。为了方便起见,App Store 中还有一个 独立的 Mac 应用,因此你可以在不处理代码或 IDE 的情况下进行尝试。如果你是开发者,并且确定 Core ML 是构建你的 Stable Diffusion 应用的最佳解决方案,那么你可以使用本指南的其余部分开始你的项目。我们迫不及待想看看你会构建什么 🙂。