Diffusers documentation

bitsandbytes

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v0.43.0).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

bitsandbytes

bitsandbytes هي الخيار الأسهل لتكميم النموذج إلى 8 و4 بت. يقوم تكميم 8 بت بضرب القيم الشاذة في fp16 مع القيم غير الشاذة في int8، ثم يعيد تحويل القيم غير الشاذة إلى fp16، ويجمعها معًا لإرجاع الأوزان في fp16. يقلل هذا من التأثير التدهوري الذي تتركه القيم الشاذة على أداء النموذج.

تضغط عملية التكميم بدقة 4 بت النموذج بشكل أكبر، وتُستخدم بشكل شائع مع QLoRA لضبط نماذج اللغة الكبيرة المكمّمة.

يُبيّن هذا الدليل كيف يمكن أن تُمكّن عملية التكميم (Quantization) من تشغيل FLUX.1-dev على ذاكرة عرض أقل من 16 جيجابايت، بل وحتى على نسخة مجانية من Google Colab.

comparison image

لاستخدام bitsandbytes، تأكد من تثبيت المكتبات التالية:

pip install diffusers transformers accelerate bitsandbytes -U

الآن يمكنك تكميم نموذج عن طريق تمرير BitsAndBytesConfig إلى from_pretrained(). يعمل هذا مع أي نموذج في أي نمط، طالما أنه يدعم التحميل باستخدام Accelerate ويحتوي على طبقات torch.nn.Linear.

8-بت
4-بت

يُقلّل تكميم النموذج بدقة 8 بت من استهلاك الذاكرة إلى النصف:

يُؤيَّد bitsandbytes في كلٍّ من Transformers وDiffusers، لذا يمكنك تكميم كلٍّ من FluxTransformer2DModel وT5EncoderModel.

لوحات Ada وشرائح GPU من السلاسل الأعلى، ننصح بتغيير dtype إلى torch.bfloat16.

لا يتم تكميم CLIPTextModel وAutoencoderKL لأنهما صغيران الحجم بالفعل، ولأن AutoencoderKL يحتوي على عدد قليل فقط من طبقات torch.nn.Linear.

from diffusers import BitsAndBytesConfig as DiffusersBitsAndBytesConfig
from transformers import BitsAndBytesConfig as TransformersBitsAndBytesConfig
import torch
from diffusers import AutoModel
from transformers import T5EncoderModel

quant_config = TransformersBitsAndBytesConfig(load_in_8bit=True,)

text_encoder_2_8bit = T5EncoderModel.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    subfolder="text_encoder_2",
    quantization_config=quant_config,
    dtype=torch.float16,
)

quant_config = DiffusersBitsAndBytesConfig(load_in_8bit=True,)

transformer_8bit = AutoModel.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    subfolder="transformer",
    quantization_config=quant_config,
    dtype=torch.float16,
)

بشكل افتراضي، يتم تحويل جميع الوحدات الأخرى مثل torch.nn.LayerNorm إلى torch.float16. يمكنك تغيير نوع البيانات لهذه الوحدات باستخدام معامل dtype.

transformer_8bit = AutoModel.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    subfolder="transformer",
    quantization_config=quant_config,
+   dtype=torch.float32,
)

لنقم بتوليد صورة باستخدام نماذجنا المُكمّاة.

يؤدي تعيين device_map="auto" إلى ملء جميع المساحة المتاحة على وحدات معالجة الرسوميات (GPU) أولاً، ثم وحدة المعالجة المركزية (CPU)، وأخيراً القرص الصلب (وهو الخيار الأبطأ على الإطلاق) إذا لم تكن هناك ذاكرة كافية بعد.

from diffusers import FluxPipeline

pipe = FluxPipeline.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    transformer=transformer_8bit,
    text_encoder_2=text_encoder_2_8bit,
    dtype=torch.float16,
    device_map="auto",
)

pipe_kwargs = {
    "prompt": "A cat holding a sign that says hello world",
    "height": 1024,
    "width": 1024,
    "guidance_scale": 3.5,
    "num_inference_steps": 50,
    "max_sequence_length": 512,
}

image = pipe(**pipe_kwargs, generator=torch.manual_seed(0),).images[0]

