U
    •Ê¹j6  ã                   @   sj   d dl Z d dlmZmZmZ d dlZddlmZmZ d dl	m
Z dgZeddd�ZG d	d„ dee ƒZdS )
é    N)ÚTypeVarÚOptionalÚIteratoré   )ÚSamplerÚDatasetÚDistributedSamplerÚT_coT)Ú	covariantc                	   @   sd   e Zd ZdZdeee ee eeeddœdd„Ze	e
 d	œd
d„Zed	œdd„Zeddœdd„ZdS )r   a'	  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 a case, each
    process can pass a :class:`~torch.utils.data.DistributedSampler` instance as a
    :class:`~torch.utils.data.DataLoader` sampler, and load a subset of the
    original dataset that is exclusive to it.

    .. note::
        Dataset is assumed to be of constant size and that any instance of it always
        returns the same elements in the same order.

    Args:
        dataset: Dataset used for sampling.
        num_replicas (int, optional): Number of processes participating in
            distributed training. By default, :attr:`world_size` is retrieved from the
            current distributed group.
        rank (int, optional): Rank of the current process within :attr:`num_replicas`.
            By default, :attr:`rank` is retrieved from the current distributed
            group.
        shuffle (bool, optional): If ``True`` (default), sampler will shuffle the
            indices.
        seed (int, optional): random seed used to shuffle the sampler if
            :attr:`shuffle=True`. This number should be identical across all
            processes in the distributed group. Default: ``0``.
        drop_last (bool, optional): if ``True``, then the sampler will drop the
            tail of the data to make it evenly divisible across the number of
            replicas. If ``False``, the sampler will add extra indices to make
            the data evenly divisible across the replicas. Default: ``False``.

    .. warning::
        In distributed mode, calling the :meth:`set_epoch` method at
        the beginning of each epoch **before** creating the :class:`DataLoader` iterator
        is necessary to make shuffling work properly across multiple epochs. Otherwise,
        the same ordering will be always used.

    Example::

        >>> # xdoctest: +SKIP
        >>> sampler = DistributedSampler(dataset) if is_distributed else None
        >>> loader = DataLoader(dataset, shuffle=(sampler is None),
        ...                     sampler=sampler)
        >>> for epoch in range(start_epoch, n_epochs):
        ...     if is_distributed:
        ...         sampler.set_epoch(epoch)
        ...     train(loader)
    NTr   F)ÚdatasetÚnum_replicasÚrankÚshuffleÚseedÚ	drop_lastÚreturnc                 C   sø   |d kr t  ¡ stdƒ‚t  ¡ }|d kr@t  ¡ s8tdƒ‚t  ¡ }||ksP|dk rjtd|› d|d › d�ƒ‚|| _|| _|| _d| _	|| _
| j
rÂt| jƒ| j dkrÂt t| jƒ| j | j ¡| _nt t| jƒ| j ¡| _| j| j | _|| _|| _d S )Nz,Requires distributed package to be availabler   zInvalid rank z%, rank should be in the interval [0, r   ú])ÚdistZis_availableÚRuntimeErrorZget_world_sizeZget_rankÚ
ValueErrorr   r   r   Úepochr   ÚlenÚmathÚceilÚnum_samplesÚ
total_sizer   r   )Úselfr   r   r   r   r   r   © r   ú[/var/www/html/bwave/python/venv/lib/python3.8/site-packages/torch/utils/data/distributed.pyÚ__init__>   s2    ÿÿzDistributedSampler.__init__)r   c                 C   sð   | j r:t ¡ }| | j| j ¡ tjt| jƒ|d� 	¡ }nt
tt| jƒƒƒ}| js¢| jt|ƒ }|t|ƒkr~||d |… 7 }q°||t |t|ƒ ¡ d |… 7 }n|d | j… }t|ƒ| jksÂt‚|| j| j| j… }t|ƒ| jksèt‚t|ƒS )N)Ú	generator)r   ÚtorchÚ	GeneratorZmanual_seedr   r   Zrandpermr   r   ÚtolistÚlistÚranger   r   r   r   ÚAssertionErrorr   r   r   Úiter)r   ÚgÚindicesZpadding_sizer   r   r   Ú__iter__`   s    $zDistributedSampler.__iter__c                 C   s   | j S )N)r   )r   r   r   r   Ú__len__{   s    zDistributedSampler.__len__)r   r   c                 C   s
   || _ dS )a)  
        Sets the epoch for this sampler. When :attr:`shuffle=True`, this ensures all replicas
        use a different random ordering for each epoch. Otherwise, the next iteration of this
        sampler will yield the same ordering.

        Args:
            epoch (int): Epoch number.
        N)r   )r   r   r   r   r   Ú	set_epoch~   s    	zDistributedSampler.set_epoch)NNTr   F)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   ÚintÚboolr   r   r	   r*   r+   r,   r   r   r   r   r      s    0       þ
   þ")r   Útypingr   r   r   r!   Ú r   r   Ztorch.distributedÚdistributedr   Ú__all__r	   r   r   r   r   r   Ú<module>   s   