Buckets:
| # Reproducibility | |
| Diffusion is a random process that generates a different output every time. For use cases like testing and replicating results, you want to generate the same result each time, across releases and platforms within a certain tolerance range. | |
| This guide will show you how to control sources of randomness and enable deterministic algorithms. | |
| ## Generator | |
| Pipelines rely on [torch.randn](https://pytorch.org/docs/stable/generated/torch.randn.html), which uses a different random seed each time, to create the initial noisy tensors. To generate the same output on a CPU or GPU, use a [Generator](https://docs.pytorch.org/docs/stable/generated/torch.Generator.html) to manage how random values are generated. | |
| > [!TIP] | |
| > If reproducibility is important, you should use a CPU `Generator`. The performance loss is often negligible and you'll generate more similar values. | |
| Use a CPU `Generator` when you care about reproducibility. CPU RNG is more stable across machines. | |
| When you pass a CPU `Generator`, Diffusers’ [randn_tensor()](/docs/diffusers/pr_14865/en/api/utilities#diffusers.utils.torch_utils.randn_tensor) samples on the CPU and moves the tensor to the GPU inside the pipeline. You do not call `randn_tensor` or `.to("cuda")` yourself. A GPU `Generator` samples on-device instead and can diverge from CPU results. | |
| Use [manual_seed](https://docs.pytorch.org/docs/stable/generated/torch.manual_seed.html) to set a seed. | |
| ```py | |
| 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] | |
| ``` | |
| Create a CPU `Generator` and set a seed with [Generator.manual_seed](https://docs.pytorch.org/docs/stable/generated/torch.Generator.html#torch.Generator.manual_seed). | |
| ```py | |
| 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] | |
| ``` | |
| Pass a `Generator` object to the pipeline instead of an integer seed. A `Generator` keeps a random state that is consumed and updated when you use it. After that, the same object produces different results on later calls, even across pipelines, because its state has changed. Reseed it or create a new `Generator` before each call when you need the same seed again. | |
| ```py | |
| 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] | |
| ``` | |
| ## Deterministic algorithms | |
| PyTorch supports [deterministic algorithms](https://docs.pytorch.org/docs/stable/notes/randomness.html#avoiding-nondeterministic-algorithms) (where available) for certain operations so they produce the same results. Deterministic algorithms may be slower and decrease performance. | |
| Use Diffusers' `enable_full_determinism()` to enable deterministic algorithms. | |
| ```py | |
| from diffusers.utils.torch_utils import enable_full_determinism | |
| enable_full_determinism() | |
| ``` | |
| `enable_full_determinism` works by: | |
| - Setting the environment variable `CUDA_LAUNCH_BLOCKING` to `1` | |
| - Setting the environment variable [CUBLAS_WORKSPACE_CONFIG](https://docs.nvidia.com/cuda/cublas/index.html#results-reproducibility) to `:16:8` so cuBLAS uses a fixed workspace layout at runtime | |
| - Calling `torch.use_deterministic_algorithms(True)` | |
| - Setting `torch.backends.cudnn.deterministic = True` | |
| - Setting `torch.backends.cudnn.benchmark = False` so cuDNN does not pick a different convolution algorithm each run | |
| - Disabling TensorFloat32 (TF32) with `torch.backends.cuda.matmul.allow_tf32 = False` in favor of more precise full-precision matmul | |
| ## Next steps | |
| You should read PyTorch's developer notes about [Reproducibility](https://docs.pytorch.org/docs/stable/notes/randomness.html). You can try to limit randomness, but it is not *guaranteed* even with an identical seed. | |
Xet Storage Details
- Size:
- 4.29 kB
- Xet hash:
- e944b504ac2a410d74b9956d94963231e9c00ee37f3af722fffa60ec16ba0a5a
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.