عند توفر ذاكرة كافية، يمكنك أيضًا نقل خط الأنابيب مباشرةً إلى وحدة معالجة الرسوميات باستخدام .to("cuda") وتطبيق enable_model_cpu_offload() لتحسين استخدام ذاكرة وحدة معالجة الرسوميات.

Once a model is quantized, you can push the model to the Hub with the push_to_hub() method. The quantization config.json file is pushed first, followed by the quantized model weights. You can also save the serialized 8-bit models locally with save_pretrained().

يدعم التدريب بأوزان 8 بت و4 بت تدريب معاملات إضافية فقط.

تحقق من بصمتك في الذاكرة باستخدام طريقة get_memory_footprint:

print(model.get_memory_footprint())

لاحظ أن هذا يخبرك فقط بحجم الذاكرة الذي تشغله معاملات النموذج ولا يقوم بتقدير متطلبات الذاكرة للاستدلال.

يمكن تحميل النماذج المُكمّمة من طريقة from_pretrained() دون الحاجة إلى تحديد معاملات quantization_config:

from diffusers import AutoModel, BitsAndBytesConfig

quantization_config = BitsAndBytesConfig(load_in_4bit=True)

model_4bit = AutoModel.from_pretrained(
    "hf-internal-testing/flux.1-dev-nf4-pkg", subfolder="transformer"
)

8-بت (خوارزمية LLM.int8())

تعرف على المزيد من التفاصيل حول التكميم بدقة 8 بت في هذا المقال!

يستكشف هذا القسم بعض الميزات المحددة لنماذج 8-بت، مثل حدود القيم الشاذة وتخطي تحويل الوحدات.

حدّ القيم الشاذة

يُعدّ «القيمة الشاذة» قيمةً لحالة مخفية تتجاوز حدًّا معينًا، وتُحسب هذه القيم بدقة fp16. وعلى الرغم من أن القيم موزعة عادةً بشكل طبيعي ([-3.5, 3.5])، إلا أن هذا التوزيع قد يختلف اختلافًا كبيرًا في النماذج الكبيرة ([-60, 6] أو [6, 60]). تعمل التكميم بدقة 8 بت بشكل جيد للقيم حوالي 5، ولكن بعد ذلك، يوجد عقوبة أداء كبيرة. القيمة الافتراضية الجيدة للحد هي 6، لكن قد يكون هناك حاجة إلى حد أدنى للنماذج الأقل استقرارًا (النماذج الصغيرة أو الضبط الدقيق).

لإيجاد أفضل حد عتبة لنموذجك، نقترح تجربة معامل llm_int8_threshold في BitsAndBytesConfig:

from diffusers import AutoModel, BitsAndBytesConfig

quantization_config = BitsAndBytesConfig(
    load_in_8bit=True, llm_int8_threshold=10,
)

model_8bit = AutoModel.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    subfolder="transformer",
    quantization_config=quantization_config,
)

تخطي تحويل الوحدة

في بعض النماذج، لا حاجة إلى تكميم كل وحدة إلى 8 بت، إذ قد يؤدي ذلك فعلياً إلى عدم استقرار. على سبيل المثال، في نماذج الانتشار مثل Stable Diffusion 3، يمكن تجاوز وحدة proj_out باستخدام معامل llm_int8_skip_modules في BitsAndBytesConfig:

from diffusers import SD3Transformer2DModel, BitsAndBytesConfig

quantization_config = BitsAndBytesConfig(
    load_in_8bit=True, llm_int8_skip_modules=["proj_out"],
)

model_8bit = SD3Transformer2DModel.from_pretrained(
    "stabilityai/stable-diffusion-3-medium-diffusers",
    subfolder="transformer",
    quantization_config=quantization_config,
)

4 بت (خوارزمية QLoRA)

تعرف على مزيد من التفاصيل في هذا المنشور على المدونة.

يستكشف هذا القسم بعض الميزات المحددة لنماذج 4-بت، مثل تغيير نوع بيانات الحساب، واستخدام نوع بيانات Normal Float 4 (NF4)، واستخدام التكميم المتداخل.

نوع بيانات الحساب

لتسريع الحساب، يمكنك تغيير نوع البيانات من float32 (القيمة الافتراضية) إلى bf16 باستخدام معامل bnb_4bit_compute_dtype في BitsAndBytesConfig:

