Buckets:
| # ParaAttention | |
| Büyük görsel ve video üretim modelleri, örneğin [FLUX.1-dev](https://huggingface.co/black-forest-labs/FLUX.1-dev) ve [HunyuanVideo](https://huggingface.co/tencent/HunyuanVideo), boyutları nedeniyle gerçek zamanlı uygulamalar ve dağıtım için çıkarım (inference) açısından zorluk yaratabilir. | |
| [ParaAttention](https://github.com/chengzeyi/ParaAttention), **bağlam paralelliği** ve **ilk blok önbelleği** uygulayan ve çıkarımı hızlandırmak için diğer tekniklerle (torch.compile, fp8 dinamik kuantizasyonu) birleştirilebilen bir kütüphanedir. | |
| Bu kılavuz, ParaAttention'ın NVIDIA L20 GPU'larında FLUX.1-dev ve HunyuanVideo'ya nasıl uygulanacağını gösterecektir. Baz çizelge ölçümümüz için herhangi bir optimizasyon uygulanmamıştır; HunyuanVideo için bellek dışı (out-of-memory) hatalarından kaçınmak amacıyla yapılanlar hariç. | |
| Temel performans ölçümümüz, FLUX.1-dev'in 28 adımda 1024x1024 çözünürlüğünde bir görüntüyü 26,36 saniyede, HunyuanVideo'nun ise 30 adımda 720p çözünürlüğünde 129 kareyi 3675,71 saniyede üretebildiğini göstermektedir. | |
| > [!TIP] | |
| > Bağlam paralelliği ile daha hızlı çıkarım için, özellikle çok sayıda GPU varsa, NVLink desteğine sahip NVIDIA A100 veya H100 GPU'ları (müsaitse) kullanmayı deneyin. | |
| ## İlk Blok Önbelleği | |
| Modeldeki transformers bloklarının çıktılarını önbelleğe alıp sonraki çıkarım adımlarında yeniden kullanmak, hesaplama maliyetini azaltır ve çıkarımı hızlandırır. | |
| Ancak, üretilen görüntü veya videoların kalitesini garanti altına almak için önbelleğin ne zaman yeniden kullanılacağına karar vermek zordur. ParaAttention, model çıktılar arasındaki farkı yaklaşık olarak hesaplamak için doğrudan **ilk transformer bloğu çıktısının kalan farkını** kullanır. Fark yeterince küçük olduğunda, önceki çıkarım adımlarının kalan farkı yeniden kullanılır. Başka bir deyişle, gürültü azaltma adımı atlanır. | |
| Bu, FLUX.1-dev ve HunyuanVideo çıkarımında çok iyi kaliteyle 2x hızlanma sağlar. | |
| AdaCache nasıl çalışır, First Block Cache bunun bir varyantıdır | |
| FLUX.1-dev üzerinde ilk blok önbelleğini uygulamak için aşağıda gösterildiği gibi `apply_cache_on_pipe` fonksiyonunu çağırın. 0.08, FLUX modelleri için varsayılan artıksal fark değeridir. | |
| ```python | |
| import time | |
| import torch | |
| from diffusers import FluxPipeline | |
| pipe = FluxPipeline.from_pretrained( | |
| "black-forest-labs/FLUX.1-dev", | |
| dtype=torch.bfloat16, | |
| ).to("cuda") # or "mps", "xpu", "cpu" | |
| from para_attn.first_block_cache.diffusers_adapters import apply_cache_on_pipe | |
| apply_cache_on_pipe(pipe, residual_diff_threshold=0.08) | |
| # Enable memory savings | |
| # pipe.enable_model_cpu_offload() | |
| # pipe.enable_sequential_cpu_offload() | |
| begin = time.time() | |
| image = pipe( | |
| "A cat holding a sign that says hello world", | |
| num_inference_steps=28, | |
| ).images[0] | |
| end = time.time() | |
| print(f"Time: {end - begin:.2f}s") | |
| print("Saving image to flux.png") | |
| image.save("flux.png") | |
| ``` | |
| | Optimizasyonlar | Orijinal | FBCache rdt=0.06 | FBCache rdt=0.08 | FBCache rdt=0.10 | FBCache rdt=0.12 | | |
| | - | - | - | - | - | - | | |
| | Önizleme |  |  |  |  |  | | |
| | Duvar Saati (s) | 26.36 | 21.83 | 17.01 | 16.00 | 13.78 | | |
| First Block Cache, neredeyse sıfır kalite kaybı ile birlikte, referans değerine kıyasla çıkarım hızını 17,01 saniyeye düşürerek 1,55 kat daha hızlı bir performans sağladı. | |
| HunyuanVideo üzerinde First Block Cache uygulamak için aşağıda gösterildiği gibi `apply_cache_on_pipe` kullanın. 0.06, HunyuanVideo modelleri için varsayılan kalan fark değeridir. | |
| ```python | |
| import time | |
| import torch | |
| from diffusers import HunyuanVideoPipeline, HunyuanVideoTransformer3DModel | |
| from diffusers.utils import export_to_video | |
| model_id = "tencent/HunyuanVideo" | |
| transformer = HunyuanVideoTransformer3DModel.from_pretrained( | |
| model_id, | |
| subfolder="transformer", | |
| dtype=torch.bfloat16, | |
| revision="refs/pr/18", | |
| ) | |
| pipe = HunyuanVideoPipeline.from_pretrained( | |
| model_id, | |
| transformer=transformer, | |
| dtype=torch.float16, | |
| revision="refs/pr/18", | |
| ).to("cuda") # or "mps", "xpu", "cpu" | |
| from para_attn.first_block_cache.diffusers_adapters import apply_cache_on_pipe | |
| apply_cache_on_pipe(pipe, residual_diff_threshold=0.6) | |
| pipe.vae.enable_tiling() | |
| begin = time.time() | |
| output = pipe( | |
| prompt="A cat walks on the grass, realistic", | |
| height=720, | |
| width=1280, | |
| num_frames=129, | |
| num_inference_steps=30, | |
| ).frames[0] | |
| end = time.time() | |
| print(f"Time: {end - begin:.2f}s") | |
| print("Saving video to hunyuan_video.mp4") | |
| export_to_video(output, "hunyuan_video.mp4", fps=15) | |
| ``` | |
| Tarayıcınız video etiketini desteklemiyor. | |
| FBCache olmadan HunyuanVideo | |
| Tarayıcınız video etiketini desteklemiyor. | |
| FBCache ile HunyuanVideo | |
| First Block Cache, neredeyse sıfır kalite kaybı ile birlikte, referans değerine kıyasla çıkarım süresini 2271.06 saniyeye indirerek 1.62x daha hızlı bir performans sağladı. | |
| ## fp8 kuantizasyonu | |
| Dinamik kuantizasyon ile fp8, çıkarımı daha da hızlandırır ve bellek kullanımını azaltır. 8-bit [NVIDIA Tensor Cores](https://www.nvidia.com/en-us/data-center/tensor-cores/)'ün kullanılabilmesi için hem aktivasyonların hem de ağırlıkların kuantize edilmesi gerekir. | |
| Metin kodlayıcı ve dönüştürücü modelini nicelleştirmek için `float8_weight_only` ve `float8_dynamic_activation_float8_weight` kullanın. | |
| Varsayılan kuantizasyon yöntemi tensör başına kuantizasyondur, ancak GPU'nuz satır başına kuantizasyonu destekliyorsa daha iyi doğruluk için bunu da deneyebilirsiniz. | |
| Aşağıdaki komutla [torchao](https://github.com/pytorch/ao/tree/main) paketini yükleyin. | |
| ```bash | |
| pip3 install -U torch torchao | |
| ``` | |
| [torch.compile](https://pytorch.org/tutorials/intermediate/torch_compile_tutorial.html), `mode="max-autotune-no-cudagraphs"` veya `mode="max-autotune"` parametresiyle kullanıldığında, performans için en iyi çekirdeği seçer. Model ilk kez çağrılıyorsa derleme işlemi uzun sürebilir ancak model derlendikten sonra bu süre kendini amorti eder. | |
| Bu örnek yalnızca dönüştürücü modelini kuantize eder, ancak bellek kullanımını daha da azaltmak için metin kodlayıcısını da kuantize edebilirsiniz. | |
| > [!TIP] | |
| > Dinamik kuantizasyon, model çıktısının dağılımını önemli ölçüde değiştirebilir; bu nedenle etkin olması için `residual_diff_threshold` değerini daha büyük bir değere değiştirmeniz gerekir. | |
| ```python | |
| import time | |
| import torch | |
| from diffusers import FluxPipeline | |
| pipe = FluxPipeline.from_pretrained( | |
| "black-forest-labs/FLUX.1-dev", | |
| dtype=torch.bfloat16, | |
| ).to("cuda") # or "mps", "xpu", "cpu" | |
| from para_attn.first_block_cache.diffusers_adapters import apply_cache_on_pipe | |
| apply_cache_on_pipe( | |
| pipe, | |
| residual_diff_threshold=0.12, # Use a larger value to make the cache take effect | |
| ) | |
| from torchao.quantization import quantize_, float8_dynamic_activation_float8_weight, float8_weight_only | |
| quantize_(pipe.text_encoder, float8_weight_only()) | |
| quantize_(pipe.transformer, float8_dynamic_activation_float8_weight()) | |
| pipe.transformer = torch.compile( | |
| pipe.transformer, mode="max-autotune-no-cudagraphs", | |
| ) | |
| # Enable memory savings | |
| # pipe.enable_model_cpu_offload() | |
| # pipe.enable_sequential_cpu_offload() | |
| for i in range(2): | |
| begin = time.time() | |
| image = pipe( | |
| "A cat holding a sign that says hello world", | |
| num_inference_steps=28, | |
| ).images[0] | |
| end = time.time() | |
| if i == 0: | |
| print(f"Warm up time: {end - begin:.2f}s") | |
| else: | |
| print(f"Time: {end - begin:.2f}s") | |
| print("Saving image to flux.png") | |
| image.save("flux.png") | |
| ``` | |
| fp8 dinamik kuantizasyonu ve torch.compile, referans değerine kıyasla çıkarım süresini 7,56 saniyeye düşürerek 3,48 kat daha hızlı hale getirdi. | |
| ```python | |
| import time | |
| import torch | |
| from diffusers import HunyuanVideoPipeline, HunyuanVideoTransformer3DModel | |
| from diffusers.utils import export_to_video | |
| model_id = "tencent/HunyuanVideo" | |
| transformer = HunyuanVideoTransformer3DModel.from_pretrained( | |
| model_id, | |
| subfolder="transformer", | |
| dtype=torch.bfloat16, | |
| revision="refs/pr/18", | |
| ) | |
| pipe = HunyuanVideoPipeline.from_pretrained( | |
| model_id, | |
| transformer=transformer, | |
| dtype=torch.float16, | |
| revision="refs/pr/18", | |
| ).to("cuda") # or "mps", "xpu", "cpu" | |
| from para_attn.first_block_cache.diffusers_adapters import apply_cache_on_pipe | |
| apply_cache_on_pipe(pipe) | |
| from torchao.quantization import quantize_, float8_dynamic_activation_float8_weight, float8_weight_only | |
| quantize_(pipe.text_encoder, float8_weight_only()) | |
| quantize_(pipe.transformer, float8_dynamic_activation_float8_weight()) | |
| pipe.transformer = torch.compile( | |
| pipe.transformer, mode="max-autotune-no-cudagraphs", | |
| ) | |
| # Enable memory savings | |
| pipe.vae.enable_tiling() | |
| # pipe.enable_model_cpu_offload() | |
| # pipe.enable_sequential_cpu_offload() | |
| for i in range(2): | |
| begin = time.time() | |
| output = pipe( | |
| prompt="A cat walks on the grass, realistic", | |
| height=720, | |
| width=1280, | |
| num_frames=129, | |
| num_inference_steps=1 if i == 0 else 30, | |
| ).frames[0] | |
| end = time.time() | |
| if i == 0: | |
| print(f"Warm up time: {end - begin:.2f}s") | |
| else: | |
| print(f"Time: {end - begin:.2f}s") | |
| print("Saving video to hunyuan_video.mp4") | |
| export_to_video(output, "hunyuan_video.mp4", fps=15) | |
| ``` | |
| NVIDIA L20 GPU yalnızca 48GB belleğe sahiptir ve HunyuanVideo, yüksek çözünürlük ve yüksek kare sayısı ile çalışırken çok büyük aktivasyon tensörlerine sahip olduğu için derleme sonrasında ve `enable_model_cpu_offload` çağrılmadığında bellek yetersizliği (OOM) hatalarıyla karşılaşabilir. 80GB'tan az belleğe sahip GPU'larda OOM hatalarını önlemek için çözünürlüğü ve kare sayısını azaltmayı deneyebilirsiniz. | |
| Büyük video üretim modelleri genellikle tam bağlı katmanlardan ziyade dikkat hesaplamalarıyla darboğaza takılır. Bu modeller, kuantizasyondan ve torch.compile'den önemli ölçüde fayda sağlamaz. | |
| ## Bağlam Paralelliği | |
| Context Parallelism, çıkarımı paralelleştirir ve birden çok GPU ile ölçeklenir. ParaAttention bileşen tasarımı, Context Parallelism'i First Block Cache ve dinamik kuantizasyonla birleştirmenizi sağlar. | |
| > [!TIP] | |
| > Birden fazla GPU ile çıkarımı ölçeklendirmenin ayrıntılı talimatları ve örnekleri için [ParaAttention](https://github.com/chengzeyi/ParaAttention/tree/main) deposuna başvurun. | |
| Eğer çıkarım sürecinin kalıcı ve hizmet verebilir olması gerekiyorsa, kendi çıkarım işleyicinizi yazmak için [torch.multiprocessing](https://pytorch.org/docs/stable/multiprocessing.html) kullanmanız önerilir. Bu, süreci başlatma ve modeli yükleme ile yeniden derleme işlemlerinin getirdiği ek yükü ortadan kaldırabilir. | |
| Aşağıdaki kod örneği, en hızlı çıkarım hızı için First Block Cache, fp8 dinamik kuantizasyonu, torch.compile ve Context Parallelism'i birleştirir. | |
| ```python | |
| import time | |
| import torch | |
| import torch.distributed as dist | |
| from diffusers import FluxPipeline | |
| dist.init_process_group() | |
| torch.cuda.set_device(dist.get_rank()) | |
| pipe = FluxPipeline.from_pretrained( | |
| "black-forest-labs/FLUX.1-dev", | |
| dtype=torch.bfloat16, | |
| ).to("cuda") # or "mps", "xpu", "cpu" | |
| from para_attn.context_parallel import init_context_parallel_mesh | |
| from para_attn.context_parallel.diffusers_adapters import parallelize_pipe | |
| from para_attn.parallel_vae.diffusers_adapters import parallelize_vae | |
| mesh = init_context_parallel_mesh( | |
| pipe.device.type, | |
| max_ring_dim_size=2, | |
| ) | |
| parallelize_pipe( | |
| pipe, | |
| mesh=mesh, | |
| ) | |
| parallelize_vae(pipe.vae, mesh=mesh._flatten()) | |
| from para_attn.first_block_cache.diffusers_adapters import apply_cache_on_pipe | |
| apply_cache_on_pipe( | |
| pipe, | |
| residual_diff_threshold=0.12, # Use a larger value to make the cache take effect | |
| ) | |
| from torchao.quantization import quantize_, float8_dynamic_activation_float8_weight, float8_weight_only | |
| quantize_(pipe.text_encoder, float8_weight_only()) | |
| quantize_(pipe.transformer, float8_dynamic_activation_float8_weight()) | |
| torch._inductor.config.reorder_for_compute_comm_overlap = True | |
| pipe.transformer = torch.compile( | |
| pipe.transformer, mode="max-autotune-no-cudagraphs", | |
| ) | |
| # Enable memory savings | |
| # pipe.enable_model_cpu_offload(gpu_id=dist.get_rank()) | |
| # pipe.enable_sequential_cpu_offload(gpu_id=dist.get_rank()) | |
| for i in range(2): | |
| begin = time.time() | |
| image = pipe( | |
| "A cat holding a sign that says hello world", | |
| num_inference_steps=28, | |
| output_type="pil" if dist.get_rank() == 0 else "pt", | |
| ).images[0] | |
| end = time.time() | |
| if dist.get_rank() == 0: | |
| if i == 0: | |
| print(f"Warm up time: {end - begin:.2f}s") | |
| else: | |
| print(f"Time: {end - begin:.2f}s") | |
| if dist.get_rank() == 0: | |
| print("Saving image to flux.png") | |
| image.save("flux.png") | |
| dist.destroy_process_group() | |
| ``` | |
| `run_flux.py` dosyasına kaydedin ve [torchrun](https://pytorch.org/docs/stable/elastic/run.html) ile başlatın. | |
| ```bash | |
| # Use --nproc_per_node to specify the number of GPUs | |
| torchrun --nproc_per_node=2 run_flux.py | |
| ``` | |
| 2 NVIDIA L20 GPU ile çıkarım hızı, baz çizgiye kıyasla 8,20 saniyeye düşer; bu da 3,21 kat daha hızlı demektir. 4 L20 ile çıkarım hızı 3,90 saniyedir, yani 6,75 kat daha hızlıdır. | |
| Aşağıdaki kod örneği, en hızlı çıkarım hızı için First Block Cache ve Context Parallelism'i birleştirir. | |
| ```python | |
| import time | |
| import torch | |
| import torch.distributed as dist | |
| from diffusers import HunyuanVideoPipeline, HunyuanVideoTransformer3DModel | |
| from diffusers.utils import export_to_video | |
| dist.init_process_group() | |
| torch.cuda.set_device(dist.get_rank()) | |
| model_id = "tencent/HunyuanVideo" | |
| transformer = HunyuanVideoTransformer3DModel.from_pretrained( | |
| model_id, | |
| subfolder="transformer", | |
| dtype=torch.bfloat16, | |
| revision="refs/pr/18", | |
| ) | |
| pipe = HunyuanVideoPipeline.from_pretrained( | |
| model_id, | |
| transformer=transformer, | |
| dtype=torch.float16, | |
| revision="refs/pr/18", | |
| ).to("cuda") # or "mps", "xpu", "cpu" | |
| from para_attn.context_parallel import init_context_parallel_mesh | |
| from para_attn.context_parallel.diffusers_adapters import parallelize_pipe | |
| from para_attn.parallel_vae.diffusers_adapters import parallelize_vae | |
| mesh = init_context_parallel_mesh( | |
| pipe.device.type, | |
| ) | |
| parallelize_pipe( | |
| pipe, | |
| mesh=mesh, | |
| ) | |
| parallelize_vae(pipe.vae, mesh=mesh._flatten()) | |
| from para_attn.first_block_cache.diffusers_adapters import apply_cache_on_pipe | |
| apply_cache_on_pipe(pipe) | |
| # from torchao.quantization import quantize_, float8_dynamic_activation_float8_weight, float8_weight_only | |
| # | |
| # torch._inductor.config.reorder_for_compute_comm_overlap = True | |
| # | |
| # quantize_(pipe.text_encoder, float8_weight_only()) | |
| # quantize_(pipe.transformer, float8_dynamic_activation_float8_weight()) | |
| # pipe.transformer = torch.compile( | |
| # pipe.transformer, mode="max-autotune-no-cudagraphs", | |
| # ) | |
| # Enable memory savings | |
| pipe.vae.enable_tiling() | |
| # pipe.enable_model_cpu_offload(gpu_id=dist.get_rank()) | |
| # pipe.enable_sequential_cpu_offload(gpu_id=dist.get_rank()) | |
| for i in range(2): | |
| begin = time.time() | |
| output = pipe( | |
| prompt="A cat walks on the grass, realistic", | |
| height=720, | |
| width=1280, | |
| num_frames=129, | |
| num_inference_steps=1 if i == 0 else 30, | |
| output_type="pil" if dist.get_rank() == 0 else "pt", | |
| ).frames[0] | |
| end = time.time() | |
| if dist.get_rank() == 0: | |
| if i == 0: | |
| print(f"Warm up time: {end - begin:.2f}s") | |
| else: | |
| print(f"Time: {end - begin:.2f}s") | |
| if dist.get_rank() == 0: | |
| print("Saving video to hunyuan_video.mp4") | |
| export_to_video(output, "hunyuan_video.mp4", fps=15) | |
| dist.destroy_process_group() | |
| ``` | |
| `run_hunyuan_video.py` dosyasına kaydedin ve [torchrun](https://pytorch.org/docs/stable/elastic/run.html) ile başlatın. | |
| ```bash | |
| # Use --nproc_per_node to specify the number of GPUs | |
| torchrun --nproc_per_node=8 run_hunyuan_video.py | |
| ``` | |
| 8 NVIDIA L20 GPU ile çıkarım hızı, baz çizgiye kıyasla 649,23 saniyeye düşürülmüş olup 5,66 kat daha hızlıdır. | |
| ## Benchmarks | |
| | GPU Türü | GPU sayısı | Optimizasyonlar | Duvar Saati (s) | Hızlanma | | |
| | - | - | - | - | - | | |
| | NVIDIA L20 | 1 | Taban | 26.36 | 1.00x | | |
| | NVIDIA L20 | 1 | FBCache (rdt=0.08) | 17.01 | 1.55x | | |
| | NVIDIA L20 | 1 | FP8 DQ | 13.40 | 1.96x | | |
| | NVIDIA L20 | 1 | FBCache (rdt=0.12) + FP8 DQ | 7.56 | 3.48x | | |
| | NVIDIA L20 | 2 | FBCache (rdt=0.12) + FP8 DQ + CP | 4.92 | 5.35x | | |
| | NVIDIA L20 | 4 | FBCache (rdt=0.12) + FP8 DQ + CP | 3.90 | 6.75x | | |
| | GPU Türü | GPU sayısı | Optimizasyonlar | Duvar Saati (s) | Hızlanma | | |
| | - | - | - | - | - | | |
| | NVIDIA L20 | 1 | Taban | 3675.71 | 1.00x | | |
| | NVIDIA L20 | 1 | FBCache | 2271.06 | 1.62x | | |
| | NVIDIA L20 | 2 | FBCache + CP | 1132.90 | 3.24x | | |
| | NVIDIA L20 | 4 | FBCache + CP | 718.15 | 5.12x | | |
| | NVIDIA L20 | 8 | FBCache + CP | 649.23 | 5.66x | | |
Xet Storage Details
- Size:
- 17.8 kB
- Xet hash:
- c4071622e3a4cbb9667217b5d23bd026880a975f7f9fdeb500172e864113f948
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.