Buckets:

mishig's picture
|
download
raw
8.05 kB

Inférence par lots

L’inférence par lots traite plusieurs invites à la fois pour augmenter le débit. Un lot maintient le GPU occupé, tandis qu’une invite unique le laisse sous-utilisé.

L'inconvénient est une latence plus élevée, car vous attendez que le lot entier soit terminé. Les lots volumineux nécessitent également plus de mémoire GPU.

Traiter plusieurs invites par lot

Passez une liste de prompts au pipeline pour générer une image pour chaque prompt.

import torch
import matplotlib.pyplot as plt
from diffusers import DiffusionPipeline

pipeline = DiffusionPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    dtype=torch.float16,
    device_map="cuda"  # or "mps", "xpu", "cpu"
)

prompts = [
    "Cinematic shot of a cozy coffee shop interior, warm pastel light streaming through a window where a cat rests. Shallow depth of field, glowing cups in soft focus, dreamy lofi-inspired mood, nostalgic tones, framed like a quiet film scene.",
    "Polaroid-style photograph of a cozy coffee shop interior, bathed in warm pastel light. A cat sits on the windowsill near steaming mugs. Soft, slightly faded tones and dreamy blur evoke nostalgia, a lofi mood, and the intimate, imperfect charm of instant film.",
    "Soft watercolor illustration of a cozy coffee shop interior, pastel washes of color filling the space. A cat rests peacefully on the windowsill as warm light glows through. Gentle brushstrokes create a dreamy, lofi-inspired atmosphere with whimsical textures and nostalgic calm.",
    "Isometric pixel-art illustration of a cozy coffee shop interior in detailed 8-bit style. Warm pastel light fills the space as a cat rests on the windowsill. Blocky furniture and tiny mugs add charm, low-res retro graphics enhance the nostalgic, lofi-inspired game aesthetic."
]

images = pipeline(
    prompt=prompts,
).images

fig, axes = plt.subplots(2, 2, figsize=(12, 12))
axes = axes.flatten()

for i, image in enumerate(images):
    axes[i].imshow(image)
    axes[i].set_title(f"Image {i+1}")
    axes[i].axis('off')

plt.tight_layout()
plt.show()

Générer plusieurs images par invite

Pour générer plusieurs variations d'un même prompt, utilisez l'argument num_images_per_prompt.

import torch
import matplotlib.pyplot as plt
from diffusers import DiffusionPipeline

pipeline = DiffusionPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    dtype=torch.float16,
    device_map="cuda"  # or "mps", "xpu", "cpu"
)

prompt="""
Isometric pixel-art illustration of a cozy coffee shop interior in detailed 8-bit style. Warm pastel light fills the
space as a cat rests on the windowsill. Blocky furniture and tiny mugs add charm, low-res retro graphics enhance the
nostalgic, lofi-inspired game aesthetic.
"""

images = pipeline(
    prompt=prompt,
    num_images_per_prompt=4
).images

fig, axes = plt.subplots(2, 2, figsize=(12, 12))
axes = axes.flatten()

for i, image in enumerate(images):
    axes[i].imshow(image)
    axes[i].set_title(f"Image {i+1}")
    axes[i].axis('off')

plt.tight_layout()
plt.show()

Générer plusieurs images pour plusieurs prompts

Combinez les deux approches pour générer différentes variations de différents prompts. Cet exemple réutilise le pipeline et les prompts des exemples ci-dessus.

images = pipeline(
    prompt=prompts,
    num_images_per_prompt=2,
).images

fig, axes = plt.subplots(2, 4, figsize=(12, 12))
axes = axes.flatten()

for i, image in enumerate(images):
    axes[i].imshow(image)
    axes[i].set_title(f"Image {i+1}")
    axes[i].axis('off')

plt.tight_layout()
plt.show()

Générer des lots reproductibles

Pour rendre un lot reproductible, passez au pipeline une liste d'objets Generator, un pour chaque image, chacun avec sa propre graine.