import torch
from diffusers import BitsAndBytesConfig

quantization_config = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_compute_dtype=torch.bfloat16)

العدد العائم العادي 4 (NF4)

NF4 هو نوع بيانات من 4 بت من ورقة QLoRA، مُعدّل للأوزان المُهيّأة من توزيع طبيعي. يجب عليك استخدام NF4 لتدريب النماذج الأساسية بدقة 4 بت. يمكن ضبط ذلك عبر معامل bnb_4bit_quant_type في BitsAndBytesConfig:

from diffusers import BitsAndBytesConfig as DiffusersBitsAndBytesConfig
from transformers import BitsAndBytesConfig as TransformersBitsAndBytesConfig

from diffusers import AutoModel
from transformers import T5EncoderModel

quant_config = TransformersBitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
)

text_encoder_2_4bit = T5EncoderModel.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    subfolder="text_encoder_2",
    quantization_config=quant_config,
    dtype=torch.float16,
)

quant_config = DiffusersBitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
)

transformer_4bit = AutoModel.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    subfolder="transformer",
    quantization_config=quant_config,
    dtype=torch.float16,
)

في الاستدلال، لا يُحدث bnb_4bit_quant_type تأثيراً كبيراً على الأداء. ومع ذلك، للبقاء متوافقاً مع أوزان النموذج، يجب عليك استخدام قيم bnb_4bit_compute_dtype وdtype.

التكميم المتداخل

التكميم المتداخل هو تقنية يمكنها توفير ذاكرة إضافية دون أي تكلفة أداء إضافية. يقوم هذا الميزة بتنفيذ تكميم ثانوي للأوزان المُكمَّمة مسبقًا لتوفير 0.4 بت/معامل إضافي.

from diffusers import BitsAndBytesConfig as DiffusersBitsAndBytesConfig
from transformers import BitsAndBytesConfig as TransformersBitsAndBytesConfig

from diffusers import AutoModel
from transformers import T5EncoderModel

quant_config = TransformersBitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_use_double_quant=True,
)

text_encoder_2_4bit = T5EncoderModel.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    subfolder="text_encoder_2",
    quantization_config=quant_config,
    dtype=torch.float16,
)

quant_config = DiffusersBitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_use_double_quant=True,
)

transformer_4bit = AutoModel.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    subfolder="transformer",
    quantization_config=quant_config,
    dtype=torch.float16,
)

إلغاء تكميم نماذج bitsandbytes

بمجرد تكميم النموذج، يمكنك إلغاء تكميمه إلى دقته الأصلية، لكن قد يؤدي ذلك إلى فقدان طفيف في الجودة. تأكد من توفر ذاكرة GPU كافية لاستيعاب النموذج بعد إلغاء التكميم.

from diffusers import BitsAndBytesConfig as DiffusersBitsAndBytesConfig
from transformers import BitsAndBytesConfig as TransformersBitsAndBytesConfig

from diffusers import AutoModel
from transformers import T5EncoderModel

quant_config = TransformersBitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_use_double_quant=True,
)

text_encoder_2_4bit = T5EncoderModel.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    subfolder="text_encoder_2",
    quantization_config=quant_config,
    dtype=torch.float16,
)

quant_config = DiffusersBitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_use_double_quant=True,
)

transformer_4bit = AutoModel.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    subfolder="transformer",
    quantization_config=quant_config,
    dtype=torch.float16,
)

text_encoder_2_4bit.dequantize()
transformer_4bit.dequantize()

torch.compile

تسريع الاستدلال باستخدام torch.compile. تأكد من تثبيت أحدث إصدار من bitsandbytes كما نوصي بتثبيت PyTorch nightly.

8-بت
4-بت
torch._dynamo.config.capture_dynamic_output_shape_ops = True

quant_config = DiffusersBitsAndBytesConfig(load_in_8bit=True)
transformer_4bit = AutoModel.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    subfolder="transformer",
    quantization_config=quant_config,
    dtype=torch.float16,
)
transformer_4bit.compile(fullgraph=True)

على بطاقة RTX 4090 مع التجميع، اكتمل توليد Flux بدقة 4 بت في 25.809 ثانية مقابل 32.570 ثانية دون التجميع.

اطّلع على سكربت القياس لمزيد من التفاصيل.

الموارد

Update on GitHub