# 再現性

Diffusion はランダムなプロセスであり、実行するたびに異なる出力を生成します。テストや結果の再現性が必要なユースケースでは、特定の許容範囲内で、リリースやプラットフォームをまたいで毎回同じ結果を生成したい場合があります。

このガイドでは、ランダム性のソースを制御し、決定論的アルゴリズムを有効にする方法について説明します。

## ジェネレーター

Pipelines は、初期のノイズ付きテンソルを生成するために、毎回異なる乱数シードを使用する [torch.randn](https://pytorch.org/docs/stable/generated/torch.randn.html) に依存しています。CPU または GPU で同じ出力を生成するには、[Generator](https://docs.pytorch.org/docs/stable/generated/torch.Generator.html) を使用して乱数の生成方法を管理してください。

> [!TIP]
> 再現性が重要である場合は、CPUの`Generator`を使用する必要があります。パフォーマンスの低下は通常無視できるほど小さく、より類似した値を生成できます。

再現性を重視する場合は、CPUの`Generator`を使用してください。CPUの乱数生成は、マシン間でより安定しています。

CPUの`Generator`を渡すと、Diffusersの[randn_tensor()](/docs/diffusers/v0.43.0/ja/api/utilities#diffusers.utils.torch_utils.randn_tensor)はCPU上でサンプリングを行い、パイプライン内でテンソルをGPUに移動します。`randn_tensor`や`.to("cuda")`を自分で呼び出す必要はありません。GPUの`Generator`はデバイス上でサンプリングを行うため、CPUの結果と異なる場合があります。

シードを設定するには、[manual_seed](https://docs.pytorch.org/docs/stable/generated/torch.manual_seed.html)を使用します。

```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]
```

CPUの`Generator`を作成し、[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]
```

整数のシードではなく、パイプラインに`Generator`オブジェクトを渡します。`Generator`は、使用時に消費・更新される乱数状態を保持します。そのため、状態が変化するため、同じオブジェクトでも後続の呼び出しでは異なる結果を生成します。パイプラインをまたいでも同様です。同じシードを再度使用する必要がある場合は、各呼び出しの前に再シードするか、新しい`Generator`を作成してください。

```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]
```

## 決定論的アルゴリズム

PyTorch は、特定の操作に対して [決定論的アルゴリズム](https://docs.pytorch.org/docs/stable/notes/randomness.html#avoiding-nondeterministic-algorithms)（利用可能な場合）をサポートしており、これにより同じ結果が得られます。決定論的アルゴリズムは、処理速度が遅くなり、パフォーマンスが低下する可能性があります。

Diffusers の `enable_full_determinism()` を使用して、決定論的アルゴリズムを有効にします。

```py
from diffusers.utils.torch_utils import enable_full_determinism

enable_full_determinism()
```

`enable_full_determinism` は、次のように動作します。

- 環境変数`CUDA_LAUNCH_BLOCKING`を`1`に設定する
- 環境変数 [CUBLAS_WORKSPACE_CONFIG](https://docs.nvidia.com/cuda/cublas/index.html#results-reproducibility) を `:16:8` に設定し、cuBLAS が実行時に固定のワークスペースレイアウトを使用するようにします
- `torch.use_deterministic_algorithms(True)` を呼び出す
- `torch.backends.cudnn.deterministic = True` を設定する
- cuDNN が実行のたびに異なる畳み込みアルゴリズムを選択しないように、`torch.backends.cudnn.benchmark = False` を設定します
- より高精度なフルプレシションの行列積を優先するため、`torch.backends.cuda.matmul.allow_tf32 = False` を設定して TensorFloat32 (TF32) を無効にします

## 次のステップ

PyTorchの開発者ノートにある[再現性](https://docs.pytorch.org/docs/stable/notes/randomness.html)についてを読むことをお勧めします。ランダム性を制限することは可能ですが、同じシードを使用しても*保証*されるわけではありません。

