Diffusers documentation

توزيع مكوّنات النموذج على وحدات معالجة الرسوميات باستخدام device_map

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

توزيع مكوّنات النموذج على وحدات معالجة الرسوميات باستخدام device_map

يضع الحجة device_map مكوّنات النموذج على وحدات معالجة رسومية منفصلة. استخدمها عندما لا يتسع النموذج لوحدة معالجة رسومية واحدة ولا تتمتع وحدات المعالجة الرسومية لديك بربط سريع. راجع الاستدلال الموزّع لمقارنتها بالاستراتيجيات الأخرى، وراجع توزيع الأجهزة للحصول على خيارات إضافية لـdevice_map.

يُحمّل المثال أدناه كل مكوّن فقط للمرحلة التي تحتاج إليه، ويستخدم device_map لتوزيع المكوّنات الكبيرة على بطاقتَي GPU.

ترميز الموجه

اضبط device_map="balanced" لوضع مشفّرات النص على وحدات معالجة رسومية منفصلة. استخدم max_memory لتحديد الحد الأقصى لكمية الذاكرة التي تستخدمها كل وحدة معالجة رسومية. اضبط transformer وvae على None بحيث يتم تحميل مشفّرات النص فقط.

from diffusers import FluxPipeline
import torch

prompt = """
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
"""

pipeline = FluxPipeline.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    transformer=None,
    vae=None,
    device_map="balanced",
    max_memory={0: "16GB", 1: "16GB"},
    dtype=torch.bfloat16
)
with torch.no_grad():
    print("Encoding prompts.")
    prompt_embeds, pooled_prompt_embeds, text_ids = pipeline.encode_prompt(
        prompt=prompt, prompt_2=None, max_sequence_length=512
    )

بمجرد حصولك على تمثيلات النص، أزل مشفّرات النص من وحدة معالجة الرسوميات (GPU) لتوفير مساحة للحوّال (transformer).

import gc

def flush():
    gc.collect()
    torch.cuda.empty_cache()
    torch.cuda.reset_max_memory_allocated()
    torch.cuda.reset_peak_memory_stats()

del pipeline.text_encoder
del pipeline.text_encoder_2
del pipeline.tokenizer
del pipeline.tokenizer_2
del pipeline

flush()

إزالة الضوضاء باستخدام المحوّل المجزأ

اضبط device_map="auto" للسماح لـ Accelerate بوضع نموذج التحويل. يملأ أول وحدة معالجة رسومية قبل الانتقال إلى التالية، ولا يستخدم وحدة المعالجة المركزية أو القرص إلا عندما تنفد ذاكرة وحدات المعالجة الرسومية. على وحدتي معالجة رسومية أصغر، ينتهي الأمر بتقسيم نموذج التحويل عبر الوحدتين. الأوزان الموجودة على وحدة المعالجة المركزية أو القرص تُبطئ الاستدلال.

from diffusers import AutoModel
import torch

transformer = AutoModel.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    subfolder="transformer",
    device_map="auto",
    dtype=torch.bfloat16
)

تحقق من transformer.hf_device_map لمعرفة كيفية توزيع النموذج التحويلي على الأجهزة. كما أن خط الأنابيب المحمّل باستخدام device_map يحتوي على خاصية hf_device_map تُظهر مكان وضع كل مكوّن.

حمّل خط أنابيب يحتوي على المحوّل فقط، و اضبط output_type="latent" حتى يعيد الكامنات بدلاً من الصور.

pipeline = FluxPipeline.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    text_encoder=None,
    text_encoder_2=None,
    tokenizer=None,
    tokenizer_2=None,
    vae=None,
    transformer=transformer,
    dtype=torch.bfloat16
)

print("Running denoising.")
height, width = 768, 1360
latents = pipeline(
    prompt_embeds=prompt_embeds,
    pooled_prompt_embeds=pooled_prompt_embeds,
    num_inference_steps=50,
    guidance_scale=3.5,
    height=height,
    width=width,
    output_type="latent",
).images

فكّ ترميز الكمون

أزل خط الأنابيب والمحوّل من الذاكرة، ثم حمّل VAE لفك ترميز الكمّيات الكامنة. VAE صغير بما يكفي ليُحمَّل على وحدة معالجة رسومية واحدة.

import torch
from diffusers import AutoencoderKL
from diffusers.image_processor import VaeImageProcessor

del pipeline.transformer
del pipeline
del transformer

flush()

vae = AutoencoderKL.from_pretrained(
    "black-forest-labs/FLUX.1-dev", subfolder="vae", dtype=torch.bfloat16
).to("cuda")  # or "mps", "xpu", "cpu"
vae_scale_factor = 2 ** (len(vae.config.block_out_channels) - 1)
image_processor = VaeImageProcessor(vae_scale_factor=vae_scale_factor)

with torch.no_grad():
    print("Running decoding.")
    latents = FluxPipeline._unpack_latents(latents, height, width, vae_scale_factor)
    latents = (latents / vae.config.scaling_factor) + vae.config.shift_factor

    image = vae.decode(latents, return_dict=False)[0]
    image = image_processor.postprocess(image, output_type="pil")
    image[0].save("split_transformer.png")

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

Update on GitHub