# Core ML로 Stable Diffusion 실행 방법

[Core ML](https://developer.apple.com/documentation/coreml)은 Apple 프레임워크에서 지원하는 모델 형식 및 머신러닝 라이브러리입니다. macOS 또는 iOS/iPadOS 앱에서 Stable Diffusion 모델을 실행하는 데 관심이 있다면, 이 가이드는 기존 PyTorch 체크포인트를 Core ML 형식으로 변환하고 Python 또는 Swift로 추론에 사용하는 방법을 보여줍니다.

Core ML 모델은 Apple 기기에 사용 가능한 모든 컴퓨트 엔진을 활용할 수 있습니다: CPU, GPU, 그리고 Apple Neural Engine(ANE, Apple Silicon Mac과 최신 iPhone/iPad에 사용 가능한 텐서 최적화 가속기). 모델과 실행되는 기기에 따라 Core ML은 컴퓨트 엔진을 혼합하여 사용할 수도 있습니다. 예를 들어, 모델의 일부는 CPU에서, 다른 일부는 GPU에서 실행될 수 있습니다.

> [!TIP]
> `diffusers` Python 코드베이스를 PyTorch에 내장된 `mps` 가속기를 사용하여 Apple Silicon Mac에서도 실행할 수 있습니다. 이 방식은 [mps 가이드](mps)에서 자세히 설명되어 있지만, 네이티브 앱과 호환되지 않습니다.

## Stable Diffusion Core ML 체크포인트

Stable Diffusion 가중치(또는 체크포인트)는 PyTorch 형식으로 저장되므로, 네이티브 앱에서 사용하려면 Core ML 형식으로 변환해야 합니다.

다행히도 Apple 엔지니어가 `diffusers`를 기반으로 PyTorch 체크포인트를 Core ML로 변환하는 [변환 도구](https://github.com/apple/ml-stable-diffusion#-converting-models-to-core-ml)를 개발했습니다.

모델을 변환하기 전에 Hugging Face Hub를 살펴보는 시간을 가져 보세요. 관심 있는 모델이 이미 Core ML 형식으로 제공되고 있을 가능성이 높습니다:

- [Apple](https://huggingface.co/apple) 조직에는 Stable Diffusion 1.4, 1.5, 2.0 base, 2.1 base 버전이 포함되어 있습니다
- [coreml community](https://huggingface.co/coreml-community)에는 커스텀 파인튜닝된 모델이 포함되어 있습니다
- 이 [필터](https://huggingface.co/models?pipeline_tag=text-to-image&library=coreml&p=2&sort=likes)를 사용하여 사용 가능한 모든 Core ML 체크포인트를 반환합니다

관심 있는 모델을 찾을 수 없는 경우, Apple의 [Core ML로 모델 변환](https://github.com/apple/ml-stable-diffusion#-converting-models-to-core-ml) 지침을 따르는 것을 권장합니다.

## 사용할 Core ML 변형 선택

Stable Diffusion 모델은 다양한 목적을 위해 설계된 서로 다른 Core ML 변형으로 변환할 수 있습니다:

- 사용할 attention 블록의 유형입니다. attention 연산은 이미지 표현 내 서로 다른 영역 간의 관계를 "주목"하고, 이미지와 텍스트 표현이 어떻게 관련되어 있는지를 이해하는 데 사용됩니다. attention은 계산 및 메모리 집약적이므로, 다양한 장치의 하드웨어 특성을 고려한 여러 구현 방식이 존재합니다. Core ML Stable Diffusion 모델에는 두 가지 attention 변형이 있습니다:
    * `split_einsum`([Apple에서 도입](https://machinelearning.apple.com/research/neural-engine-transformers))은 최신 iPhone, iPad 및 M 시리즈 컴퓨터에서 사용할 수 있는 ANE 디바이스를 위해 최적화되어 있습니다.
    * "original" attention(`diffusers`에서 사용되는 기본 구현)는 CPU/GPU와만 호환되며 ANE와는 호환되지 않습니다. `original` attention을 사용하여 CPU + GPU에서 모델을 실행하는 것이 ANE보다 *더 빠를 수 있습니다*. 추가적인 세부 사항은 [이 성능 벤치마크](https://huggingface.co/blog/fast-mac-diffusers#performance-benchmarks) 및 [커뮤니티에서 제공한 추가 측정 결과](https://github.com/huggingface/swift-coreml-diffusers/issues/31)를 참고하세요.

- 지원되는 추론 프레임워크입니다.
    * `packages`는 Python 추론에 적합합니다. 이는 네이티브 앱에 통합하기 전에 변환된 Core ML 모델을 테스트하거나, Core ML 성능을 탐색하되 네이티브 앱 지원이 필요하지 않은 경우에 사용할 수 있습니다. 예를 들어, 웹 UI를 가진 애플리케이션은 Python Core ML 백엔드를 완벽하게 사용할 수 있습니다.
    * Swift 코드를 사용하려면 `compiled` 모델이 필요합니다. Hub의 `compiled` 모델은 iOS 및 iPadOS 기기와 호환성을 위해 대형 UNet 모델 가중치를 여러 파일로 분리합니다. 이는 [`--chunk-unet` 변환 옵션](https://github.com/apple/ml-stable-diffusion#-converting-models-to-core-ml)에 해당합니다. 네이티브 앱을 지원하려면 `compiled` 변형을 선택해야 합니다.

공식 Core ML Stable Diffusion [모델](https://huggingface.co/apple/coreml-stable-diffusion-v1-4/tree/main)에는 이러한 변형이 포함되지만, 커뮤니티의 모델은 다를 수 있습니다:

```
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에서 추론을 실행하려면 `compiled` 버전은 Swift와만 호환되므로 `packages` 폴더에 저장된 버전 중 하나를 사용해야 합니다. `original` 또는 `split_einsum` 어텐션을 사용할지 선택할 수 있습니다.

Hub에서 `original` attention 변형을 `models`이라는 이름의 디렉터리로 다운로드하는 방법은 다음과 같습니다:

```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`은 추론에 허용할 하드웨어를 지정합니다. 다음 옵션 중 하나여야 합니다: `ALL`, `CPU_AND_GPU`, `CPU_ONLY`, `CPU_AND_NE`. 선택적으로 출력 경로와 재현성을 위한 시드도 제공할 수 있습니다.

추론 스크립트는 원래 버전의 Stable Diffusion 모델인 `CompVis/stable-diffusion-v1-4`를 사용한다고 가정합니다. 다른 모델을 사용하는 경우, `--model-version` 옵션을 사용하여 추론 명령줄에서 해당 모델의 Hub id를 *반드시* 지정해야 합니다. 이는 이미 지원되는 모델과 사용자가 직접 학습하거나 파인튜닝한 커스텀 모델 모두에 적용됩니다.

예를 들어, [`stable-diffusion-v1-5/stable-diffusion-v1-5`](https://huggingface.co/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
```

## Swift에서 Core ML 추론

Swift에서 추론을 실행하는 것은 모델이 이미 `mlmodelc` 형식으로 컴파일되어 있기 때문에 Python보다 약간 빠릅니다. 이는 모델이 로드되는 앱 시작 시점에 체감되지만, 이후 여러 번의 생성을 실행하면 체감되지 않습니다.

### 다운로드

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](https://www.swift.org/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` 값은 `all`, `cpuOnly`, `cpuAndGPU`, `cpuAndNeuralEngine` 중 하나여야 합니다.

자세한 내용은 [Apple의 저장소 지침](https://github.com/apple/ml-stable-diffusion)을 참고하세요.

## 지원되는 Diffusers 기능

Core ML 모델 및 추론 코드는 🧨 Diffusers의 많은 기능, 옵션, 유연성을 지원하지 않습니다. 다음 제한 사항을 염두에 두시기 바랍니다:

- Core ML 모델은 추론에만 적합합니다. 학습이나 파인튜닝에는 사용할 수 없습니다.
- Swift로 이식된 스케줄러는 두 가지뿐입니다. Stable Diffusion에서 기본적으로 사용하는 스케줄러와, `diffusers` 구현에서 Swift로 이식한 `DPMSolverMultistepScheduler`입니다. `DPMSolverMultistepScheduler`는 약 절반의 스텝으로 동일한 품질을 생성하므로 사용을 권장합니다.
- 추론 코드에서 negative prompts, classifier-free guidance scale, image-to-image 작업을 사용할 수 있습니다. depth guidance, ControlNet, latent upscaler와 같은 고급 기능은 아직 사용할 수 없습니다.

Apple의 [변환 및 추론 저장소](https://github.com/apple/ml-stable-diffusion)와 저희의 [swift-coreml-diffusers](https://github.com/huggingface/swift-coreml-diffusers) 저장소는 다른 개발자들이 이를 기반으로 구축할 수 있도록 기술 데모로 의도되었습니다.

누락된 기능에 대해 강한 의견을 가지고 계신 경우, 기능 요청을 열거나, 더 좋게는 기여 PR을 열어 주세요 🙂.

## 네이티브 Diffusers Swift 앱

Apple 하드웨어에서 Stable Diffusion을 실행하는 가장 쉬운 방법 중 하나는 `diffusers`와 Apple의 변환 및 추론 저장소를 기반으로 한 [오픈 소스 Swift 저장소](https://github.com/huggingface/swift-coreml-diffusers)를 사용하는 것입니다. 코드를 살펴보고 [Xcode](https://developer.apple.com/xcode/)로 컴파일한 후, 필요에 맞게 수정할 수 있습니다. 편의를 위해 [App Store에 독립형 Mac 앱](https://apps.apple.com/app/diffusers/id1666309574)도 제공되므로, 코드나 IDE를 다룰 필요 없이 바로 사용해 볼 수 있습니다. 개발자로서 Core ML이 Stable Diffusion 앱을 구축하는 최선의 해결책이라고 판단했다면, 이 가이드의 나머지 부분을 참고하여 프로젝트를 시작할 수 있습니다. 여러분이 무엇을 만들지 기대됩니다 🙂.