Consultez la documentation Reproductibilité pour en savoir plus sur les algorithmes déterministes et l'objet Generator.

Créez un Generator par image à l'aide d'une compréhension de liste. Multiplier une liste ([generator] * 3) vous donne trois références au même Generator, de sorte que les images ne reçoivent pas de graines indépendantes.

# don't do this
generator = [torch.Generator(device="cuda").manual_seed(0)] * 3  # or "mps", "xpu", "cpu"

Le nombre de générateurs doit correspondre au nombre d'images du lot. Passez le generator au pipeline.

import torch
import matplotlib.pyplot as plt
from diffusers import DiffusionPipeline

pipeline = DiffusionPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    dtype=torch.float16,
    device_map="cuda"
)

prompts = [
    "Cinematic shot of a cozy coffee shop interior, warm pastel light streaming through a window where a cat rests. Shallow depth of field, glowing cups in soft focus, dreamy lofi-inspired mood, nostalgic tones, framed like a quiet film scene.",
    "Polaroid-style photograph of a cozy coffee shop interior, bathed in warm pastel light. A cat sits on the windowsill near steaming mugs. Soft, slightly faded tones and dreamy blur evoke nostalgia, a lofi mood, and the intimate, imperfect charm of instant film.",
    "Soft watercolor illustration of a cozy coffee shop interior, pastel washes of color filling the space. A cat rests peacefully on the windowsill as warm light glows through. Gentle brushstrokes create a dreamy, lofi-inspired atmosphere with whimsical textures and nostalgic calm.",
    "Isometric pixel-art illustration of a cozy coffee shop interior in detailed 8-bit style. Warm pastel light fills the space as a cat rests on the windowsill. Blocky furniture and tiny mugs add charm, low-res retro graphics enhance the nostalgic, lofi-inspired game aesthetic."
]
generator = [torch.Generator(device="cuda").manual_seed(i) for i in range(len(prompts))]  # or "mps", "xpu", "cpu"

images = pipeline(
    prompt=prompts,
    generator=generator
).images

fig, axes = plt.subplots(2, 2, figsize=(12, 12))
axes = axes.flatten()

for i, image in enumerate(images):
    axes[i].imshow(image)
    axes[i].set_title(f"Image {i+1}")
    axes[i].axis('off')

plt.tight_layout()
plt.show()

Chaque image est associée à une graine, ce qui vous permet de choisir une image qui vous plaît et de la régénérer avec la même graine tout en affinant son prompt.

Gérer les requêtes concurrentes

Un serveur augmente également le débit en traitant simultanément les requêtes de nombreux utilisateurs. Chargez le pipeline une seule fois et partagez-le entre les requêtes afin que les modèles restent en mémoire GPU une seule fois. Les planificateurs ne sont pas sûrs pour le multithreading, il est donc nécessaire d’attribuer à chaque requête son propre planificateur via from_pipe(). Partager un seul planificateur entre plusieurs threads provoque des erreurs telles que IndexError: index 21 is out of bounds for dimension 0 with size 21.

scheduler = shared_pipeline.scheduler.from_config(shared_pipeline.scheduler.config)
pipeline = StableDiffusion3Pipeline.from_pipe(shared_pipeline, scheduler=scheduler)

Pour des serveurs complets construits avec FastAPI, consultez l’exemple server et l’exemple server-async. L’exemple server-async clone également l’état du générateur de nombres aléatoires pour chaque requête et rend les tokenizers sûrs à partager entre les threads.

Étapes suivantes

  • Lorsqu'un lot ne tient pas sur une seule GPU, ou que vous avez plus de prompts qu'une seule GPU ne peut en traiter, répartissez les prompts sur plusieurs GPU grâce au parallélisme de données.

Xet Storage Details

Size:
8.05 kB
·
Xet hash:
1572a738194c64a71f637a706d8fd62d67af693c86832cdb839b54980178c700

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