There is a bug in PyTorch/Numpy where when loading batches in parallel with a DataLoader
(i.e. setting num_workers > 1
), the same NumPy random seed is used for each worker, resulting in any random functions applied being identical across parallelized batches. This can be resolved by passing a seed generator to the worker_init_fn
argument like so.
However the issue persists across multiple epochs.
Minimal example:
import numpy as np
from torch.utils.data import Dataset, DataLoader
class RandomDataset(Dataset):
def __getitem__(self, index):
return np.random.randint(0, 1000, 2)
def __len__(self):
return 4
dataset = RandomDataset()
dataloader = DataLoader(dataset, batch_size=1,
num_workers=2,
worker_init_fn = lambda x: np.random.seed(x))
for epoch in range(3):
print(f'\nEpoch {epoch}')
for batch in dataloader:
print(batch)
As you can see, while parallelized batches within an epoch now produce different results, the results are identical across epochs:
Epoch 0
tensor([[684, 559]])
tensor([[ 37, 235]])
tensor([[629, 192]])
tensor([[908, 72]])
Epoch 1
tensor([[684, 559]])
tensor([[ 37, 235]])
tensor([[629, 192]])
tensor([[908, 72]])
Epoch 2
tensor([[684, 559]])
tensor([[ 37, 235]])
tensor([[629, 192]])
tensor([[908, 72]])
How can this be behaviour be fixed?
Using an empty argument e.g. worker_init_fn = lambda _: np.random.seed()
appears to fix this - are there any issues with this workaround?