Buckets:
Bellek kullanımını azaltın
Flux ve Wan gibi modern difüzyon modelleri, çıkarım sırasında donanımınızda çok fazla bellek alan milyarlarca parametreye sahiptir. Bu, yaygın GPU'ların genellikle yeterli belleğe sahip olmaması nedeniyle zorlayıcıdır. Bellek kısıtlamalarını aşmak için birden fazla GPU kullanabilir (mevcutsa), hattın bazı bileşenlerini CPU'ya aktarabilir ve daha fazlasını yapabilirsiniz.
Bu kılavuz, bellek kullanımınızı nasıl azaltacağınızı gösterecektir.
Bu tekniklerin modele göre ayarlanmasının gerekebileceğini unutmayın. Örneğin, transformer tabanlı bir difüzyon modeli, UNet tabanlı bir modelden bu bellek optimizasyonlarından aynı ölçüde fayda görmeyebilir.
Birden fazla GPU
Birden fazla GPU'ya erişiminiz varsa, büyük bir modeli donanımınız arasında verimli bir şekilde yüklemek ve dağıtmak için birkaç seçenek mevcuttur. Bu özellikler Accelerate kütüphanesi tarafından desteklenir, bu nedenle önce kütüphanenin yüklü olduğundan emin olun.
pip install -U accelerate
Parçalı denetim noktaları
Büyük kontrol noktalarını (checkpoint) birden fazla parça (shard) halinde yüklemek faydalıdır, çünkü parçalar tek tek yüklenir. Bu, bellek kullanımını düşük tutar; yalnızca model boyutu ve en büyük parça boyutu kadar bellek gerektirir. fp32 kontrol noktası 5GB'tan büyükse parçalama (sharding) öneririz. Varsayılan parça boyutu 5GB'tır.
Bir kontrol noktasını save_pretrained() içinde max_shard_size parametresiyle parçalara ayırın.
from diffusers import AutoModel
unet = AutoModel.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0", subfolder="unet"
)
unet.save_pretrained("sdxl-unet-sharded", max_shard_size="5GB")
Artık belleği tasarruflu kullanmak için normal kontrol noktası yerine parçalı kontrol noktasını kullanabilirsiniz.
import torch
from diffusers import AutoModel, StableDiffusionXLPipeline
unet = AutoModel.from_pretrained(
"username/sdxl-unet-sharded", dtype=torch.float16
)
pipeline = StableDiffusionXLPipeline.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0",
unet=unet,
dtype=torch.float16
).to("cuda") # or "mps", "xpu", "cpu"
Cihaz yerleşimi
Cihaz yerleşimi deneysel bir özelliktir ve API değişebilir. Şu anda yalnızca
balancedstratejisi desteklenmektedir. Gelecekte ek eşleme stratejilerini desteklemeyi planlıyoruz.
device_map parametresi, bir pipeline'daki model bileşenlerinin veya tek bir modeldeki katmanların cihazlar arasında nasıl dağıtılacağını kontrol eder.
balanced cihaz yerleştirme stratejisi, hattı tüm kullanılabilir cihazlar arasında eşit olarak böler.
import torch
from diffusers import AutoModel, StableDiffusionXLPipeline
pipeline = StableDiffusionXLPipeline.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0",
dtype=torch.float16,
device_map="balanced"
)
Bir hattın cihaz haritasını hf_device_map ile inceleyebilirsiniz.
print(pipeline.hf_device_map)
{'unet': 1, 'vae': 1, 'safety_checker': 0, 'text_encoder': 0}
device_map, Flux difüzyon dönüştürücüsü gibi 12,5 milyar parametreye sahip büyük modelleri yüklemek için kullanışlıdır. Modelin önce en hızlı cihaza, ardından daha yavaş cihazlara otomatik olarak dağıtılmasını sağlamak için "auto" olarak ayarlayın. Daha fazla ayrıntı için Parçalı denetim noktaları bölümüne bakın.
import torch
from diffusers import AutoModel
transformer = AutoModel.from_pretrained(
"black-forest-labs/FLUX.1-dev",
subfolder="transformer",
device_map="auto",
dtype=torch.bfloat16
)
Bir modelin cihaz haritasını hf_device_map ile inceleyebilirsiniz.
print(transformer.hf_device_map)
Kendi device_map tasarımınızı oluştururken, bir sözlük olmalıdır; bu sözlük, modelin belirli bir modül adı veya katmanı ile bir cihaz tanımlayıcısını (GPU'lar için bir tamsay, CPU'lar için cpu ve disk için disk) eşleştirir.
Bir modelde hf_device_map çağrısını yaparak model katmanlarının nasıl dağıtıldığını görün ve ardından kendi dağıtımınızı tasarlayın.
print(transformer.hf_device_map)
{'pos_embed': 0, 'time_text_embed': 0, 'context_embedder': 0, 'x_embedder': 0, 'transformer_blocks': 0, 'single_transformer_blocks.0': 0, 'single_transformer_blocks.1': 0, 'single_transformer_blocks.2': 0, 'single_transformer_blocks.3': 0, 'single_transformer_blocks.4': 0, 'single_transformer_blocks.5': 0, 'single_transformer_blocks.6': 0, 'single_transformer_blocks.7': 0, 'single_transformer_blocks.8': 0, 'single_transformer_blocks.9': 0, 'single_transformer_blocks.10': 'cpu', 'single_transformer_blocks.11': 'cpu', 'single_transformer_blocks.12': 'cpu', 'single_transformer_blocks.13': 'cpu', 'single_transformer_blocks.14': 'cpu', 'single_transformer_blocks.15': 'cpu', 'single_transformer_blocks.16': 'cpu', 'single_transformer_blocks.17': 'cpu', 'single_transformer_blocks.18': 'cpu', 'single_transformer_blocks.19': 'cpu', 'single_transformer_blocks.20': 'cpu', 'single_transformer_blocks.21': 'cpu', 'single_transformer_blocks.22': 'cpu', 'single_transformer_blocks.23': 'cpu', 'single_transformer_blocks.24': 'cpu', 'single_transformer_blocks.25': 'cpu', 'single_transformer_blocks.26': 'cpu', 'single_transformer_blocks.27': 'cpu', 'single_transformer_blocks.28': 'cpu', 'single_transformer_blocks.29': 'cpu', 'single_transformer_blocks.30': 'cpu', 'single_transformer_blocks.31': 'cpu', 'single_transformer_blocks.32': 'cpu', 'single_transformer_blocks.33': 'cpu', 'single_transformer_blocks.34': 'cpu', 'single_transformer_blocks.35': 'cpu', 'single_transformer_blocks.36': 'cpu', 'single_transformer_blocks.37': 'cpu', 'norm_out': 'cpu', 'proj_out': 'cpu'}
Örneğin, aşağıdaki device_map, single_transformer_blocks.10 ile single_transformer_blocks.20 arasındaki blokları ikinci bir GPU'ya (1) yerleştirir.
import torch
from diffusers import AutoModel
device_map = {
'pos_embed': 0, 'time_text_embed': 0, 'context_embedder': 0, 'x_embedder': 0, 'transformer_blocks': 0, 'single_transformer_blocks.0': 0, 'single_transformer_blocks.1': 0, 'single_transformer_blocks.2': 0, 'single_transformer_blocks.3': 0, 'single_transformer_blocks.4': 0, 'single_transformer_blocks.5': 0, 'single_transformer_blocks.6': 0, 'single_transformer_blocks.7': 0, 'single_transformer_blocks.8': 0, 'single_transformer_blocks.9': 0, 'single_transformer_blocks.10': 1, 'single_transformer_blocks.11': 1, 'single_transformer_blocks.12': 1, 'single_transformer_blocks.13': 1, 'single_transformer_blocks.14': 1, 'single_transformer_blocks.15': 1, 'single_transformer_blocks.16': 1, 'single_transformer_blocks.17': 1, 'single_transformer_blocks.18': 1, 'single_transformer_blocks.19': 1, 'single_transformer_blocks.20': 1, 'single_transformer_blocks.21': 'cpu', 'single_transformer_blocks.22': 'cpu', 'single_transformer_blocks.23': 'cpu', 'single_transformer_blocks.24': 'cpu', 'single_transformer_blocks.25': 'cpu', 'single_transformer_blocks.26': 'cpu', 'single_transformer_blocks.27': 'cpu', 'single_transformer_blocks.28': 'cpu', 'single_transformer_blocks.29': 'cpu', 'single_transformer_blocks.30': 'cpu', 'single_transformer_blocks.31': 'cpu', 'single_transformer_blocks.32': 'cpu', 'single_transformer_blocks.33': 'cpu', 'single_transformer_blocks.34': 'cpu', 'single_transformer_blocks.35': 'cpu', 'single_transformer_blocks.36': 'cpu', 'single_transformer_blocks.37': 'cpu', 'norm_out': 'cpu', 'proj_out': 'cpu'
}
transformer = AutoModel.from_pretrained(
"black-forest-labs/FLUX.1-dev",
subfolder="transformer",
device_map=device_map,
dtype=torch.bfloat16
)
Her cihaz için maksimum bellek kullanımını eşleyen bir sözlük geçirerek bir sınır uygulayın. Bir cihaz max_memory içinde değilse, yok sayılır ve pipeline bileşenleri ona dağıtılmaz.
import torch
from diffusers import AutoModel, StableDiffusionXLPipeline
max_memory = {0:"1GB", 1:"1GB"}
pipeline = StableDiffusionXLPipeline.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0",
dtype=torch.float16,
device_map="balanced",
max_memory=max_memory
)
Diffusers varsayılan olarak tüm cihazların maksimum belleğini kullanır, ancak bunlar GPU'lara sığmıyorsa aşağıdaki yöntemlerle tek bir GPU kullanıp CPU'ya taşımak gerekir.
- enable_model_cpu_offload() yalnızca tek bir GPU üzerinde çalışır ancak çok büyük bir model bu GPU'ya sığmayabilir
- enable_sequential_cpu_offload() çalışabilir ancak son derece yavaştır ve ayrıca tek bir GPU ile sınırlıdır
device_map'i sıfırlamak için reset_device_map() yöntemini kullanın. Bir pipeline cihaz eşlemeli olarak yapılandırıldıysa ve .to(), enable_sequential_cpu_offload() ve enable_model_cpu_offload() gibi yöntemleri kullanmak istiyorsanız bu işlem gereklidir.
pipeline.reset_device_map()
VAE dilimleme
VAE slicing, büyük girdi partilerini tek bir veri partisine bölerek ve bunları ayrı ayrı işleyerek bellek tasarrufu sağlar. Bu yöntem, aynı anda birden fazla görüntü oluşturulduğunda en iyi sonucu verir.
Örneğin, aynı anda 4 görsel üretiyorsanız, çözümleme (decoding) işlemi tepe aktivasyon belleğini 4 kat artırır. VAE dilimleme (slicing), 4 görselin tamamını aynı anda çözmek yerine her seferinde yalnızca 1 görseli çözerek bu artışı azaltır.
Dilimlenmiş VAE'yi etkinleştirmek için enable_slicing() çağrısını yapın. Çoklu görüntü toplu işlemlerini çözerken performansın küçük ölçüde artmasını, tek görüntülü toplu işlemlerde ise performans etkisi görmemenizi bekleyebilirsiniz.
import torch
from diffusers import AutoModel, StableDiffusionXLPipeline
pipeline = StableDiffusionXLPipeline.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0",
dtype=torch.float16,
).to("cuda") # or "mps", "xpu", "cpu"
pipeline.vae.enable_slicing()
pipeline(["An astronaut riding a horse on Mars"]*32).images[0]
print(f"Max memory reserved: {torch.cuda.max_memory_allocated() / 1024**3:.2f} GB")
AutoencoderKLWan ve AsymmetricAutoencoderKL sınıfları dilimlemeyi desteklemez.
VAE karolama
VAE tiling, bir görüntüyü tek seferde işlemek yerine daha küçük, üst üste binen karolara bölerek bellek tasarrufu sağlar. Bu, GPU'nun bir anda yalnızca bir karoyu işlemesi nedeniyle tepe bellek kullanımını da azaltır.
VAE karolarını etkinleştirmek için enable_tiling() çağrısını yapın. Karolar ayrı ayrı çözümlendiği için üretilen görüntüde karoladan karolaya hafif ton farklılıkları görülebilir, ancak karolar arasında belirgin dikişler olmamalıdır. Çözünürlük, önceden belirlenmiş (ancak yapılandırılabilir) bir sınırın altındaysa karolama devre dışı bırakılır. Örneğin, StableDiffusionPipeline içindeki VAE için bu sınır 512x512'dir.
import torch
from diffusers import AutoPipelineForImage2Image
from diffusers.utils import load_image
pipeline = AutoPipelineForImage2Image.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0", dtype=torch.float16
).to("cuda") # or "mps", "xpu", "cpu"
pipeline.vae.enable_tiling()
init_image = load_image("https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/img2img-sdxl-init.png")
prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k"
pipeline(prompt, image=init_image, strength=0.5).images[0]
print(f"Max memory reserved: {torch.cuda.max_memory_allocated() / 1024**3:.2f} GB")
AutoencoderKLWan ve AsymmetricAutoencoderKL karoları (tiling) desteklemez.
Offloading
Offload stratejileri, şu anda aktif olmayan katmanları veya modelleri GPU belleğinin artmasını önlemek için CPU'ya taşır. Bu stratejiler, çıkarım hızı ile bellek kullanımı arasında denge kurmak için kuantizasyon ve torch.compile ile birleştirilebilir.
Daha fazla ayrıntı için Derlenmiş ve offload edilmiş kuantize modeller kılavuzuna başvurun.
CPU'ya aktarma
CPU offloading, ağırlıkları seçici olarak GPU'dan CPU'ya taşır. Bir bileşen gerektiğinde GPU'ya aktarılır, gerekmediğinde ise CPU'ya taşınır. Bu yöntem, tüm modeller yerine alt modüller üzerinde çalışır. Tüm modeli GPU'da depolamaktan kaçınarak bellek tasarrufu sağlar.
CPU offloading bellek kullanımını dramatik olarak azaltır ancak alt modüllerin cihazlar arasında birden fazla kez ileri geri geçirilmesi nedeniyle son derece yavaştır. Bu kadar yavaş olması nedeniyle çoğu zaman pratik olmayabilir.
enable_sequential_cpu_offload() çağrısından önce pipeline'ı CUDA'ya taşımayın, aksi takdirde tasarruf edilen bellek miktarı yalnızca minimal olacaktır (daha fazla ayrıntı için bu issue'a bakın). Bu, modele kancalar (hooks) kuran durumlu bir işlemdir.
Bir pipeline üzerinde etkinleştirmek için enable_sequential_cpu_offload() çağrısını yapın.
import torch
from diffusers import DiffusionPipeline
pipeline = DiffusionPipeline.from_pretrained(
"black-forest-labs/FLUX.1-schnell", dtype=torch.bfloat16
)
pipeline.enable_sequential_cpu_offload()
pipeline(
prompt="An astronaut riding a horse on Mars",
guidance_scale=0.,
height=768,
width=1360,
num_inference_steps=4,
max_sequence_length=256,
).images[0]
print(f"Max memory reserved: {torch.cuda.max_memory_allocated() / 1024**3:.2f} GB")
Model aktarımı
Model offloading, bazı katmanların veya model bileşenlerinin seçici olarak taşınması yerine tüm modelleri GPU'ya taşır. Ana hat modellerinden biri, genellikle metin kodlayıcı, UNet ve VAE, GPU'ya yerleştirilirken diğer bileşenler CPU'da tutulur. Birden fazla kez çalışan UNet gibi bileşenler, tamamen bitirilip artık ihtiyaç duyulmadığına kadar GPU'da kalır. Bu, CPU offloading iletişiminin getirdiği ek yükü ortadan kaldırır ve model offloading'i daha hızlı bir alternatif haline getirir. Bunun bedeli ise bellek tasarrufunun o kadar büyük olmayacağıdır.
Modeler, hookler kurulduktan sonra pipeline dışında yeniden kullanılırsa (daha fazla ayrıntı için Hook Kaldırma bölümüne bakın), bunları doğru şekilde offload edebilmek için tüm pipeline'ı ve modelleri beklenen sırayla çalıştırmanız gerektiğini unutmayın. Bu, modele hooklar kuran durumlu bir işlemdir.
Bir pipeline üzerinde etkinleştirmek için enable_model_cpu_offload() çağrısını yapın.
import torch
from diffusers import DiffusionPipeline
pipeline = DiffusionPipeline.from_pretrained(
"black-forest-labs/FLUX.1-schnell", dtype=torch.bfloat16
)
pipeline.enable_model_cpu_offload()
pipeline(
prompt="An astronaut riding a horse on Mars",
guidance_scale=0.,
height=768,
width=1360,
num_inference_steps=4,
max_sequence_length=256,
).images[0]
print(f"Max memory reserved: {torch.cuda.max_memory_allocated() / 1024**3:.2f} GB")
enable_model_cpu_offload(), metin kodlayıcıların gizli durumunu üretmek için encode_prompt() yöntemini tek başına kullanırken de yardımcı olur.
Grup dışa aktarma
Group offloading, iç katman gruplarını (torch.nn.ModuleList veya torch.nn.Sequential) CPU'ya taşır. model offloading'den daha az bellek kullanır ve iletişim maliyetini azalttığı için CPU offloading'den daha hızlıdır.
Group offloading, ileri (forward) uygulaması girdilerin ağırlıklara bağlı cihaz dökümünü (device casting) içeriyorsa, tüm modellerle çalışmayabilir; çünkü bu durum, group offloading'in kendi cihaz döküm mekanizmasıyla çelişebilir.
offload_type parametresini block_level veya leaf_level olarak yapılandırarak grup boşaltmayı etkinleştirin.
block_level,num_blocks_per_groupparametresine göre katman gruplarını taşır (offload). Örneğin, 40 katmanlı bir modeldenum_blocks_per_group=2ise, her seferinde 2 katman yüklenir (onload) ve taşınır (offload) (toplamda 20 onload/offload). Bu, bellek gereksinimlerini önemli ölçüde azaltır.leaf_level, en düşük seviyede katmanları tek tek taşır ve CPU offloading ile eşdeğerdir. Ancak, çıkarım hızından ödün vermeden akışlar (streams) kullanarak daha hızlı hale getirilebilir.
Grup offload, tüm pipeline'lar veya bireysel modeller için desteklenir. Grup offload'ın tüm pipeline'a uygulanması en kolay seçenekken, bireysel modellere seçici olarak uygulanması, kullanıcılara farklı modeller için farklı offload teknikleri kullanma konusunda daha fazla esneklik sağlar.
Bir pipeline üzerinde enable_group_offload() çağırın.
import torch
from diffusers import CogVideoXPipeline
from diffusers.hooks import apply_group_offloading
from diffusers.utils import export_to_video
onload_device = torch.device("cuda")
offload_device = torch.device("cpu")
pipeline = CogVideoXPipeline.from_pretrained("THUDM/CogVideoX-5b", dtype=torch.bfloat16)
pipeline.enable_group_offload(
onload_device=onload_device,
offload_device=offload_device,
offload_type="leaf_level",
use_stream=True
)
prompt = (
"A panda, dressed in a small, red jacket and a tiny hat, sits on a wooden stool in a serene bamboo forest. "
"The panda's fluffy paws strum a miniature acoustic guitar, producing soft, melodic tunes. Nearby, a few other "
"pandas gather, watching curiously and some clapping in rhythm. Sunlight filters through the tall bamboo, "
"casting a gentle glow on the scene. The panda's face is expressive, showing concentration and joy as it plays. "
"The background includes a small, flowing stream and vibrant green foliage, enhancing the peaceful and magical "
"atmosphere of this unique musical performance."
)
video = pipeline(prompt=prompt, guidance_scale=6, num_inference_steps=50).frames[0]
print(f"Max memory reserved: {torch.cuda.max_memory_allocated() / 1024**3:.2f} GB")
export_to_video(video, "output.mp4", fps=8)
ModelMixin sınıfından türeyen standart Diffusers model bileşenlerinde enable_group_offload() çağrın. ModelMixin sınıfından türemeyen, örneğin genel bir torch.nn.Module gibi diğer model bileşenleri için bunun yerine apply_group_offloading() kullanın.
import torch
from diffusers import CogVideoXPipeline
from diffusers.hooks import apply_group_offloading
from diffusers.utils import export_to_video
onload_device = torch.device("cuda")
offload_device = torch.device("cpu")
pipeline = CogVideoXPipeline.from_pretrained("THUDM/CogVideoX-5b", dtype=torch.bfloat16)
# Use the enable_group_offload method for Diffusers model implementations
pipeline.transformer.enable_group_offload(onload_device=onload_device, offload_device=offload_device, offload_type="leaf_level")
pipeline.vae.enable_group_offload(onload_device=onload_device, offload_type="leaf_level")
# Use the apply_group_offloading method for other model components
apply_group_offloading(pipeline.text_encoder, onload_device=onload_device, offload_type="block_level", num_blocks_per_group=2)
prompt = (
"A panda, dressed in a small, red jacket and a tiny hat, sits on a wooden stool in a serene bamboo forest. "
"The panda's fluffy paws strum a miniature acoustic guitar, producing soft, melodic tunes. Nearby, a few other "
"pandas gather, watching curiously and some clapping in rhythm. Sunlight filters through the tall bamboo, "
"casting a gentle glow on the scene. The panda's face is expressive, showing concentration and joy as it plays. "
"The background includes a small, flowing stream and vibrant green foliage, enhancing the peaceful and magical "
"atmosphere of this unique musical performance."
)
video = pipeline(prompt=prompt, guidance_scale=6, num_inference_steps=50).frames[0]
print(f"Max memory reserved: {torch.cuda.max_memory_allocated() / 1024**3:.2f} GB")
export_to_video(video, "output.mp4", fps=8)
CUDA akışı
use_stream parametresi, asenkron veri aktarım akışlarını destekleyen CUDA cihazlarında, CPU offloading ile karşılaştırıldığında genel çalışma süresini azaltmak için etkinleştirilebilir. Katman ön yükleme (layer prefetching) kullanarak veri aktarımı ile hesaplamayı üst üste bindirir. Çalıştırılacak bir sonraki katman, mevcut katman hâlâ çalıştırılırken GPU'ya yüklenir. Bu, CPU belleğini önemli ölçüde artırabilir; bu nedenle model boyutunun iki katı kadar belleğe sahip olduğunuzdan emin olun.
Daha fazla hızlanma için hafif bir bellek kullanımı artışı pahasına record_stream=True ayarlayın. Daha fazla bilgi için torch.Tensor.record_stream belgelerine bakın.
Tiling etkinleştirilmiş VAE'lerde
use_stream=Truekullanırken, cihaz uyumsuzluğu hatalarını önlemek için çıkarımdan önce sahte bir ileri geçiş (sahte girdilerle de yapılabilir) yapmanızdan emin olun. Bu, tüm uygulamalarda çalışmayabilir, bu nedenle herhangi bir sorunla karşılaşırsanız bir sorun (issue) açmaktan çekinmeyin.
block_level grup offloading kullanıyorsanız ve use_stream etkinleştirildiyse, num_blocks_per_group parametresi 1 olarak ayarlanmalıdır, aksi takdirde bir uyarı oluşturulur.
pipeline.transformer.enable_group_offload(onload_device=onload_device, offload_device=offload_device, offload_type="leaf_level", use_stream=True, record_stream=True)
low_cpu_mem_usage parametresi, grup dışa aktarma sırasında akışlar kullanılırken CPU bellek kullanımını azaltmak için True olarak ayarlanabilir. Bu, leaf_level dışa aktarma ve CPU belleğinin darboğaz olduğu durumlarda en iyi seçenektir. Bellek, önceden sabitlemek yerine sabitlenmiş tensörleri anlık olarak oluşturarak tasarruf edilir. Ancak bu, genel çalışma süresini artırabilir.
Disk'e aktarma
Grup dışa aktarma, model boyutuna bağlı olarak önemli miktarda sistem belleği tüketebilir. Sınırlı belleğe sahip sistemlerde, ikincil bellek olarak diske grup dışa aktarmayı deneyin.
Modeli diske taşımak için offload_to_disk_path argümanını enable_group_offload() veya apply_group_offloading() içinde ayarlayın.
pipeline.transformer.enable_group_offload(onload_device=onload_device, offload_device=offload_device, offload_type="leaf_level", offload_to_disk_path="path/to/disk")
apply_group_offloading(pipeline.text_encoder, onload_device=onload_device, offload_type="block_level", num_blocks_per_group=2, offload_to_disk_path="path/to/disk")
Hız ve bellek ödünleşimlerini karşılaştırmak için bu iki tabloya başvurun.
Katman bazlı döküm
Daha fazla bellek tasarrufu için katman bazlı dökümleme (casting) ile grup offloading özelliğini birleştirin.
Layerwise casting, ağırlıkları daha küçük bir veri biçiminde (örneğin torch.float8_e4m3fn ve torch.float8_e5m2) saklayarak daha az bellek kullanır ve bu ağırlıkları hesaplama için torch.float16 veya torch.bfloat16 gibi daha yüksek bir hassasiyete yükseltir. fp8'de saklanmalarının üretim kalitesini düşürebilmesi nedeniyle belirli katmanlar (normalizasyon ve modülasyon ile ilgili ağırlıklar) atlanır.
Katman bazlı dönüştürme, ileri (forward) uygulaması ağırlıkların içsel tip dönüşümünü içeriyorsa tüm modellerle çalışmayabilir. Katman bazlı dönüştürmenin mevcut uygulaması, ileri geçişin ağırlık hassasiyetinden bağımsız olduğunu ve girdi veri türlerinin her zaman
compute_dtypeolarak belirtildiğini varsayar (uyumsuz bir uygulama için buraya bakın).Katman bazlı dönüştürme, PEFT katmanlarına sahip özel modelleme uygulamalarında da başarısız olabilir. Bazı kontroller mevcuttur ancak bunlar kapsamlı şekilde test edilmemiştir ve tüm durumlarda çalışacağı garanti edilmemektedir.
Depolama ve hesaplama veri türlerini ayarlamak için enable_layerwise_casting() çağrın.
import torch
from diffusers import CogVideoXPipeline, CogVideoXTransformer3DModel
from diffusers.utils import export_to_video
transformer = CogVideoXTransformer3DModel.from_pretrained(
"THUDM/CogVideoX-5b",
subfolder="transformer",
dtype=torch.bfloat16
)
transformer.enable_layerwise_casting(storage_dtype=torch.float8_e4m3fn, compute_dtype=torch.bfloat16)
pipeline = CogVideoXPipeline.from_pretrained("THUDM/CogVideoX-5b",
transformer=transformer,
dtype=torch.bfloat16
).to("cuda") # or "mps", "xpu", "cpu"
prompt = (
"A panda, dressed in a small, red jacket and a tiny hat, sits on a wooden stool in a serene bamboo forest. "
"The panda's fluffy paws strum a miniature acoustic guitar, producing soft, melodic tunes. Nearby, a few other "
"pandas gather, watching curiously and some clapping in rhythm. Sunlight filters through the tall bamboo, "
"casting a gentle glow on the scene. The panda's face is expressive, showing concentration and joy as it plays. "
"The background includes a small, flowing stream and vibrant green foliage, enhancing the peaceful and magical "
"atmosphere of this unique musical performance."
)
video = pipeline(prompt=prompt, guidance_scale=6, num_inference_steps=50).frames[0]
print(f"Max memory reserved: {torch.cuda.max_memory_allocated() / 1024**3:.2f} GB")
export_to_video(video, "output.mp4", fps=8)
Daha fazla kontrol ve esneklik gerekiyorsa apply_layerwise_casting() metodu da kullanılabilir. Belirli iç modüller üzerinde çağrılarak model katmanlarına kısmen uygulanabilir. Normalizasyon ve modülasyon katmanları gibi kaçınılması gereken modülleri belirtmek için skip_modules_pattern veya skip_modules_classes parametrelerini kullanın.
import torch
from diffusers import CogVideoXTransformer3DModel
from diffusers.hooks import apply_layerwise_casting
transformer = CogVideoXTransformer3DModel.from_pretrained(
"THUDM/CogVideoX-5b",
subfolder="transformer",
dtype=torch.bfloat16
)
# skip the normalization layer
apply_layerwise_casting(
transformer,
storage_dtype=torch.float8_e4m3fn,
compute_dtype=torch.bfloat16,
skip_modules_classes=["norm"],
non_blocking=True,
)
torch.channels_last
torch.channels_last, tensörlerin depolanma biçimini (batch size, channels, height, width) düzeninden (batch size, height, width, channels) düzenine çevirir. Bu, tensörlerin bellekteki depolama düzeniyle donanımın tensörlere sıralı erişim yapma biçimini hizalar ve piksel değerlerine erişmek için bellekte ileri geri atlamaları önler.
Tüm operatörler şu anda channels-last formatını desteklememekte ve bu durum daha düşük performansa yol açabilir, ancak yine de denemeye değerdir.
print(pipeline.unet.conv_out.state_dict()["weight"].stride()) # (2880, 9, 3, 1)
pipeline.unet.to(memory_format=torch.channels_last) # in-place operation
print(
pipeline.unet.conv_out.state_dict()["weight"].stride()
) # (2880, 1, 960, 320) having a stride of 1 for the 2nd dimension proves that it works
Hafıza-verimli dikkat
Diffusers, set_attention_backend() aracılığıyla birden fazla bellek verimli dikkat (attention) arka uçunu (FlashAttention, xFormers, SageAttention ve diğerleri) destekler. Bunlar arasında nasıl geçiş yapılacağını öğrenmek için Attention backends kılavuzuna başvurun.
Xet Storage Details
- Size:
- 31.3 kB
- Xet hash:
- 3067f8066ce8b40f5bf1f104cfd2449afa5001e13f47fa180d4ed33e5c02f6f4
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.