Automatic1111 на Apple Silicon можно заметно ускорить, не отказываясь от привычного окружения. Автор сделал форк stable-diffusion-webui-metal: та же WebUI, те же checkpoints, LoRAs, семплеры, API и расширения, но генерация идёт быстрее. На M3 Pro короткая пятишаговая генерация DPM++ SDE с CFG 1.15 упала с 8–10 секунд до 3–7 секунд. На M1 Mac mini в сопоставимом тесте время снизилось с 12.8 до 8.7 секунд — это примерно 32% меньше задержки.
Главное — не заменять Automatic1111, а встроить нативные для Apple куски кода в те места, где Metal реально выигрывает. Например, для SD 1.x форм attention добавлен путь Metal Flash Attention, но только когда замеры показывают, что он быстрее. В остальных случаях работает обычный PyTorch SDPA.
Критичной оказалась отправка command buffer. Раньше native extension коммитил MPS command buffer после каждого вызова attention. При короткой генерации это съедало заметную часть времени. Форк интегрировал Metal-код в текущий MPS stream PyTorch, и лишние коммиты исчезли.
Ещё одна оптимизация — учёт unified memory. На Apple Silicon GPU и система делят одну физическую память. Вместо фиксированного порога VRAM форк оценивает стоимость attention по объёму доступной памяти и выбирает sub-quadratic fallback с динамическим размером чанков. Для K/V чанков используется online softmax: не копятся все частичные результаты, а поддерживается бегущий максимум и взвешенная сумма.
Кроме того, удалены устаревшие обходные пути для старых багов MPS, включено PYTORCH_MPS_PREFER_METAL=1 и убран апкаст в FP16 для короткого пути. Написан fused Metal kernel для GroupNorm + SiLU, которые в SD 1.x UNet встречаются постоянно.
Есть и отдельная история — NGMS (Negative Guidance Minimum Sigma). Он пропускает unconditional guidance на части шагов. Это ускоряет, но меняет расчёт и результат, поэтому записывается в PNG metadata. Это не то же самое, что ускорение движка.
Некоторые эксперименты не сработали. Packed QKV проекции дали 0.26% замедления. Целые residual blocks в MPSGraph: микро-бенчмарки показывали ускорение до 9%, но полная генерация стала на 1% медленнее. Так что их выпилили. «Микро-бенчмарки номинируют изменения, полные генерации их выбирают».
В итоге форк — это всего четыре коммита поверх dev-ветки Automatic1111. Все неподдерживаемые случаи откатываются к PyTorch. Нативные расширения самопроверяются в subprocess при старте, чтобы не уронить WebUI. Это всё ещё Automatic1111, просто с меньшим временем ожидания на границах между Python, PyTorch, MPSGraph и Metal.