Após um ano de atraso, fico feliz em anunciar que pretendo construir um novo projeto confortável para fornecer a velocidade de inferência mais rápida para todos os modelos que executam com ComfyUI . Acabou de começar e espero que seja um ótimo projeto? .. Por favor, continue se concentrando nisso e me dê feedbacks?!
OBSERVAÇÃO
O desenvolvimento ativo no stable-fast foi pausado. Atualmente, estou trabalhando em um novo projeto baseado em torch._dynamo direcionado a novos modelos, como stable-cascade , SD3 e Sora como Mmodels. Seria mais rápido e mais flexível, além de apoiar mais backends de hardware do que CUDA .
O contato é bem -vindo.
Discord Channel
stable-fast atinge o desempenho da inferência da SOTA em todos os tipos de modelos difusores, mesmo com a mais recente linha StableVideoDiffusionPipeline . E, diferentemente TensorRT ou AITemplate , que leva dezenas de minutos para compilar um modelo, stable-fast leva apenas alguns segundos para compilar um modelo. stable-fast também suporta dynamic shape , LoRA e ControlNet fora da caixa.
| Modelo | tocha | Torch.compile | Ait | OneFlow | Tensorrt | estável-rápido |
|---|---|---|---|---|---|---|
| SD 1.5 (MS) | 1897 | 1510 | 1158 | 1003 | 991 | 995 |
| SVD-XT (s) | 83 | 70 | 47 |
NOTA : Durante o benchmarking, TensorRT é testado com static batch size e CUDA Graph enabled enquanto stable-fast está funcionando com a forma dinâmica.
stable-fast é uma estrutura de otimização de inferência ultra leve para os difusores Huggingface no NVIDIA GPUS . stable-fast fornece otimização super rápida de inferência, utilizando algumas técnicas e recursos importantes:
stable-fast implementa uma série de operadores de fusão de convolução de CUDNN totalmente funcionais e totalmente compatíveis com todos os tipos de combinações de padrões de computação de polarização Conv + Bias + Add + Act .stable-fast implementa uma série de operadores GEMM fundidos que calculam com precisão fp16 , que é rápida que os padrões de Pytorch (leia e escreva com fp16 enquanto calculam com fp32 ).stable-fast é capaz de fundir GEGLU(x, W, V, b, c) = GELU(xW + b) ⊗ (xV + c) em um kernel Cuda.stable-fast implementa um operador de NHWC GroupNorm + Silu altamente otimizado com Triton do OpenAI, que elimina a necessidade de operadores de permutação de formato de memória.stable-fast melhora a interface torch.jit.trace para torná-la mais adequada para rastrear modelos complexos. Quase todas as partes do StableDiffusionPipeline/StableVideoDiffusionPipeline podem ser rastreadas e convertidas em TorchScript . É mais estável que torch.compile e possui uma sobrecarga significativamente mais baixa da CPU do que torch.compile e suporta ControlNet e Lora .stable-fast pode capturar o UNet , VAE e TextEncoder no formato do gráfico CUDA, que pode reduzir a sobrecarga da CPU quando o tamanho do lote é pequeno. Essa implementação também suporta forma dinâmica.stable-fast apenas usa o Xformers e o torna compatível com o TorchScript . Meu próximo objetivo é manter stable-fast como uma das estruturas de otimização de inferência mais rápidas para diffusers e também fornecer uma redução de aceleração e VRAM para transformers . Na verdade, eu já uso stable-fast para otimizar o LLMS e obter uma aceleração significativa. Mas ainda preciso fazer algum trabalho para torná -lo mais estável e fácil de usar e fornecer uma interface de usuário estável.
stable-fast é otimizado especificamente para difusores Huggingface . Ele atinge um alto desempenho em muitas bibliotecas. E fornece uma velocidade de compilação muito rápida em apenas alguns segundos. É significativamente mais rápido que torch.compile , TensorRT e AITemplate no tempo de compilação.stable-fast funciona como uma estrutura de plug-in para PyTorch . Ele utiliza a funcionalidade e as infraestruturas existentes PyTorch e é compatível com outras técnicas de aceleração, bem como técnicas populares de ajuste fino e soluções de implantação.stable-fast é compatível com todos os tipos de HuggingFace Diffusers e versões PyTorch . Também é compatível com ControlNet e LoRA . E até suporta a última caixa StableVideoDiffusionPipeline pronta! NOTA : Atualmente, stable-fast é testado apenas no Linux e WSL2 in Windows . Você precisa instalar o Pytorch com suporte CUDA no primeiro (versões de 1,12 a 2.1).
Eu testei apenas stable-fast com torch>=2.1.0 , xformers>=0.0.22 e triton>=2.1.0 no CUDA 12.1 e Python 3.10 . Outras versões podem construir e executar com sucesso, mas isso não é garantido.
Faça o download da roda correspondente ao seu sistema na página Releases e instale -a com pip3 install <wheel file> .
Atualmente, as rodas Linux e Windows estão disponíveis.
# Change cu121 to your CUDA version and <wheel file> to the path of the wheel file.
# And make sure the wheel file is compatible with your PyTorch version.
pip3 install --index-url https://download.pytorch.org/whl/cu121
' torch>=2.1.0 ' ' xformers>=0.0.22 ' ' triton>=2.1.0 ' ' diffusers>=0.19.3 '
' <wheel file> ' # Make sure you have CUDNN/CUBLAS installed.
# https://developer.nvidia.com/cudnn
# https://developer.nvidia.com/cublas
# Install PyTorch with CUDA and other packages at first.
# Windows user: Triton might be not available, you could skip it.
# NOTE: 'wheel' is required or you will meet `No module named 'torch'` error when building.
pip3 install wheel ' torch>=2.1.0 ' ' xformers>=0.0.22 ' ' triton>=2.1.0 ' ' diffusers>=0.19.3 '
# (Optional) Makes the build much faster.
pip3 install ninja
# Set TORCH_CUDA_ARCH_LIST if running and building on different GPU types.
# You can also install the latest stable release from PyPI.
# pip3 install -v -U stable-fast
pip3 install -v -U git+https://github.com/chengzeyi/stable-fast.git@main#egg=stable-fast
# (this can take dozens of minutes) NOTA : Qualquer uso fora sfast.compilers não tem garantia de ser compatível com versões anteriores.
NOTA : Para obter o melhor desempenho, xformers e o OpenAI do triton>=2.1.0 precisa ser instalado e ativado. Pode ser necessário criar xformers a partir da fonte para torná -lo compatível com o seu PyTorch .
stable-fast é capaz de otimizar diretamente StableDiffusionPipeline e StableDiffusionPipelineXL .
import time
import torch
from diffusers import ( StableDiffusionPipeline ,
EulerAncestralDiscreteScheduler )
from sfast . compilers . diffusion_pipeline_compiler import ( compile ,
CompilationConfig )
def load_model ():
model = StableDiffusionPipeline . from_pretrained (
'runwayml/stable-diffusion-v1-5' ,
torch_dtype = torch . float16 )
model . scheduler = EulerAncestralDiscreteScheduler . from_config (
model . scheduler . config )
model . safety_checker = None
model . to ( torch . device ( 'cuda' ))
return model
model = load_model ()
config = CompilationConfig . Default ()
# xformers and Triton are suggested for achieving best performance.
try :
import xformers
config . enable_xformers = True
except ImportError :
print ( 'xformers not installed, skip' )
try :
import triton
config . enable_triton = True
except ImportError :
print ( 'Triton not installed, skip' )
# CUDA Graph is suggested for small batch sizes and small resolutions to reduce CPU overhead.
# But it can increase the amount of GPU memory used.
# For StableVideoDiffusionPipeline it is not needed.
config . enable_cuda_graph = True
model = compile ( model , config )
kwarg_inputs = dict (
prompt =
'(masterpiece:1,2), best quality, masterpiece, best detailed face, a beautiful girl' ,
height = 512 ,
width = 512 ,
num_inference_steps = 30 ,
num_images_per_prompt = 1 ,
)
# NOTE: Warm it up.
# The initial calls will trigger compilation and might be very slow.
# After that, it should be very fast.
for _ in range ( 3 ):
output_image = model ( ** kwarg_inputs ). images [ 0 ]
# Let's see it!
# Note: Progress bar might work incorrectly due to the async nature of CUDA.
begin = time . time ()
output_image = model ( ** kwarg_inputs ). images [ 0 ]
print ( f'Inference time: { time . time () - begin :.3f } s' )
# Let's view it in terminal!
from sfast . utils . term_image import print_image
print_image ( output_image , max_width = 80 )Consulte Exemplos/Optimize_Stable_Diffusion_PiPeline.py para obter mais detalhes.
Você pode verificar este colab para ver como ele funciona na GPU T4:
stable-fast é capaz de otimizar o mais novo pipeline latent consistency model e obter uma aceleração significativa.
Consulte Exemplos/otimize_lcm_pipeline.py para obter mais detalhes sobre como otimizar o modelo SD normal com o LCM Lora. Consulte Exemplos/otimize_lcm_pipeline.py para obter mais detalhes sobre como otimizar o modelo LCM independente.
stable-fast é capaz de otimizar a mais recente StableVideoDiffusionPipeline e obter uma aceleração 2x
Consulte exemplos/otimize_stable_video_diffusion_pipeline.py para obter mais detalhes
A troca de Lora é suportada dinamicamente, mas você precisa fazer algum trabalho extra. É possível porque o gráfico compilado e CUDA Graph compartilham os mesmos dados de subjacação (ponteiros) com o modelo UNET original. Portanto, tudo o que você precisa fazer é atualizar os parâmetros do modelo UNET original no local.
O código a seguir supõe que você já carregue um Lora e compilou o modelo, e deseja mudar para outro Lora.
Se você não habilitar o gráfico CUDA e manter preserve_parameters = True , as coisas podem ser muito mais fáceis. O código a seguir pode nem ser necessário.
# load_state_dict with assign=True requires torch >= 2.1.0
def update_state_dict ( dst , src ):
for key , value in src . items ():
# Do inplace copy.
# As the traced forward function shares the same underlaying data (pointers),
# this modification will be reflected in the traced forward function.
dst [ key ]. copy_ ( value )
# Switch "another" LoRA into UNet
def switch_lora ( unet , lora ):
# Store the original UNet parameters
state_dict = unet . state_dict ()
# Load another LoRA into unet
unet . load_attn_procs ( lora )
# Inplace copy current UNet parameters to the original unet parameters
update_state_dict ( state_dict , unet . state_dict ())
# Load the original UNet parameters back.
# We use assign=True because we still want to hold the references
# of the original UNet parameters
unet . load_state_dict ( state_dict , assign = True )
switch_lora ( compiled_model . unet , lora_b_path ) stable-fast estende a funcionalidade quantize_dynamic de Pytorch e fornece um operador linear quantizado dinamicamente no back-end do CUDA. Ao ativá -lo, você pode obter uma ligeira redução de VRAM para diffusers e redução significativa de VRAM para transformers , e o Cound obtém uma aceleração potencial (nem sempre).
Para SD XL , espera -se que ele veja a redução de VRAM de 2GB com um tamanho de imagem de 1024x1024 .
def quantize_unet ( m ):
from diffusers . utils import USE_PEFT_BACKEND
assert USE_PEFT_BACKEND
m = torch . quantization . quantize_dynamic ( m , { torch . nn . Linear },
dtype = torch . qint8 ,
inplace = True )
return m
model . unet = quantize_unet ( model . unet )
if hasattr ( model , 'controlnet' ):
model . controlnet = quantize_unet ( model . controlnet )Consulte Exemplos/Optimize_Stable_Diffusion_PiPeline.py para obter mais detalhes.
# TCMalloc is highly suggested to reduce CPU overhead
# https://github.com/google/tcmalloc
LD_PRELOAD=/path/to/libtcmalloc.so python3 ... import packaging . version
import torch
if packaging . version . parse ( torch . __version__ ) >= packaging . version . parse ( '1.12.0' ):
torch . backends . cuda . matmul . allow_tf32 = True O desempenho varia muito bem em diferentes configurações de hardware/software/plataforma/driver. É muito difícil comparar com precisão. E preparar o ambiente para o benchmarking também é um trabalho árduo. Eu já testei em algumas plataformas antes, mas os resultados ainda podem ser imprecisos. Observe que, ao benchmarking, a barra de progresso mostrada pelo tqdm pode ser imprecisa devido à natureza assíncrona do CUDA. Para resolver esse problema, uso CUDA Event para medir a velocidade das iterações por segundo com precisão.
Espera stable-fast funcione melhor nas GPUs mais recentes e nas versões mais recentes do CUDA. Nas GPUs mais antigas, o aumento do desempenho pode ser limitado. Durante o benchmarking, a barra de progresso pode funcionar incorretamente devido à natureza assíncrona do CUDA.
Este é o meu PC de jogos pessoais?. Possui uma CPU mais poderosa do que aqueles de fornecedores de servidores em nuvem.
| Estrutura | SD 1.5 | SD XL (1024x1024) | SD 1.5 ControlNet |
|---|---|---|---|
| Vanilla Pytorch (2.1.0) | 29.5 it/s | 4.6 It/s | 19.7 it/s |
| Torch.compile (2.1.0, Max-AutoTune) | 40.0 It/s | 6.1 it/s | 21.8 it/s |
| Aitemplate | 44.2 it/s | ||
| OneFlow | 53.6 It/s | ||
| Auto1111 Webui | 17.2 It/s | 3.6 It/s | |
| Auto1111 Webui (com SDPA) | 24.5 it/s | 4.3 It/s | |
| Tensorrt (Auto1111 Webui) | 40.8 IT/S. | ||
| Demonstração oficial da Tensorrt | 52.6 it/s | ||
| estável-rápido (com Xformers & Triton) | 51.6 IT/S. | 9.1 it/s | 36.7 it/s |
Obrigado pela ajuda do @ConscelerAtus e do @Harishp , testei a velocidade no H100.
| Estrutura | SD 1.5 | SD XL (1024x1024) | SD 1.5 ControlNet |
|---|---|---|---|
| Vanilla Pytorch (2.1.0) | 54.5 it/s | 14.9 It/s | 35.8 it/s |
| Torch.compile (2.1.0, Max-AutoTune) | 66.0 it/s | 18.5 It/s | |
| estável-rápido (com Xformers & Triton) | 104.6 it/s | 21.6 it/s | 72.6 it/s |
Obrigado pelo @SuperSecureHuman e da ajuda de @Jon-Chuang , o benchmarking no A100 já está disponível.
| Estrutura | SD 1.5 | SD XL (1024x1024) | SD 1.5 ControlNet |
|---|---|---|---|
| Vanilla Pytorch (2.1.0) | 35.6 it/s | 8.7 It/s | 25.1 it/s |
| Torch.compile (2.1.0, Max-AutoTune) | 41.9 it/s | 10.0 it/s | |
| estável-rápido (com Xformers & Triton) | 61.8 it/s | 11.9 It/s | 41.1 it/s |
| Modelo | Suportado |
|---|---|
| Abraçando os difusores de rosto (1.5/2.1/xl) | Sim |
| Com controlnet | Sim |
| Com Lora | Sim |
| Modelo de consistência latente | Sim |
| Sdxl turbo | Sim |
| Difusão de vídeo estável | Sim |
| Funcionalidade | Suportado |
|---|---|
| Forma dinâmica | Sim |
| Texto para imagem | Sim |
| Imagem para imagem | Sim |
| Imagem em pintura | Sim |
| Estrutura da interface do usuário | Suportado | Link |
|---|---|---|
| Automatic1111 | WIP | |
| Sd a seguir | Sim | SD Next |
| Comfyui | Sim | ComfyUI_stable_fast |
| Sistema operacional | Suportado |
|---|---|
| Linux | Sim |
| Windows | Sim |
| Windows WSL | Sim |
Consulte Doc/Solução de problemas.MD para obter mais detalhes.
E você pode ingressar no canal Discord para pedir ajuda.