Diffusers documentation
تجميع نماذج الكمّ وتحميلها
تجميع نماذج الكمّ وتحميلها
غالبًا ما تتضمن تحسين النماذج مقايضات بين سرعة الاستدلال واستهلاك الذاكرة. على سبيل المثال، بينما يمكن لـالتخزين المؤقت أن يعزز سرعة الاستدلال، فإنه يزيد أيضًا من استهلاك الذاكرة نظرًا لاحتياجه إلى تخزين مخرجات طبقات الانتباه الوسيطة. تجمع استراتيجية التحسين الأكثر توازنًا بين تكميم النموذج، وtorch.compile، وطرق التفريغ المختلفة.
راجع دليل torch.compile لمعرفة المزيد حول التجميع وكيفية تطبيقه هنا. على سبيل المثال، يمكن للتجميع الإقليمي أن يقلل بشكل كبير من وقت التجميع دون التنازل عن أي تسريع.
في توليد الصور، يمكن أن يؤدي الجمع بين التكميم وإزاحة النموذج غالبًا إلى تحقيق أفضل توازن بين الجودة والسرعة والذاكرة. ولا تكون إزاحة المجموعات فعالة بنفس القدر في توليد الصور، لأنه عادةً ما يكون من غير الممكن تداخل نقل البيانات بالكامل إذا انتهى نواة الحساب بشكل أسرع. وهذا يؤدي إلى بعض النفقات الإضافية للتواصل بين المعالج المركزي (CPU) ومعالج الرسوميات (GPU).
في توليد الفيديو، يميل الجمع بين التكميم وإزاحة المجموعات إلى أن يكون أفضل لأن نماذج الفيديو تكون أكثر ارتباطاً بالحساب.
توفر الجدول أدناه مقارنة بين تركيبات استراتيجيات التحسين وتأثيرها على زمن الاستجابة واستهلاك الذاكرة في Flux.
| التركيبة | زمن الاستجابة (ثانية) | استهلاك الذاكرة (جيجابايت) |
|---|---|---|
| التكميم | 32.602 | 14.9453 |
| التكميم، torch.compile | 25.847 | 14.9448 |
| التكميم، torch.compile، نقل النموذج إلى وحدة المعالجة المركزية | 32.312 | 12.2369 |
ستُظهر لك هذه الدليل كيفية تجميع نموذج مُكمَّم ونقله باستخدام bitsandbytes. تأكد من أنك تستخدم PyTorch nightly وأحدث إصدار من bitsandbytes.
على الرغم من أننا نستخدم bitsandbytes في هذا المثال، فإن محركات التكميم الأخرى مثل TorchAO تدعم أيضًا هذه الميزات.
pip install -U bitsandbytes
التكميم وtorch.compile
ابدأ بـ تكميم النموذج لتقليل الذاكرة المطلوبة للتخزين و تجميعه لتسريع الاستدلال.
قم بإعداد Dynamo باستخدام capture_dynamic_output_shape_ops = True للتعامل مع المخرجات الديناميكية عند تجميع نماذج bitsandbytes.
import torch
from diffusers import DiffusionPipeline
from diffusers.quantizers import PipelineQuantizationConfig
torch._dynamo.config.capture_dynamic_output_shape_ops = True
# quantize
pipeline_quant_config = PipelineQuantizationConfig(
quant_backend="bitsandbytes_4bit",
quant_kwargs={"load_in_4bit": True, "bnb_4bit_quant_type": "nf4", "bnb_4bit_compute_dtype": torch.bfloat16},
components_to_quantize=["transformer", "text_encoder_2"],
)
pipeline = DiffusionPipeline.from_pretrained(
"black-forest-labs/FLUX.1-dev",
quantization_config=pipeline_quant_config,
dtype=torch.bfloat16,
).to("cuda") # or "mps", "xpu", "cpu"
# compile
pipeline.transformer.to(memory_format=torch.channels_last)
pipeline.transformer.compile(mode="max-autotune", fullgraph=True)
pipeline("""
cinematic film still of a cat sipping a margarita in a pool in Palm Springs, California
highly detailed, high budget hollywood movie, cinemascope, moody, epic, gorgeous, film grain
"""
).images[0]التكميم، وtorch.compile، والتفريغ
بالإضافة إلى التكميم وtorch.compile، جرّب الإزاحة (offloading) إذا كنت بحاجة إلى تقليل استهلاك الذاكرة بشكل أكبر. تقوم الإزاحة بنقل طبقات أو مكونات نموذج مختلفة من وحدة المعالجة المركزية (CPU) إلى وحدة معالجة الرسوميات (GPU) حسب الحاجة للعمليات الحسابية.
قم بتكوين Dynamo cache_size_limit أثناء الإزاحة لتجنب إعادة التجميع المفرط، و اضبط capture_dynamic_output_shape_ops = True للتعامل مع المخرجات الديناميكية عند تجميع نماذج bitsandbytes.
ينقل إزاحة النموذج إلى المعالج المركزي مكوّن خط المعالجة الفردي، مثل نموذج التحوّل، إلى وحدة معالجة الرسوميات عند الحاجة إليه للحساب. وإلا، يتم إزاحته إلى المعالج المركزي.
import torch
from diffusers import DiffusionPipeline
from diffusers.quantizers import PipelineQuantizationConfig
torch._dynamo.config.cache_size_limit = 1000
torch._dynamo.config.capture_dynamic_output_shape_ops = True
# quantize
pipeline_quant_config = PipelineQuantizationConfig(
quant_backend="bitsandbytes_4bit",
quant_kwargs={"load_in_4bit": True, "bnb_4bit_quant_type": "nf4", "bnb_4bit_compute_dtype": torch.bfloat16},
components_to_quantize=["transformer", "text_encoder_2"],
)
pipeline = DiffusionPipeline.from_pretrained(
"black-forest-labs/FLUX.1-dev",
quantization_config=pipeline_quant_config,
dtype=torch.bfloat16,
).to("cuda") # or "mps", "xpu", "cpu"
# model CPU offloading
pipeline.enable_model_cpu_offload()
# compile
pipeline.transformer.compile()
pipeline(
"cinematic film still of a cat sipping a margarita in a pool in Palm Springs, California, highly detailed, high budget hollywood movie, cinemascope, moody, epic, gorgeous, film grain"
).images[0]ينقل تفريغ المجموعات الطبقات الداخلية لمكوّن خط أنابيب فردي، مثل نموذج التحوّل، إلى وحدة معالجة الرسوميات (GPU) لأغراض الحساب، ثم يفرّغه عندما لا يكون مطلوبًا. وفي الوقت نفسه، يستخدم ميزة تدفق CUDA لجلب الطبقة التالية مسبقًا للتنفيذ.
من خلال تداخل الحساب ونقل البيانات، يكون أسرع من نقل النموذج إلى وحدة المعالجة المركزية (CPU) مع توفير الذاكرة أيضًا.
# pip install ftfy
import torch
from diffusers import AutoModel, DiffusionPipeline
from diffusers.hooks import apply_group_offloading
from diffusers.utils import export_to_video
from diffusers.quantizers import PipelineQuantizationConfig
from transformers import UMT5EncoderModel
torch._dynamo.config.cache_size_limit = 1000
torch._dynamo.config.capture_dynamic_output_shape_ops = True
# quantize
pipeline_quant_config = PipelineQuantizationConfig(
quant_backend="bitsandbytes_4bit",
quant_kwargs={"load_in_4bit": True, "bnb_4bit_quant_type": "nf4", "bnb_4bit_compute_dtype": torch.bfloat16},
components_to_quantize=["transformer", "text_encoder"],
)
text_encoder = UMT5EncoderModel.from_pretrained(
"Wan-AI/Wan2.1-T2V-14B-Diffusers", subfolder="text_encoder", dtype=torch.bfloat16
)
pipeline = DiffusionPipeline.from_pretrained(
"Wan-AI/Wan2.1-T2V-14B-Diffusers",
quantization_config=pipeline_quant_config,
dtype=torch.bfloat16,
).to("cuda") # or "mps", "xpu", "cpu"
# group offloading
onload_device = torch.device("cuda")
offload_device = torch.device("cpu")
pipeline.transformer.enable_group_offload(
onload_device=onload_device,
offload_device=offload_device,
offload_type="leaf_level",
use_stream=True,
non_blocking=True
)
pipeline.vae.enable_group_offload(
onload_device=onload_device,
offload_device=offload_device,
offload_type="leaf_level",
use_stream=True,
non_blocking=True
)
apply_group_offloading(
pipeline.text_encoder,
onload_device=onload_device,
offload_type="leaf_level",
use_stream=True,
non_blocking=True
)
# compile
pipeline.transformer.compile()
prompt = """
The camera rushes from far to near in a low-angle shot,
revealing a white ferret on a log. It plays, leaps into the water, and emerges, as the camera zooms in
for a close-up. Water splashes berry bushes nearby, while moss, snow, and leaves blanket the ground.
Birch trees and a light blue sky frame the scene, with ferns in the foreground. Side lighting casts dynamic
shadows and warm highlights. Medium composition, front view, low angle, with depth of field.
"""
negative_prompt = """
Bright tones, overexposed, static, blurred details, subtitles, style, works, paintings, images, static, overall gray, worst quality,
low quality, JPEG compression residue, ugly, incomplete, extra fingers, poorly drawn hands, poorly drawn faces, deformed, disfigured,
misshapen limbs, fused fingers, still picture, messy background, three legs, many people in the background, walking backwards
"""
output = pipeline(
prompt=prompt,
negative_prompt=negative_prompt,
num_frames=81,
guidance_scale=5.0,
).frames[0]
export_to_video(output, "output.mp4", fps=16)