Diffusers documentation
Reprodutibilidade
Reprodutibilidade
A difusão é um processo aleatório que gera uma saída diferente a cada vez. Para casos de uso como testes e replicação de resultados, você deseja gerar o mesmo resultado a cada vez, entre lançamentos e plataformas, dentro de uma certa faixa de tolerância.
Este guia mostrará como controlar as fontes de aleatoriedade e habilitar algoritmos determinísticos.
Gerador
Os Pipelines depend de torch.randn, que utiliza uma semente aleatória diferente a cada vez, para criar os tensores ruidosos iniciais. Para gerar a mesma saída em uma CPU ou GPU, use um Generator para gerenciar como os valores aleatórios são gerados.
Se a reprodutibilidade for importante, você deve usar um
Generatorde CPU. A perda de desempenho é frequentemente insignificante e você gerará valores mais semelhantes.
Use um Generator de CPU quando a reprodutibilidade for uma preocupação. O RNG de CPU é mais estável entre máquinas.
Ao passar um Generator de CPU, o randn_tensor() do Diffusers amostra na CPU e move o tensor para a GPU dentro do pipeline. Você não chama randn_tensor ou .to("cuda") por conta própria. Um Generator de GPU amostra diretamente no dispositivo e pode divergir dos resultados da CPU.
Use manual_seed para definir uma semente.
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]Crie um Generator de CPU e defina uma semente com 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]Passe um objeto Generator para o pipeline em vez de uma semente inteira. Um Generator mantém um estado aleatório que é consumido e atualizado quando você o usa. Depois disso, o mesmo objeto produz resultados diferentes em chamadas posteriores, mesmo entre pipelines, porque seu estado mudou. Replante a semente ou crie um novo Generator antes de cada chamada quando precisar da mesma semente novamente.
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 determinísticos
O PyTorch suporta algoritmos determinísticos (quando disponíveis) para determinadas operações, de modo que elas produzam os mesmos resultados. Os algoritmos determinísticos podem ser mais lentos e reduzir o desempenho.
Use o enable_full_determinism() do Diffusers para habilitar algoritmos determinísticos.
from diffusers.utils.torch_utils import enable_full_determinism
enable_full_determinism()enable_full_determinism funciona da seguinte forma:
- Definir a variável de ambiente
CUDA_LAUNCH_BLOCKINGpara1 - Definir a variável de ambiente CUBLAS_WORKSPACE_CONFIG como
:16:8para que o cuBLAS utilize um layout de workspace fixo em tempo de execução - Chamar
torch.use_deterministic_algorithms(True) - Definindo
torch.backends.cudnn.deterministic = True - Definindo
torch.backends.cudnn.benchmark = Falsepara que o cuDNN não escolha um algoritmo de convolução diferente a cada execução - Desativando o TensorFloat32 (TF32) com
torch.backends.cuda.matmul.allow_tf32 = Falseem favor de um matmul de precisão total mais preciso
Próximas etapas
Você deve ler as notas de desenvolvimento do PyTorch sobre Reproducibility. Você pode tentar limitar a aleatoriedade, mas isso não é garantido, mesmo com uma semente idêntica.
Update on GitHub