Diffusers documentation

Google TPU

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

Google TPU

Tensor Processing Units (TPU) — это ускорители машинного обучения от Google, доступные в виде Cloud TPU (v6e, v7x). Diffusers работает на них через TorchTPU, бэкенд PyTorch для TPU, с минимальными изменениями кода.

Доступны три режима выполнения:

РежимПостояннаяКак активироватьПримечания
Строгий режим eager (по умолчанию)EagerMode.DEFER_NEVERpipe.to("tpu")Операции, отправляемые по одной, асинхронные
Оптимизированный режим eagerEagerMode.DEFER_AND_FUSETORCH_TPU_DEFER_AND_FUSE=1Операции откладываются и объединяются в более крупные графы; быстрее строгого режима eager, но время компиляции дольше
Компиляция—torch.compile(module, backend="tpu")AOT-компиляция с TpuBackend

Следуйте инструкции по установке TorchTPU. После установки import torch автоматически загружает его и регистрирует устройство "tpu", поэтому единственным необходимым изменением является pipe.to("tpu"). Добавляйте import torch_tpu только в том случае, если вы отключили автоматическую загрузку бэкенда с помощью TORCH_DEVICE_BACKEND_AUTOLOAD=0.

Режим Eager

FLUX.1-schnell не помещается целиком на одном чипе v6e, поэтому используйте enable_model_cpu_offload(), чтобы перемещать каждую модель на TPU только во время её выполнения. Устройство "tpu" определяется автоматически.

import torch

from diffusers import FluxPipeline

pipe = FluxPipeline.from_pretrained("black-forest-labs/FLUX.1-schnell", dtype=torch.bfloat16)
pipe.enable_model_cpu_offload()

image = pipe(
    prompt="a golden retriever surfing a wave, photorealistic",
    height=1024,
    width=1024,
    num_inference_steps=4,
    guidance_scale=0.0,
).images[0]

image.save("output.png")

Если модель слишком велика для одного чипа или у вас несколько чипов и вы хотите снизить задержку, распределите модели по чипам. См. раздел Tensor parallelism.

Скомпилированный режим

TorchTPU регистрирует "tpu" как имя бэкенда для torch.compile (внутри используется TpuBackend), поэтому компоненты компилируются так же, как и любые другие цели torch.compile. Первый вызов (прогрев) выполняется медленно, так как происходит компиляция; последующие вызовы с теми же формами повторно используют скомпилированный граф.

TorchTPU требует статических форм, поэтому передайте dynamic=False. Новая height или width приводит к повторной компиляции для этой формы один раз; уже встреченные формы переиспользуются. Изменение num_inference_steps не вызывает повторной компиляции.

Если весь пайплайн помещается на один чип, перенесите его на TPU и скомпилируйте полный трансформер. Stable Diffusion 3.5 Medium (~15 ГБ в bf16) помещается на один чип v6e.

import torch

from diffusers import StableDiffusion3Pipeline

pipe = StableDiffusion3Pipeline.from_pretrained("stabilityai/stable-diffusion-3.5-medium", dtype=torch.bfloat16)
pipe.to("tpu")
pipe.transformer.compile(backend="tpu", fullgraph=True, dynamic=False)

# Warmup — triggers static graph compilation.
pipe(prompt="warmup", height=1024, width=1024, num_inference_steps=40, guidance_scale=4.5)

# Later calls with the same shapes reuse the compiled graph.
image = pipe(
    prompt="a golden retriever surfing a wave, photorealistic",
    height=1024,
    width=1024,
    num_inference_steps=40,
    guidance_scale=4.5,
).images[0]

image.save("output.png")

Если пайплайн не помещается на одном чипе:

  • При использовании нескольких чипов вместо этого применяйте tensor parallelism. Всё остаётся на TPU, а pipe.transformer.compile(...) работает так же и с шардированным трансформером.
  • При использовании enable_model_cpu_offload() хуки offload не могут быть отслежены torch.compile. Компилируйте только повторяющиеся блоки трансформера, используя pipe.transformer.compile_repeated_blocks(backend="tpu", fullgraph=True, dynamic=False).

Параллелизм тензоров

Размещайте модели, слишком большие для одного чипа, на нескольких. Текстовый энкодер (~48 ГБ) и трансформер (~64 ГБ) FLUX.2-dev по отдельности превышают объём одного чипа, поэтому в примере ниже оба компонента распределяются по нескольким чипам:

  • трансформер с TensorParallelConfig, переданным в аргумент parallel_config метода from_pretrained(). Каждый ранг читает только свой срез каждого шардированного веса, поэтому полная модель никогда не материализуется. Общие сведения о TP (_tp_plan, colwise/rowwise) см. в руководстве Tensor parallelism.
  • текстовый энкодер с собственным тензорным параллелизмом Transformers, передавая DistributedConfig и ту же сетку.

На TPU инициализируйте группу процессов с backend="tpu_dist" и создайте сетку с помощью DeviceMesh("tpu", ...).

import torch
import torch.distributed as dist
from torch.distributed.device_mesh import DeviceMesh
from transformers import DistributedConfig, Mistral3ForConditionalGeneration

from diffusers import Flux2Pipeline, Flux2Transformer2DModel, TensorParallelConfig

dist.init_process_group(backend="tpu_dist")
mesh = DeviceMesh("tpu", list(range(dist.get_world_size())))

repo_id = "black-forest-labs/FLUX.2-dev"
text_encoder = Mistral3ForConditionalGeneration.from_pretrained(
    repo_id,
    subfolder="text_encoder",
    dtype=torch.bfloat16,
    distributed_config=DistributedConfig(tp_plan="auto"),
    device_mesh=mesh,
)
transformer = Flux2Transformer2DModel.from_pretrained(
    repo_id, subfolder="transformer", dtype=torch.bfloat16, parallel_config=TensorParallelConfig(mesh=mesh)
)
pipe = Flux2Pipeline.from_pretrained(
    repo_id, text_encoder=text_encoder, transformer=transformer, dtype=torch.bfloat16
)
pipe.vae.to("tpu")

image = pipe(
    prompt="a golden retriever surfing a wave, photorealistic",
    num_inference_steps=28,
    generator=torch.Generator("cpu").manual_seed(0),
).images[0]
if dist.get_rank() == 0:
    image.save("output.png")

Запустите один процесс на чип. Установите --nproc_per_node в значение, равное общему числу чипов TPU на вашем хосте.

eval $(python -m torch_tpu._internal.distributed.launchers.singlehost_wrapper | sed 's/^/export /')
torchrun --nproc_per_node=8 flux2_tp.py

Команда запуска выше использует внутренний модуль TorchTPU (torch_tpu._internal), а не стабильный API, и в будущих релизах TorchTPU может измениться. Актуальный способ запуска многочиповых задач смотрите в репозитории TorchTPU.

Update on GitHub