Buckets:

mishig's picture
|
download
raw
7.23 kB
# Google TPU
Las unidades de procesamiento de tensores (TPU) son los aceleradores de aprendizaje automático de Google, disponibles como Cloud TPU (v6e, v7x). Diffusers se ejecuta en ellos a través de [TorchTPU](https://github.com/google-pytorch/torch_tpu/), el backend de PyTorch para TPU, con cambios mínimos en el código.
Hay disponibles tres modos de ejecución:
| Modo | Constante | Cómo activar | Notas |
|---|---|---|---|
| Eager estricto (predeterminado) | `EagerMode.DEFER_NEVER` | `pipe.to("tpu")` | Operaciones despachadas una a la vez, asíncronas |
| Eager optimizado | `EagerMode.DEFER_AND_FUSE` | `TORCH_TPU_DEFER_AND_FUSE=1` | Operaciones diferidas y fusionadas en grafos más grandes; más rápido que el modo estricto eager, con una compilación más larga |
| Compilar | — | `torch.compile(module, backend="tpu")` | Compilación AOT con `TpuBackend` |
Siga la [guía de instalación de TorchTPU](https://github.com/google-pytorch/torch_tpu/). Una vez instalado, `import torch` lo carga automáticamente y registra el dispositivo `"tpu"`, por lo que `pipe.to("tpu")` es el único cambio necesario. Añada `import torch_tpu` solo si deshabilitó la carga automática del backend con `TORCH_DEVICE_BACKEND_AUTOLOAD=0`.
## Modo eager
FLUX.1-schnell no cabe en un solo chip v6e a la vez, por lo que use [enable_model_cpu_offload()](/docs/diffusers/v0.43.0/es/api/pipelines/overview#diffusers.DiffusionPipeline.enable_model_cpu_offload) para mover cada modelo al TPU solo mientras se ejecuta. Detecta automáticamente el dispositivo `"tpu"`.
```python
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")
```
Si un modelo es demasiado grande para un solo chip, o si tienes varios chips y quieres una latencia más baja, divide los modelos entre los chips. Consulta la sección [Paralelismo de tensores](#tensor-parallelism).
## Modo compilado
TorchTPU registra `"tpu"` como nombre de backend de `torch.compile` (`TpuBackend` por debajo), por lo que los componentes se compilan como cualquier otro destino de `torch.compile`. La primera llamada (calentamiento) es lenta porque compila; las llamadas posteriores con las mismas formas reutilizan el gráfico compilado.
> [!IMPORTANT]
> TorchTPU requiere **formas estáticas**, por lo que debe pasar `dynamic=False`. Una nueva `height` o `width` vuelve a compilar para esa forma, una sola vez; las formas ya vistas se reutilizan. Cambiar `num_inference_steps` no vuelve a compilar.
Cuando el pipeline completo cabe en un solo chip, muévelo a la TPU y compila el transformer completo. Stable Diffusion 3.5 Medium (~15GB en bf16) cabe en un solo chip v6e.
```python
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")
```
Si el pipeline no cabe en un solo chip:
- Con varios chips, utilice [tensor parallelism](#tensor-parallelism) para fragmentarlo. Todo permanece en la TPU y `pipe.transformer.compile(...)` funciona de la misma manera en el transformer fragmentado.
- Con [enable_model_cpu_offload()](/docs/diffusers/v0.43.0/es/api/pipelines/overview#diffusers.DiffusionPipeline.enable_model_cpu_offload), los hooks de offload no pueden ser trazados por `torch.compile`. En su lugar, compile solo los bloques repetidos del transformer, con `pipe.transformer.compile_repeated_blocks(backend="tpu", fullgraph=True, dynamic=False)`.
## Paralelismo de tensores
Divida en varios chips los modelos demasiado grandes para un solo chip. El codificador de texto (~48GB) y el transformador (~64GB) de FLUX.2-dev superan la capacidad de un chip individual, por lo que el ejemplo siguiente divide ambos:
- el transformer con [TensorParallelConfig](/docs/diffusers/v0.43.0/es/api/parallel#diffusers.TensorParallelConfig), pasado al argumento `parallel_config` de [from_pretrained()](/docs/diffusers/v0.43.0/es/api/models/overview#diffusers.ModelMixin.from_pretrained). Cada rank solo lee su propia porción de cada peso fragmentado, por lo que el modelo completo nunca se materializa. Para más detalles generales sobre TP (`_tp_plan`, colwise/rowwise), consulte la guía de [Tensor parallelism](./tensor_parallelism).
- el codificador de texto con el propio [paralelismo de tensores](https://huggingface.co/docs/transformers/perf_infer_gpu_multi) de Transformers, pasando un [DistributedConfig](https://huggingface.co/docs/transformers/v5.22.2/en/expert_parallelism#transformers.DistributedConfig) y la misma malla.
En TPU, inicializa el grupo de procesos con `backend="tpu_dist"` y construye la malla con `DeviceMesh("tpu", ...)`.
```python
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")
```
Inicie un proceso por chip. Establezca `--nproc_per_node` para usar el número total de chips TPU de su host.
```bash
eval $(python -m torch_tpu._internal.distributed.launchers.singlehost_wrapper | sed 's/^/export /')
torchrun --nproc_per_node=8 flux2_tp.py
```
> [!WARNING]
> El comando de lanzamiento anterior utiliza un módulo interno de TorchTPU (`torch_tpu._internal`), no una API estable, y se espera que cambie en una futura versión de TorchTPU. Consulte el [repositorio de TorchTPU](https://github.com/google-pytorch/torch_tpu/) para conocer la forma actual de lanzar trabajos de varios chips.

Xet Storage Details

Size:
7.23 kB
·
Xet hash:
5470dcb843e21ac74c901239c4b4ac70510a3a896716742196f40b18f221ce60

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.