Buckets:

mishig's picture
|
download
raw
14.4 kB
# Precisão e compilação
Precisão reduzida e compilação são duas formas de acelerar a inferência do Diffusers. Carregue os pesos em `bfloat16` ou `float16` e, em seguida, compile o denoiser (o UNet ou o transformer) com `torch.compile` ou compilação regional.
## Tipo de dados do modelo
A precisão e o tipo de dados dos pesos do modelo afetam a velocidade de inferência, pois uma precisão maior exige mais memória para carregar e mais tempo para executar os cálculos. O Diffusers carrega os pesos do modelo em `float32` quando você omite `dtype`, portanto, alterar o tipo de dados é uma maneira simples de obter inferência mais rápida rapidamente.
`bfloat16` é semelhante a `float16`, mas é mais robusto a erros numéricos. O suporte de hardware para `bfloat16` varia, mas a maioria das GPUs modernas é capaz de suportar `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` é semelhante a `bfloat16`, mas pode ser mais suscetível a erros numéricos.
```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]
```
O modo [TensorFloat-32](https://blogs.nvidia.com/blog/2020/05/14/tensorfloat-32-precision-format/) (`tf32`) é suportado em GPUs NVIDIA Ampere e mais recentes e ele executa as operações de convolução e multiplicação de matrizes em `tf32`. O armazenamento e as demais operações permanecem em `float32`. Isso acelera as operações que rodam em `float32`, portanto, é mais útil quando o pipeline ou partes dele permanecem em `float32`.
O PyTorch habilita o modo `tf32` apenas para convoluções por padrão e você precisará habilitá-lo explicitamente para multiplicações de matrizes.
```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.float32
).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]
```
Consulte a documentação de [treinamento com precisão mista](https://huggingface.co/docs/transformers/en/perf_train_gpu_one#mixed-precision) para mais detalhes.
## Atenção de produto escalar
[Scaled dot product attention (SDPA)](https://pytorch.org/docs/stable/generated/torch.nn.functional.scaled_dot_product_attention.html) é a atenção padrão no PyTorch 2.0 e versões posteriores, por meio de `AttnProcessor2_0` ou do backend `native` do despachador de atenção. O PyTorch seleciona um kernel de SDPA para o seu hardware. Para FlashAttention, SageAttention, xFormers, kernels do Hub e outros backends, consulte [Attention backends](./attention_backends).
## torch.compile
[torch.compile](https://pytorch.org/tutorials/intermediate/torch_compile_tutorial.html) acelera a inferência compilando o código e as operações do PyTorch em kernels otimizados. Normalmente, você compila o denoiser, que domina o tempo de execução, seja `pipeline.unet` ou `pipeline.transformer`, e às vezes também o VAE.
Ative as seguintes configurações do compilador para máxima velocidade (consulte a [lista completa](https://github.com/pytorch/pytorch/blob/main/torch/_inductor/config.py) para mais opções).
```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
```
Carregue e compile o denoiser e o VAE. Use `pipeline.unet` em pipelines UNet, como o Stable Diffusion XL, ou `pipeline.transformer` em pipelines Flux e DiT. Existem vários modos diferentes para você escolher, mas `"max-autotune"` busca os kernels mais rápidos e usa CUDA graphs. Os CUDA graphs reduzem o overhead ao lançar múltiplas operações de GPU por meio de uma única operação de CPU.
Alterar o layout de memória para [channels_last](./memory#torchchannelslast) também pode acelerar modelos com muitas convoluções, como UNets e VAEs. Faça um benchmark primeiro, pois alguns modelos ficam mais lentos.
```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.unet = torch.compile(
pipeline.unet, mode="max-autotune", fullgraph=True
)
pipeline.vae.to(memory_format=torch.channels_last)
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]
```
A compilação é lenta na primeira vez, especialmente com `"max-autotune"`, porque o compilador busca kernels e continua usando o mesmo objeto de pipeline compilado em seguida (veja [Cache de tempo de compilação](https://docs.pytorch.org/tutorials/recipes/torch_compile_caching_tutorial.html) e [Configuração de cache](https://docs.pytorch.org/tutorials/recipes/torch_compile_caching_configuration_tutorial.html) para saber como configurar o comportamento de cache). Chamar o pipeline compilado com um tamanho de imagem diferente dispara a recompilação.
### Compilação de formas dinâmicas
`torch.compile` acompanha as formas e condições de entrada e, se estas forem diferentes, recompila o modelo. Por exemplo, se um modelo for compilado em uma imagem de resolução 1024x1024 e usado em uma imagem com resolução diferente, isso aciona a recompilação.
Para evitar recompilação, adicione `dynamic=True` para tentar gerar um kernel mais dinâmico e evitar recompilação quando as condições mudarem.
```diff
+ torch.fx.experimental._config.use_duck_shape = False
+ pipeline.unet = torch.compile(
pipeline.unet, fullgraph=True, dynamic=True
)
```
Especificar `use_duck_shape=False` instrui o compilador se ele deve usar a mesma variável simbólica para representar tamanhos de entrada que são iguais. Para mais detalhes, confira este [comentário](https://github.com/huggingface/diffusers/pull/11327#discussion_r2047659790).
Nem todos os modelos podem se beneficiar da compilação dinâmica imediatamente e podem exigir alterações. Consulte este [PR](https://github.com/huggingface/diffusers/pull/11297/) que melhorou a implementação do [AuraFlowPipeline](/docs/diffusers/main/pt/api/pipelines/aura_flow#diffusers.AuraFlowPipeline) para se beneficiar da compilação dinâmica.
Sinta-se à vontade para abrir uma issue se a compilação dinâmica não funcionar como esperado para um modelo do Diffusers.
### Compilação regional
[Compilação regional](https://docs.pytorch.org/tutorials/recipes/regional_compilation.html) reduz a latência de inicialização ao compilar apenas o *bloco pequeno e repetido com frequência* de um modelo — tipicamente uma camada de transformer — e permite reutilizar os artefatos compilados para cada ocorrência subsequente. Para muitas arquiteturas de difusão, isso proporciona acelerações de tempo de execução comparáveis às da compilação de grafo completo e pode reduzir o tempo de compilação em até 8–10x.
Use o método [compile_repeated_blocks()](/docs/diffusers/main/pt/api/models/overview#diffusers.ModelMixin.compile_repeated_blocks), um auxiliar que encapsula `torch.compile`, no denoiser. Chame-o em `pipeline.unet` ou `pipeline.transformer`, dependendo do pipeline.
```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"
pipeline.unet.compile_repeated_blocks(fullgraph=True)
```
Para habilitar a compilação regional para um novo modelo, defina `_repeated_blocks` com os nomes das classes dos blocos repetidos (strings). Para o UNet do SDXL, use `BasicTransformerBlock`. Os denoisers Transformer listam os nomes das classes de seus blocos repetidos da mesma forma.
```py
_repeated_blocks = ["BasicTransformerBlock"]
```
Há também um método [compile_regions](https://github.com/huggingface/accelerate/blob/273799c85d849a1954a4f2e65767216eb37fa089/src/accelerate/utils/other.py#L78) no [Accelerate](https://huggingface.co/docs/accelerate/index) que seleciona automaticamente os blocos candidatos em um modelo para compilação. O restante do grafo é compilado separadamente. Isso é útil para experimentos rápidos, pois há menos opções para você definir quais blocos compilar ou ajustar as flags de compilação.
```bash
pip install -U accelerate
```
```py
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/main/pt/api/models/overview#diffusers.ModelMixin.compile_repeated_blocks) é intencionalmente explícito. Liste os blocos a repetir em `_repeated_blocks` e o helper compila apenas esses blocos. Ele oferece um comportamento previsível e facilita o raciocínio sobre a reutilização do cache em uma linha de código.
### Quebras de gráfico
Defina `fullgraph=True` para que o torch.compile gere um erro em caso de quebra de grafo, em vez de dividir o grafo silenciosamente, o que reduz a aceleração.
### Sincronização de GPU
Após cada previsão do denoiser, o pipeline chama o método `step` do scheduler, que indexa `sigmas`. Manter `sigmas` na GPU pode forçar uma sincronização CPU↔GPU a cada passo. Esse custo é fácil de ignorar até que o denoiser seja compilado. Prefira deixar `sigmas` na CPU (schedulers do Diffusers, como o Euler, já fazem isso).
### Benchmarks
Consulte o conjunto de dados [diffusers/benchmarks](https://huggingface.co/datasets/diffusers/benchmarks) para ver dados de latência de inferência e uso de memória para pipelines compilados.
O repositório [diffusers-torchao](https://github.com/sayakpaul/diffusers-torchao#benchmarking-results) também contém resultados de benchmarking para as versões compiladas do Flux e do CogVideoX.
## Kernels
[Kernels](https://huggingface.co/docs/kernels/index) é uma biblioteca para construir, distribuir e carregar kernels de computação otimizados no [Hub](https://huggingface.co/kernels-community). Ela suporta kernels de [atenção](./attention_backends#set-a-backend-on-the-model) e kernels CUDA personalizados para operações como RMSNorm, GEGLU, RoPE e AdaLN.
O guia de [Integração do Pipeline do Diffusers](https://github.com/huggingface/kernels/blob/main/kernel-builder/skills/cuda-kernels/references/diffusers-integration.md) mostra como integrar um kernel com a habilidade [add cuda-kernels](https://github.com/huggingface/kernels/blob/main/kernel-builder/skills/cuda-kernels/SKILL.md). Essa habilidade permite que um agente, como Claude ou Codex, escreva kernels personalizados voltados para um modelo específico e seu hardware. O post [Custom kernels for all from Codex and Claude](https://huggingface.co/blog/custom-cuda-kernels-agent-skills) traz mais detalhes.
Por exemplo, um kernel RMSNorm personalizado (gerado pela skill `add cuda-kernels`) com [torch.compile](#torchcompile) acelera a geração do LTX-Video em 1,43x em um H100.
<iframe src="https://huggingface.co/datasets/docs-benchmarks/kernel-ltx-video/embed/viewer/default/train" frameborder="0" width="100%" height="560px"
>
## Quantização dinâmica
A quantização dinâmica de ativação int8 está disponível no [torchao](../quantization/torchao). Use [TorchAoConfig](/docs/diffusers/main/pt/api/quantization#diffusers.TorchAoConfig) com uma configuração como [`Int8DynamicActivationInt8WeightConfig`](https://docs.pytorch.org/ao/stable/api_reference/generated/torchao.quantization.Int8DynamicActivationInt8WeightConfig.html), ou a API `quantize_` do torchao. Não use o helper mais antigo `apply_dynamic_quant`.
## Matrizes de projeção fundidas
> [!WARNING]
> `~DiffusionPipeline.fuse_qkv_projections` é experimental.
Uma entrada é projetada em três subespaços, representados pelas matrizes de projeção Q, K e V, em um bloco de atenção. Essas projeções são tipicamente calculadas separadamente, mas é possível combiná-las horizontalmente em uma única matriz e realizar a projeção em uma única etapa. Isso aumenta o tamanho das multiplicações de matrizes das projeções de entrada e também melhora o impacto da quantização.
```py
pipeline.fuse_qkv_projections()
```
## Próximas etapas
- Leia o post no blog [Presenting Flux Fast: Making Flux go brrr on H100s](https://pytorch.org/blog/presenting-flux-fast-making-flux-go-brrr-on-h100s/) para saber mais sobre como você pode combinar todas essas otimizações com [TorchInductor](https://docs.pytorch.org/docs/stable/torch.compiler.html) e [AOTInductor](https://docs.pytorch.org/docs/stable/torch.compiler_aot_inductor.html) para uma aceleração de ~2,5x usando as receitas de [flux-fast](https://github.com/huggingface/flux-fast).
Essas receitas suportam hardware AMD e [Flux.1 Kontext Dev](https://huggingface.co/black-forest-labs/FLUX.1-Kontext-dev).
- Consulte o post no blog [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/) para maximizar o desempenho com `torch.compile` em modelos de difusão.

Xet Storage Details

Size:
14.4 kB
·
Xet hash:
6271cf967a319ddcbdcb26bc4f2f97044eb7108627ba6e6e287ca896af7ecce5

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