Diffusers documentation
Reproducibilidad
Reproducibilidad
La difusión es un proceso aleatorio que genera una salida diferente cada vez. Para casos de uso como pruebas y replicación de resultados, se desea generar el mismo resultado cada vez, entre versiones y plataformas, dentro de un cierto rango de tolerancia.
Esta guía le mostrará cómo controlar las fuentes de aleatoriedad y habilitar algoritmos deterministas.
Generador
Los pipelines dependen de torch.randn, que utiliza una semilla aleatoria diferente en cada ejecución, para crear los tensores ruidosos iniciales. Para generar la misma salida en una CPU o GPU, utilice un Generator para gestionar cómo se generan los valores aleatorios.
Si la reproducibilidad es importante, debe usar un
Generatorde CPU. La pérdida de rendimiento suele ser despreciable y generará valores más similares.
Utilice un Generator de CPU cuando le importe la reproducibilidad. El RNG de CPU es más estable entre máquinas.
Cuando se pasa un Generator de CPU, randn_tensor() de Diffusers muestrea en la CPU y mueve el tensor a la GPU dentro del pipeline. No se llama a randn_tensor ni a .to("cuda") manualmente. Un Generator de GPU muestrea directamente en el dispositivo y puede divergir de los resultados de la CPU.
Use manual_seed para establecer una semilla.
import torch
from diffusers import DiffusionPipeline
pipeline = DiffusionPipeline.from_pretrained(
"Qwen/Qwen-Image", dtype=torch.bfloat16, device_map="cuda" # or "mps", "xpu", "cpu"
)
generator = torch.manual_seed(0)
image = pipeline(
prompt="a red apple on a wooden table",
generator=generator,
num_inference_steps=4,
).images[0]Cree un Generator de CPU y establezca una semilla con Generator.manual_seed.
import torch
from diffusers import DiffusionPipeline
pipeline = DiffusionPipeline.from_pretrained(
"Qwen/Qwen-Image", dtype=torch.bfloat16, device_map="cpu"
)
generator = torch.Generator(device="cpu").manual_seed(0)
image = pipeline(
prompt="a red apple on a wooden table",
generator=generator,
num_inference_steps=4,
).images[0]Pase un objeto Generator a la pipeline en lugar de una semilla entera. Un Generator mantiene un estado aleatorio que se consume y actualiza cuando lo utiliza. Después de eso, el mismo objeto produce resultados diferentes en llamadas posteriores, incluso entre pipelines, porque su estado ha cambiado. Vuelva a sembrarlo o cree un nuevo Generator antes de cada llamada cuando necesite la misma semilla de nuevo.
import torch
prompt = "a red apple on a wooden table"
for _ in range(5):
generator = torch.manual_seed(0)
image = pipeline(prompt, generator=generator, num_inference_steps=4).images[0]Algoritmos deterministas
PyTorch admite algoritmos deterministas (cuando están disponibles) para ciertas operaciones para que produzcan los mismos resultados. Los algoritmos deterministas pueden ser más lentos y reducir el rendimiento.
Use enable_full_determinism() de Diffusers para habilitar algoritmos deterministas.
from diffusers.utils.torch_utils import enable_full_determinism
enable_full_determinism()enable_full_determinism funciona de la siguiente manera:
- Establecer la variable de entorno
CUDA_LAUNCH_BLOCKINGen1 - Establecer la variable de entorno CUBLAS_WORKSPACE_CONFIG en
:16:8para que cuBLAS utilice un diseño de espacio de trabajo fijo en tiempo de ejecución - Llamar a
torch.use_deterministic_algorithms(True) - Establecer
torch.backends.cudnn.deterministic = True - Establecer
torch.backends.cudnn.benchmark = Falsepara que cuDNN no elija un algoritmo de convolución diferente en cada ejecución - Desactivar TensorFloat32 (TF32) con
torch.backends.cuda.matmul.allow_tf32 = Falsea favor de un matmul de precisión completa más preciso
Próximos pasos
Deberías leer las notas de desarrollo de PyTorch sobre Reproducibility. Puedes intentar limitar la aleatoriedad, pero no está garantizada ni siquiera con una semilla idéntica.
Update on GitHub