Automatic1111 针对苹果 Metal,SD1.5 提速 40%
我在苹果硬件上经常使用 Draw Things,但一直困扰我的是 Automatic1111 的速度:它感觉比应该的慢。虽然不是无法使用的慢,但慢得让你注意到。在我的 M3 Pro 上,使用 Automatic1111 进行短短五步 DPM++ SDE 生成通常需要 8-10 秒。Draw Things 已经让我看到,在苹果硅上,稳定扩散的体验要迅速得多。所以我想看看这种差距有多少是必要的。GitHub - dmikey/stable-diffusion-webui-metal:为苹果硅优化的 Automatic1111。Gabby 在 GitHub 上创建一个帐户来为 dmikey/stable-diffusion-webui-metal 的开发贡献代码。重要的一点是:我不想替换 Automatic1111。我希望保留相同的 WebUI、检查点、LoRAs、采样器、扩展、API、提示语法和一般工作流。我对将所有内容转换为 Core ML 并围绕它构建另一个推理引擎不感兴趣。目标更狭窄:如果我们让重要部分的表现更像本地苹果软件,Automatic1111 能快到什么程度?答案是,对于我正在运行的工作负载而言,速度快多了。原本在我的 M3 Pro 上大约需要 8-10 秒的同一类生成,现在一般在 3 到 7 秒之间。而 13-20 秒的情况,现在在我的 M1 Mac Mini 上则缩短到了 8-10 秒。这些都是我当前工作负载下观察到的范围,并不是一个声称能够普遍提高 2 倍的受控基准测试。另外,运行时的改进和 NGMS 之间也有一个重要的区别,后者实际减少了指导工作的量。不过,实际使用中的差异是显著的。然而,最有趣的不是最终的数字,而是达到这个结果所需的过程。这并不是一个简单的优化。首先要关注工作负载,而不是基准测试。我关注的工作负载非常特定:稳定扩散 1.x DPM++ SDE Karras 5 步 CFG 大约 1.15 384×640 和 512×512 FP16 UNet 默认在 MPS 上使用 FP32 VAE。这种特异性很重要。最初,DPM++ 2M 看起来是个快速节省时间的简单方法。它更快,但没能从短时间安排中产生我想要的结果。这不是优化,而是不同的工作负载。这成了之后所有优化的规则:如果某个优化在孤立时看起来不错,但没有在保持我想要的结果的同时加快实际生成,就不算。关注显然是个好的起点。PyTorch 的 MPS 后端已经有了显著提升,但仍然有一些稳定扩散的注意力形状直接转换为 Metal 是合理的。错误的是将自定义的 Metal 实现视为普遍更快。它不是。相反,我为 SD 1.x 的注意力形状添加了一个专门的 Metal Flash Attention 路径,它在测试中确实展现了优势。路由器的概念结构大致如下:如果推理和 fp16_mps 且 query_tokens >= 192 且 head_dim 在 (40, 80, 160) 内:返回 metal_flash_attention(q, k, v) 否则返回 pytorch_sdpa(q, k, v)。在掩码、训练、丢弃、张量布局、分组查询注意力和支持类型方面还有额外的检查,但这就是基本思路。Metal 不是因为听起来更快而是默认的。只有在我们测量出该形状并且它值得的时候,它才得到操作。其他所有内容都通过 PyTorch 处理。这个后备是重要的。Automatic1111 支持的配置比我的五步 SD 1.x 工作流多得多。我不想要一个如果没有人碰任何东西就能运行的更快分支。内核并不是整个问题。将注意力引入 Metal 有所帮助,但暴露出了更有趣的东西。原生扩展在每次注意力调用后都提交 MPS 命令缓冲区。稳定扩散在每次 UNet 评估时都会反复调用注意力。在短短五步生成过程中,反复提交小块工作开始成为总运行时间的重要组成部分。因此,我没有将 Metal 内核视为一个独立的小应用程序,而是将其集成到 PyTorch 当前的 MPS 流中。该扩展结束了 PyTorch 当前的内核合并,将 Metal Flash Attention 操作编码到当前的命令缓冲区,然后让其余的 PyTorch MPS 工作继续进行。每次注意力调用之后的显式提交也随之消失。这实际成了整个项目中最重要的教训之一。最快的内核如果在每个调用后都提交命令缓冲区,仍然会失去效果。在这些生成时间下,开销很重要。你不再只是优化 GPU 乘法矩阵的速度。你在优化 Python、PyTorch、MPSGraph 和 Metal 之间的协调频率。另外还有一个绝妙的提醒:不要相信计时器:早期版本之一产生了一幅绿色的图像。它很快,但也是绿色的。Metal 路径现在运行一个隔离的注意力加投影正确性验证。
本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。
☕请我喝杯咖啡