In training, we only care about the "infinite stream" of training data. So this sampler produces an infinite stream of indices and all workers cooperate to correctly shuffle the indices and sample different indices. The samplers in each worker effectively produces `indices[worker_id
| 38 | |
| 39 | |
| 40 | class InfiniteSampler(Sampler): |
| 41 | """ |
| 42 | In training, we only care about the "infinite stream" of training data. |
| 43 | So this sampler produces an infinite stream of indices and |
| 44 | all workers cooperate to correctly shuffle the indices and sample different indices. |
| 45 | The samplers in each worker effectively produces `indices[worker_id::num_workers]` |
| 46 | where `indices` is an infinite stream of indices consisting of |
| 47 | `shuffle(range(size)) + shuffle(range(size)) + ...` (if shuffle is True) |
| 48 | or `range(size) + range(size) + ...` (if shuffle is False) |
| 49 | """ |
| 50 | |
| 51 | def __init__( |
| 52 | self, |
| 53 | size: int, |
| 54 | shuffle: bool = True, |
| 55 | seed: Optional[int] = 0, |
| 56 | rank=0, |
| 57 | world_size=1, |
| 58 | ): |
| 59 | """ |
| 60 | Args: |
| 61 | size (int): the total number of data of the underlying dataset to sample from |
| 62 | shuffle (bool): whether to shuffle the indices or not |
| 63 | seed (int): the initial seed of the shuffle. Must be the same |
| 64 | across all workers. If None, will use a random seed shared |
| 65 | among workers (require synchronization among all workers). |
| 66 | """ |
| 67 | self._size = size |
| 68 | assert size > 0 |
| 69 | self._shuffle = shuffle |
| 70 | self._seed = int(seed) |
| 71 | |
| 72 | if dist.is_available() and dist.is_initialized(): |
| 73 | self._rank = dist.get_rank() |
| 74 | self._world_size = dist.get_world_size() |
| 75 | else: |
| 76 | self._rank = rank |
| 77 | self._world_size = world_size |
| 78 | |
| 79 | def __iter__(self): |
| 80 | start = self._rank |
| 81 | yield from itertools.islice( |
| 82 | self._infinite_indices(), start, None, self._world_size |
| 83 | ) |
| 84 | |
| 85 | def _infinite_indices(self): |
| 86 | g = torch.Generator() |
| 87 | g.manual_seed(self._seed) |
| 88 | while True: |
| 89 | if self._shuffle: |
| 90 | yield from torch.randperm(self._size, generator=g) |
| 91 | else: |
| 92 | yield from torch.arange(self._size) |
| 93 | |
| 94 | def __len__(self): |
| 95 | return self._size // self._world_size |
no outgoing calls
no test coverage detected