class_docstr: Sampler that restricts data loading to a subset of the dataset.
  
  It is especially useful in conjunction with
  :class:`torch.nn.parallel.DistributedDataParallel`. In such case, each
  process can pass a DistributedSampler instance as a DataLoader sampler,
  and load a subset of the original dataset that is exclusive to it.
  
  .. note::
      Dataset is assumed to be of constant size.
  
  Arguments:
      dataset: Dataset used for sampling.
      num_replicas (optional): Number of processes participating in
          distributed training.
      rank (optional): Rank of the current process within num_replicas.
class_docstr_tok: ["Sampler","that","restricts","data","loading","to","a","subset","of","the","dataset",".","It","is","especially","useful","in","conjunction","with",":","class",":","`","torch.nn.parallel.DistributedDataParallel","`",".","In","such","case",",","each","process","can","pass","a","DistributedSampler","instance","as","a","DataLoader","sampler",",","and","load","a","subset","of","the","original","dataset","that","is","exclusive","to","it",".","..","note",":",":","Dataset","is","assumed","to","be","of","constant","size",".","Arguments",":","dataset",":","Dataset","used","for","sampling",".","num_replicas","(","optional",")",":","Number","of","processes","participating","in","distributed","training",".","rank","(","optional",")",":","Rank","of","the","current","process","within","num_replicas","."]
code: def __iter__(self):
      # deterministically shuffle based on epoch
      g = torch.Generator()
      g.manual_seed(self.epoch)
  
      indices = []
      for i, size in enumerate(self.group_sizes):
          if size > 0:
              indice = np.where(self.flag == i)[0]
              assert len(indice) == size
              # add .numpy() to avoid bug when selecting indice in parrots.
              # TODO: check whether torch.randperm() can be replaced by
              # numpy.random.permutation().
              indice = indice[
                  list(torch.randperm(int(size), generator=g).numpy())
              ].tolist()
              extra = int(
                  math.ceil(
                      size
                      * 1.0
                      / self.samples_per_gpu
                      / self.num_replicas
                  )
              ) * self.samples_per_gpu * self.num_replicas - len(indice)
              # pad indice
              tmp = indice.copy()
              for _ in range(extra // size):
                  indice.extend(tmp)
              indice.extend(tmp[: extra % size])
              indices.extend(indice)
  
      assert len(indices) == self.total_size
  
      indices = [
          indices[j]
          for i in list(
              torch.randperm(
                  len(indices) // self.samples_per_gpu, generator=g
              )
          )
          for j in range(
              i * self.samples_per_gpu, (i + 1) * self.samples_per_gpu
          )
      ]
  
      # subsample
      offset = self.num_samples * self.rank
      indices = indices[offset : offset + self.num_samples]
      assert len(indices) == self.num_samples
  
      return iter(indices)
  
file_path: insightface/detection/scrfd/mmdet/datasets/samplers/group_sampler.py
imports: from __future__ import division
  import math
  import numpy
  import torch
  from mmcv.runner import get_dist_info
  from torch.utils.data import Sampler
label_desc: Use image node_id 2 for calling the DistributedGroupSampler obj's underlying member method code with example usage: obj.__iter__() and returns: iter