Buckets:

mishig's picture
|
download
raw
19.9 kB
# 추론 가속
Diffusion 모델은 추론이 느립니다. 생성은 반복적인 과정으로, 특정 수의 "스텝"에 걸쳐 노이즈가 점진적으로 이미지나 비디오로 정제되기 때문입니다. 이 과정을 가속화하려면 다양한 [스케줄러](../api/schedulers/overview)를 실험해 보거나, 모델 가중치의 정밀도를 낮춰 계산 속도를 높이고, 더 메모리 효율적인 어텐션 메커니즘을 사용하는 등의 방법을 시도해 볼 수 있습니다.
이러한 기법들을 결합하여 함께 사용하면, 단일 기법만 사용할 때보다 추론 속도를 더 빠르게 할 수 있습니다.
이 가이드에서는 추론을 가속하는 방법을 다룹니다.
## 모델 데이터 유형
모델 가중치의 정밀도와 데이터 유형은 추론 속도에 영향을 미칩니다. 정밀도가 높을수록 가중치를 로드하는 데 더 많은 메모리가 필요하고, 연산을 수행하는 데 더 많은 시간이 소요되기 때문입니다. PyTorch는 기본적으로 모델 가중치를 float32 또는 전체 정밀도로 로드하므로, 데이터 유형을 변경하는 것은 추론 속도를 빠르게 하는 간단한 방법입니다.
bfloat16은 float16과 유사하지만 수치 오류에 대해 더 강건합니다. bfloat16에 대한 하드웨어 지원은 다양하지만, 대부분의 최신 GPU는 bfloat16을 지원합니다.
```py
import torch
from diffusers import StableDiffusionXLPipeline
pipeline = StableDiffusionXLPipeline.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0", dtype=torch.bfloat16
).to("cuda") # or "mps", "xpu", "cpu"
prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k"
pipeline(prompt, num_inference_steps=30).images[0]
```
float16은 bfloat16과 유사하지만 수치 오류가 발생할 가능성이 더 높을 수 있습니다.
```py
import torch
from diffusers import StableDiffusionXLPipeline
pipeline = StableDiffusionXLPipeline.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0", dtype=torch.float16
).to("cuda") # or "mps", "xpu", "cpu"
prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k"
pipeline(prompt, num_inference_steps=30).images[0]
```
[TensorFloat-32 (tf32)](https://blogs.nvidia.com/blog/2020/05/14/tensorfloat-32-precision-format/) 모드는 NVIDIA Ampere GPU에서 지원되며, tf32로 컨볼루션 및 행렬 곱셈 연산을 수행합니다. 저장 및 기타 연산은 float32로 유지됩니다. bfloat16 또는 float16과 함께 사용하면 계산 속도가 크게 향상됩니다.
PyTorch는 기본적으로 합성곱(convolution)에 대해서만 tf32 모드를 활성화하며, 행렬 곱셈에 대해서는 명시적으로 활성화해야 합니다.
```py
import torch
from diffusers import StableDiffusionXLPipeline
torch.backends.cuda.matmul.allow_tf32 = True
pipeline = StableDiffusionXLPipeline.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0", dtype=torch.bfloat16
).to("cuda") # or "mps", "xpu", "cpu"
prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k"
pipeline(prompt, num_inference_steps=30).images[0]
```
자세한 내용은 [혼합 정밀도 학습](https://huggingface.co/docs/transformers/en/perf_train_gpu_one#mixed-precision) 문서를 참조하세요.
## 스케일된 도트 프로덕트 어텐션
> [!TIP]
> 메모리 효율적 어텐션은 추론 속도 *및* [메모리 사용량](./memory#memory-efficient-attention)을 최적화합니다!
[Scaled dot product attention (SDPA)](https://pytorch.org/docs/stable/generated/torch.nn.functional.scaled_dot_product_attention.html)는 [FlashAttention](https://github.com/Dao-AILab/flash-attention), [xFormers](https://github.com/facebookresearch/xformers) 및 네이티브 C++ 구현 등 여러 attention backends를 구현합니다. 하드웨어에 가장 최적화된 backends를 자동으로 선택합니다.
PyTorch >= 2.0을 사용하는 경우 SDPA가 기본적으로 활성화되며, 코드에 추가적인 변경 사항은 필요하지 않습니다. 원하시는 경우 다른 attention backends를 실험하여 직접 선택할 수 있습니다. 아래 예제는 [torch.nn.attention.sdpa_kernel](https://pytorch.org/docs/stable/generated/torch.nn.attention.sdpa_kernel.html) 컨텍스트 매니저를 사용하여 효율적인 attention을 활성화합니다.
```py
from torch.nn.attention import SDPBackend, sdpa_kernel
import torch
from diffusers import StableDiffusionXLPipeline
pipeline = StableDiffusionXLPipeline.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0", dtype=torch.bfloat16
).to("cuda") # or "mps", "xpu", "cpu"
prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k"
with sdpa_kernel(SDPBackend.EFFICIENT_ATTENTION):
image = pipeline(prompt, num_inference_steps=30).images[0]
```
## torch.compile
[torch.compile](https://pytorch.org/tutorials/intermediate/torch_compile_tutorial.html)은 PyTorch 코드와 연산을 최적화된 커널로 컴파일하여 추론을 가속화합니다. Diffusers는 일반적으로 UNet, transformer, VAE와 같이 계산 집약적인 모델을 컴파일합니다.
최대 속도를 위해 다음 컴파일러 설정을 활성화하세요(추가 옵션은 [전체 목록](https://github.com/pytorch/pytorch/blob/main/torch/_inductor/config.py)을 참조하세요).
```py
import torch
from diffusers import StableDiffusionXLPipeline
torch._inductor.config.conv_1x1_as_mm = True
torch._inductor.config.coordinate_descent_tuning = True
torch._inductor.config.epilogue_fusion = False
torch._inductor.config.coordinate_descent_check_all_directions = True
```
UNet과 VAE를 로드하고 컴파일합니다. 선택할 수 있는 여러 가지 모드가 있지만, `"max-autotune"`은 CUDA graph로 컴파일하여 가장 빠른 속도를 최적화합니다. CUDA graphs는 단일 CPU 연산을 통해 여러 GPU 연산을 실행함으로써 오버헤드를 효과적으로 줄여줍니다.
> [!TIP]
> PyTorch 2.3.1에서는 torch.compile의 캐싱 동작을 제어할 수 있습니다. 이는 여러 컴파일 플래그에 대해 그리드 서치를 수행하여 최적의 구성을 찾는 `"max-autotune"`와 같은 컴파일 모드에서 특히 유용합니다. [torch.compile의 Compile Time Caching](https://pytorch.org/tutorials/recipes/torch_compile_caching_tutorial.html) 튜토리얼에서 자세히 알아보세요.
메모리 레이아웃을 [channels_last](./memory#torchchannelslast)로 변경하면 메모리와 추론 속도도 최적화됩니다.
```py
pipeline = StableDiffusionXLPipeline.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0", dtype=torch.float16
).to("cuda") # or "mps", "xpu", "cpu"
pipeline.unet.to(memory_format=torch.channels_last)
pipeline.vae.to(memory_format=torch.channels_last)
pipeline.unet = torch.compile(
pipeline.unet, mode="max-autotune", fullgraph=True
)
pipeline.vae.decode = torch.compile(
pipeline.vae.decode,
mode="max-autotune",
fullgraph=True
)
prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k"
pipeline(prompt, num_inference_steps=30).images[0]
```
컴파일은 첫 번째 실행 시 느리지만, 한 번 컴파일된 후에는 훨씬 빠릅니다. 동일한 유형의 추론 작업에만 컴파일된 파이프라인을 사용하도록 하십시오. 다른 이미지 크기로 컴파일된 파이프라인을 호출하면 컴파일이 다시 트리거되며, 이는 느리고 비효율적입니다.
### 동적 형상 컴파일
> [!TIP]
> 더 나은 지원을 위해 항상 PyTorch의 nightly 버전을 사용하도록 하십시오.
`torch.compile`은 입력 형상과 조건을 추적하며, 이들이 다르면 모델을 다시 컴파일합니다. 예를 들어, 1024x1024 해상도의 이미지로 컴파일된 모델이 다른 해상도의 이미지에 사용되면 재컴파일이 트리거됩니다.
재컴파일링을 피하려면 `dynamic=True`를 추가하여 조건이 변경될 때 재컴파일링을 피할 수 있는 더 동적인 커널을 생성하도록 시도해 보세요.
```diff
+ torch.fx.experimental._config.use_duck_shape = False
+ pipeline.unet = torch.compile(
pipeline.unet, fullgraph=True, dynamic=True
)
```
`use_duck_shape=False`를 지정하면 컴파일러가 동일한 크기의 입력을 동일한 기호 변수로 표현할지 여부를 결정합니다. 자세한 내용은 이 [댓글](https://github.com/huggingface/diffusers/pull/11327#discussion_r2047659790)을 확인하세요.
모든 모델이 기본적으로 동적 컴파일의 이점을 누릴 수 있는 것은 아니며, 일부 모델은 변경이 필요할 수 있습니다. [AuraFlowPipeline](/docs/diffusers/v0.43.0/ko/api/pipelines/aura_flow#diffusers.AuraFlowPipeline) 구현을 개선하여 동적 컴파일의 이점을 누릴 수 있도록 한 이 [PR](https://github.com/huggingface/diffusers/pull/11297/)을 참고하세요.
Diffusers 모델에서 동적 컴파일이 예상대로 작동하지 않는 경우, 자유롭게 이슈를 열어 주세요.
### 지역별 컴파일
[Regional compilation](https://docs.pytorch.org/tutorials/recipes/regional_compilation.html)은 모델의 *작고 반복적으로 실행되는 블록*, 일반적으로 transformer layer만 컴파일하여 콜드 스타트 지연 시간을 줄이고, 이후 모든 발생 위치에서 컴파일된 산출물을 재사용할 수 있게 합니다. 많은 diffusion 아키텍처의 경우, 이는 전체 그래프 컴파일과 동일한 런타임 속도 향상을 제공하면서 컴파일 시간을 8~10배 줄여줍니다.
아래와 같이 transformer 모델과 같은 컴포넌트에 `torch.compile`을 래핑하는 헬퍼인 [compile_repeated_blocks()](/docs/diffusers/v0.43.0/ko/api/models/overview#diffusers.ModelMixin.compile_repeated_blocks) 메서드를 사용합니다.
```py
# pip install -U diffusers
import torch
from diffusers import StableDiffusionXLPipeline
pipeline = StableDiffusionXLPipeline.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0",
dtype=torch.float16,
).to("cuda") # or "mps", "xpu", "cpu"
# compile only the repeated transformer layers inside the UNet
pipeline.unet.compile_repeated_blocks(fullgraph=True)
```
새 모델에 대한 지역 컴파일을 활성화하려면, 컴파일할 블록의 클래스 이름(문자열)을 포함하는 `_repeated_blocks` 속성을 모델 클래스에 추가하세요.
```py
class MyUNet(ModelMixin):
_repeated_blocks = ("Transformer2DModel",) # ← compiled by default
```
> [!TIP]
> 지역별 컴파일 예제가 더 필요하면 [PR](https://github.com/huggingface/diffusers/pull/11705)을 참고하세요.
[Accelerate](https://huggingface.co/docs/accelerate/index)에는 모델에서 컴파일할 후보 블록을 자동으로 선택하는 [compile_regions](https://github.com/huggingface/accelerate/blob/273799c85d849a1954a4f2e65767216eb37fa089/src/accelerate/utils/other.py#L78) 메서드도 있습니다. 나머지 그래프는 별도로 컴파일됩니다. 컴파일할 블록을 지정하거나 컴파일 플래그를 조정할 수 있는 옵션이 많지 않으므로, 빠른 실험에 유용합니다.
```py
# pip install -U accelerate
import torch
from diffusers import StableDiffusionXLPipeline
from accelerate.utils import compile_regions
pipeline = StableDiffusionXLPipeline.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0", dtype=torch.float16
).to("cuda") # or "mps", "xpu", "cpu"
pipeline.unet = compile_regions(pipeline.unet, mode="reduce-overhead", fullgraph=True)
```
[compile_repeated_blocks()](/docs/diffusers/v0.43.0/ko/api/models/overview#diffusers.ModelMixin.compile_repeated_blocks)는 의도적으로 명시적으로 설계되었습니다. `_repeated_blocks`에 반복할 블록을 나열하면 헬퍼는 해당 블록만 컴파일합니다. 이는 한 줄의 코드로 캐시 재사용에 대한 예측 가능한 동작과 쉬운 추론을 제공합니다.
### 그래프 브레이크
`fullgraph=True`를 torch.compile에 지정하는 것이 중요합니다. 이를 통해 기반 모델에 그래프 브레이크가 발생하지 않도록 보장할 수 있으며, 성능 저하 없이 torch.compile의 이점을 활용할 수 있습니다. UNet과 VAE의 경우, 반환 변수에 접근하는 방식이 달라집니다.
```diff
- latents = unet(
- latents, timestep=timestep, encoder_hidden_states=prompt_embeds
-).sample
+ latents = unet(
+ latents, timestep=timestep, encoder_hidden_states=prompt_embeds, return_dict=False
+)[0]
```
### GPU 동기화
`step()` 함수는 denoiser가 예측을 할 때마다 scheduler에서 [호출](https://github.com/huggingface/diffusers/blob/1d686bac8146037e97f3fd8c56e4063230f71751/src/diffusers/pipelines/stable_diffusion_xl/pipeline_stable_diffusion_xl.py#L1228)되며, `sigmas` 변수는 [인덱싱](https://github.com/huggingface/diffusers/blob/1d686bac8146037e97f3fd8c56e4063230f71751/src/diffusers/schedulers/scheduling_euler_discrete.py#L476)됩니다. GPU에 배치되면 CPU와 GPU 간의 통신 동기화 때문에 지연이 발생합니다. denoiser가 이미 컴파일된 경우 이 지연이 더 뚜렷하게 나타납니다.
일반적으로 통신 동기화 및 지연을 피하기 위해 `sigmas`는 [CPU에 유지](https://github.com/huggingface/diffusers/blob/35a969d297cba69110d175ee79c59312b9f49e1e/src/diffusers/schedulers/scheduling_euler_discrete.py#L240)되어야 합니다.
> [!TIP]
> Refer to the [torch.compile and Diffusers: A Hands-On Guide to Peak Performance](https://pytorch.org/blog/torch-compile-and-diffusers-a-hands-on-guide-to-peak-performance/) blog post for maximizing performance with `torch.compile` for diffusion models.
### 벤치마크
컴파일된 파이프라인의 추론 지연 시간 및 메모리 사용량 데이터를 확인하려면 [diffusers/benchmarks](https://huggingface.co/datasets/diffusers/benchmarks) 데이터셋을 참조하세요.
[diffusers-torchao](https://github.com/sayakpaul/diffusers-torchao#benchmarking-results) 저장소에는 Flux와 CogVideoX의 컴파일된 버전 벤치마킹 결과도 포함되어 있습니다.
## 커널
[Kernels](https://huggingface.co/docs/kernels/index)는 [Hub](https://huggingface.co/kernels-community)에서 최적화된 compute kernel을 빌드, 배포 및 로드하기 위한 라이브러리입니다. RMSNorm, GEGLU, RoPE, AdaLN과 같은 연산을 위한 [attention](./attention_backends#setattentionbackend) kernel 및 사용자 정의 CUDA kernel을 지원합니다.
[Diffusers Pipeline Integration](https://github.com/huggingface/kernels/blob/main/kernel-builder/skills/cuda-kernels/references/diffusers-integration.md) 가이드는 커널을 [add cuda-kernels](https://github.com/huggingface/kernels/blob/main/kernel-builder/skills/cuda-kernels/SKILL.md) 스킬과 통합하는 방법을 보여줍니다. 이 스킬을 사용하면 Claude나 Codex와 같은 에이전트가 특정 모델과 사용자의 하드웨어를 대상으로 하는 커스텀 커널을 작성할 수 있습니다.
> [!TIP]
> Install the [add cuda-kernels](https://github.com/huggingface/kernels/blob/main/kernel-builder/skills/cuda-kernels/SKILL.md) skill to teach an agent how to write a kernel. The [Custom kernels for all from Codex and Claude](https://huggingface.co/blog/custom-cuda-kernels-agent-skills) blog post covers this in more detail.
예를 들어, `add cuda-kernels` 스킬로 생성된 커스텀 RMSNorm 커널에 [torch.compile](#torchcompile)을 적용하면 H100에서 LTX-Video 생성 속도가 1.43배 빨라집니다.
<iframe src="https://huggingface.co/datasets/docs-benchmarks/kernel-ltx-video/embed/viewer/default/train" frameborder="0" width="100%" height="560px"
>
## 동적 양자화
[Dynamic quantization](https://docs.pytorch.org/ao/main/api_reference/generated/torchao.quantization.Int8DynamicActivationInt8WeightConfig.html)은 정밀도를 낮추어 더 빠른 수학 연산을 가능하게 함으로써 추론 속도를 향상시킵니다. 이 특정 양자화 방식은 고정된 스케일링 계수를 사용하는 대신 런타임의 데이터에 기반하여 활성화(activation)의 스케일링 방식을 결정합니다. 그 결과, 스케일링 계수가 데이터에 더 정확하게 맞춰집니다.
아래 예시에서는 [torchao](../quantization/torchao) 라이브러리를 사용하여 UNet과 VAE에 [동적 int8 양자화](https://docs.pytorch.org/ao/main/api_reference/generated/torchao.quantization.Int8DynamicActivationInt8WeightConfig.html)를 적용합니다.
> [!TIP]
> Diffusers의 torchao 통합 사용법에 대해 자세히 알아보려면 [torchao](../quantization/torchao) 문서를 참조하세요.
최대 속도를 위해 컴파일러 태그를 구성합니다.
```py
import torch
from torchao import apply_dynamic_quant
from diffusers import StableDiffusionXLPipeline
torch._inductor.config.conv_1x1_as_mm = True
torch._inductor.config.coordinate_descent_tuning = True
torch._inductor.config.epilogue_fusion = False
torch._inductor.config.coordinate_descent_check_all_directions = True
torch._inductor.config.force_fuse_int_mm_with_mul = True
torch._inductor.config.use_mixed_mm = True
```
동적 양자화에서 이점을 얻지 못하는 UNet과 VAE의 일부 선형 레이어를 [dynamic_quant_filter_fn](https://github.com/huggingface/diffusion-fast/blob/0f169640b1db106fe6a479f78c1ed3bfaeba3386/utils/pipeline_utils.py#L16)으로 필터링합니다.
```py
pipeline = StableDiffusionXLPipeline.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0", dtype=torch.bfloat16
).to("cuda") # or "mps", "xpu", "cpu"
apply_dynamic_quant(pipeline.unet, dynamic_quant_filter_fn)
apply_dynamic_quant(pipeline.vae, dynamic_quant_filter_fn)
prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k"
pipeline(prompt, num_inference_steps=30).images[0]
```
## Fused projection matrices
> [!WARNING]
> [fuse_qkv_projections](https://github.com/huggingface/diffusers/blob/58431f102cf39c3c8a569f32d71b2ea8caa461e1/src/diffusers/pipelines/pipeline_utils.py#L2034) 메서드는 실험적이며 지원 범위가 주로 Stable Diffusion 파이프라인으로 제한됩니다. 다른 파이프라인에서 이를 활성화하는 방법에 대해서는 이 [PR](https://github.com/huggingface/diffusers/pull/6179)을 참고하세요.
Q, K, V 투영 행렬로 표현되는 세 개의 부분 공간으로 입력이 투영되는 attention 블록에서, 이러한 투영은 일반적으로 개별적으로 계산됩니다. 하지만 이를 가로로 결합하여 단일 행렬로 만들고, 한 단계에서 투영을 수행할 수 있습니다. 이렇게 하면 입력 투영의 행렬 곱셈 크기가 증가하고, 양자화의 효과도 향상됩니다.
```py
pipeline.fuse_qkv_projections()
```
## 리소스
- [Presenting Flux Fast: Making Flux go brrr on H100s](https://pytorch.org/blog/presenting-flux-fast-making-flux-go-brrr-on-h100s/) 블로그 포스트를 읽어 [flux-fast](https://github.com/huggingface/flux-fast)의 레시피를 사용하여 [TorchInductor](https://docs.pytorch.org/docs/stable/torch.compiler.html)와 [AOTInductor](https://docs.pytorch.org/docs/stable/torch.compiler_aot_inductor.html)와 이 모든 최적화를 결합하여 약 2.5배의 속도 향상을 달성하는 방법에 대해 자세히 알아보세요.
이 레시피는 AMD 하드웨어와 [Flux.1 Kontext Dev](https://huggingface.co/black-forest-labs/FLUX.1-Kontext-dev)를 지원합니다.
- [torch.compile과 Diffusers: 최고의 성능을 위한 실전 가이드](https://pytorch.org/blog/torch-compile-and-diffusers-a-hands-on-guide-to-peak-performance/) 블로그 포스트를 읽어보세요
`torch.compile`를 사용할 때 성능을 극대화하려면

Xet Storage Details

Size:
19.9 kB
·
Xet hash:
ff75ef7ce4bf45090cabbae3f14f215d5f259298db3bf7cf20318dc513e1f138

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.