Diffusers documentation

Phân chia các thành phần của mô hình trên các GPU bằng device_map

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

Phân chia các thành phần của mô hình trên các GPU bằng device_map

Tham số device_map đặt các thành phần của mô hình trên các GPU riêng biệt. Hãy sử dụng nó khi một mô hình không vừa trên một GPU và các GPU của bạn không có kết nối nhanh. Tham khảo Suy luận phân tán để so sánh nó với các chiến lược khác, và Đặt thiết bị để biết thêm các tùy chọn device_map.

Ví dụ dưới đây chỉ nạp mỗi thành phần cho giai đoạn cần đến nó, và sử dụng device_map để phân bổ các thành phần lớn sang hai GPU.

Mã hóa prompt

Đặt device_map="balanced" để đặt các text encoder trên các GPU riêng biệt. Sử dụng max_memory để giới hạn lượng bộ nhớ mà mỗi GPU sử dụng. Đặt transformer và vae thành None để chỉ tải các text encoder.

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
    )

Sau khi có được các vector nhúng văn bản, hãy gỡ các bộ mã hóa văn bản khỏi GPU để nhường chỗ cho 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()

Loại bỏ nhiễu bằng transformer phân mảnh

Đặt device_map="auto" để Accelerate tự động bố trí transformer. Nó sẽ lấp đầy GPU đầu tiên trước khi chuyển sang GPU tiếp theo, và chỉ sử dụng CPU hoặc đĩa khi các GPU hết bộ nhớ. Trên hai GPU nhỏ hơn, transformer sẽ được chia đều trên cả hai. Trọng số nằm trên CPU hoặc đĩa sẽ làm chậm suy luận.

from diffusers import AutoModel
import torch

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

Kiểm tra transformer.hf_device_map để xem transformer được phân phối trên các thiết bị như thế nào. Một pipeline được nạp với device_map cũng có thuộc tính hf_device_map cho biết mỗi thành phần được đặt ở đâu.

Tải một pipeline chỉ với transformer, và đặt output_type="latent" để nó trả về latents thay vì hình ảnh.

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

Giải mã các biến tiềm ẩn

Gỡ pipeline và transformer khỏi bộ nhớ và nạp VAE để giải mã các latents. VAE đủ nhỏ để chạy trên một GPU.

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")

Bằng cách tải và gỡ tải có chọn lọc các mô hình bạn cần ở một giai đoạn nhất định và chia nhỏ các mô hình lớn nhất trên nhiều GPU, bạn có thể chạy suy luận với các mô hình lớn trên GPU tiêu dùng.

Update on GitHub