U
    ©Ê¹jÄ:  ã                   @   st  d dl Z d dlmZ d dlmZ d dlmZmZ ejfdd„Z	d ejfdd„Z
d ejfdd	„Zejejfd
d„Zejejfdd„Zejfdd„Zejfdd„Zejfdd„Zddejfdd„Zejejfdd„ZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZG d d!„ d!eƒZG d"d#„ d#eƒZG d$d%„ d%eƒZG d&d'„ d'eƒZG d(d)„ d)eƒZG d*d+„ d+eƒZdS ),é    N)ÚFunction)ÚgroupÚReduceOpc                 C   s   t  ||| ¡S )a»  
    Broadcasts the tensor to the whole group.

    ``tensor`` must have the same number of elements in all processes
    participating in the collective.

    Arguments:
        tensor (Tensor): Data to be sent if ``src`` is the rank of current
            process.
        src (int): Source rank.
        group (ProcessGroup, optional): The process group to work on.

    Returns:
        Tensor: Received tensor from the broadcast op.

    )Ú
_BroadcastÚapply)ÚtensorÚsrcr   © r	   ú^/var/www/html/bwave/python/venv/lib/python3.8/site-packages/torch/distributed/nn/functional.pyÚ	broadcast	   s    r   c                 C   s   t  ||| ¡S )aT  
    Gathers a list of tensors in a single process.

    Arguments:
        tensor (Tensor): Input tensor.
        dst (int, optional): Destination rank (default is 0).
        group (ProcessGroup, optional): The process group to work on.

    Returns:
        tuple[Tensor]: List of appropriately-sized tensors with the gathered data.
    )Ú_Gatherr   )r   Údstr   r	   r	   r
   Úgather   s    r   c                 C   s   t j||f| žŽ S )aö  
    Scatters a list of tensors to all processes in a group.

    Each process will receive exactly one tensor and store its data in the
    ``tensor`` argument.

    Arguments:
        tensors (list[Tensor]): List of tensors to scatter on the source rank.
            Receivers must pass ``None`.
        src (int, optional): Source rank (default is 0).
        group (ProcessGroup, optional): The process group to work on.

    Returns:
        Tensor: Output tensor from the scatter operation.

    )Ú_Scatterr   )Útensorsr   r   r	   r	   r
   Úscatter,   s    r   c                 C   s   t  |||| ¡S )a  
    Reduces the tensor data across all machines.

    Only the process with rank ``dst`` is going to receive the final result.

    Arguments:
        tensor (Tensor): Input of the collective.
        dst (int): Destination rank.
        op (optional): One of the values from
            ``torch.distributed.ReduceOp``
            enum.  Specifies an operation used for element-wise reductions.
        group (ProcessGroup, optional): The process group to work on.

    Returns:
        Tensor: Output of the collective.

    )Ú_Reducer   )r   r   Úopr   r	   r	   r
   Úreduce@   s    r   c                 C   s   t j||| f|žŽ S )aõ  
    Reduces, then scatters a list of tensors to all processes in a group.

    Arguments:
        output (Tensor): Output tensor.
        input_list (list[Tensor]): List of tensors to reduce and scatter.
        op (optional): One of the values from
            ``torch.distributed.ReduceOp``
            enum.  Specifies an operation used for element-wise reductions.
        group (ProcessGroup, optional): The process group to work on.

    Returns:
        Tensor: Output of the collective.

    )Ú_Reduce_Scatterr   )ÚoutputZ
input_listr   r   r	   r	   r
   Úreduce_scatterU   s    r   c                 C   s   t  || ¡S )a  
    Gathers tensors from the whole group in a list.

    Arguments:
        tensor (Tensor): Tensor to be broadcast from current process.
        group (ProcessGroup, optional): The process group to work on.

    Returns:
        tuple([Tensor]): Output of the collective.

    )Ú
_AllGatherr   )r   r   r	   r	   r
   Ú
all_gatherh   s    r   c                 C   s   t  | ||¡S )aâ  
    Single tensor all gather. Gathers a single tensor from all ranks, and puts them in a single output tensor.

    Args:
        output_tensor (Tensor): Output tensor. It should contain
            correctly-sized tensors to be used for output of the collective.
        input_tensor (Tensor): Tensor to be broadcast from current process.
        group (ProcessGroup, optional): The process group to work on. If None,
            the default process group will be used.

    Examples:
        >>> # All tensors below are of torch.int64 dtype.
        >>> # We have 2 process groups, 2 ranks.
        >>> # xdoctest: +SKIP("incorrect want text")
        >>> output_tensor = torch.zeros(2, dtype=torch.int64)
        >>> output_tensor
        [tensor([0, 0])] # Rank 0 and 1
        >>> tensor = torch.arange(1, dtype=torch.int64) + 1 + rank
        >>> tensor
        tensor([1]) # Rank 0
        tensor([2]) # Rank 1
        >>> dist.all_gather_base(output_tensor, tensor)
        >>> output_tensor
        tensor([1,2]) # Rank 0
        tensor([1,2]) # Rank 1

    .. warning::
        `_all_gather_base` is experimental and subject to change.
        It is the caller's responsibility to ensure the output_tensor
        is correctly sized.

    )Ú_AllGatherBaser   )Úoutput_tensorÚinput_tensorr   r	   r	   r
   Ú_all_gather_basev   s    !r   c                 C   s   t j|| f|žŽ S )aÇ  
    Each process scatters list of input tensors to all processes in a group and
    return gathered list of tensors in output list.

    Arguments:
        output_tensor_list (list[Tensor]): list of tensors to gather one per rank.
        input_tensor_list (list[Tensor]): List of tensors to scatter one per rank.
        group (ProcessGroup, optional): The process group to work on.

    Returns:
        tuple([Tensor]): Output of the collective.

    )Ú	_AlltoAllr   )Zoutput_tensor_listÚinput_tensor_listr   r	   r	   r
   Ú
all_to_allš   s    r    c                 C   s   t  || |||¡S )a  
    Each process splits input tensor and then scatters the split list
    to all processes in a group. Then concatenate the received tensors from all
    the processes in the group and return single output tensor.

    Arguments:
        output (Tensor): Gathered concatenated output tensor.
        input (Tensor): Input tensor to scatter.
        output_split_sizes: (list[Int], optional): Output split sizes for dim 0
            if specified None or empty, dim 0 of ``output`` tensor must divide
            equally by ``world_size``.
        input_split_sizes: (list[Int], optional): Input split sizes for dim 0
            if specified None or empty, dim 0 of ``input`` tensor must divide
            equally by ``world_size``.

    Returns:
        Tensor: Output of the collective.

    )Ú_AlltoAllSingler   )r   ÚinputÚoutput_split_sizesÚinput_split_sizesr   r	   r	   r
   Úall_to_all_single«   s        ÿr%   c                 C   s   t  ||| ¡S )a*  
    Reduces the tensor data across all machines in such a way that all get
    the final result.

    After the call the returned tensor is going to be bitwise
    identical in all processes.

    Arguments:
        tensor (Tensor): Input of the collective.
        op (optional): One of the values from
            ``torch.distributed.ReduceOp``
            enum.  Specifies an operation used for element-wise reductions.
        group (ProcessGroup, optional): The process group to work on.

    Returns:
        Tensor: Output of the collective

    )Ú
_AllReducer   )r   r   r   r	   r	   r
   Ú
all_reduceÊ   s    r'   c                   @   s$   e Zd Zedd„ ƒZedd„ ƒZdS )r   c                 C   s2   || _ || _t ¡ | _| ¡ }tj|||d� |S ©N©r   )r   r   ÚdistÚget_rankÚrankÚcloner   )Úctxr   r   r   r	   r	   r
   Úforwardá   s    
z_Broadcast.forwardc                 C   s4   t  | jtj| j|¡}| j| jkr*| ¡  d d |fS ©N)r   r   r   r   ÚSUMr   r,   Zzero_)r.   Úgrad_outputÚgxr	   r	   r
   Úbackwardì   s    z_Broadcast.backwardN©Ú__name__Ú
__module__Ú__qualname__Ústaticmethodr/   r4   r	   r	   r	   r
   r   à   s   

r   c                   @   s$   e Zd Zedd„ ƒZedd„ ƒZdS )r   c                    sp   || _ || _‡ fdd„ttj|d�ƒD ƒ}ˆ  ¡ ‰ tj|d�|krVtjˆ |||d� ntjˆ d ||d� t|ƒS )Nc                    s   g | ]}t  ˆ ¡‘qS r	   )ÚtorchÚ
zeros_like©Ú.0Úi©r   r	   r
   Ú
<listcomp>ý   s    z#_Gather.forward.<locals>.<listcomp>r)   )	r   r   Úranger*   Úget_world_sizeÚ
contiguousr+   r   Útuple)r.   r   r   r   Útensor_listr	   r?   r
   r/   õ   s    
ÿz_Gather.forwardc                 G   s   dt j| j| jf|žŽ f S ©N©NN)r   r   r   r   )r.   Úgrad_outputsr	   r	   r
   r4     s    z_Gather.backwardNr5   r	   r	   r	   r
   r   ô   s   
r   c                   @   s$   e Zd Zedd„ ƒZedd„ ƒZdS )r   c                    sr   || _ || _t‡ fdd„ˆ D ƒƒs&t‚t ˆ d ¡}tj|d�|kr\tj|t	ˆ ƒ||d� ntj|d ||d� |S )Nc                 3   s"   | ]}|  ¡ ˆ d    ¡ kV  qdS )r   N©Úsize©r=   Út©r   r	   r
   Ú	<genexpr>  s     z#_Scatter.forward.<locals>.<genexpr>r   r)   )
r   r   ÚallÚAssertionErrorr:   r;   r*   r+   r   Úlist)r.   r   r   r   r   r	   rM   r
   r/     s    z_Scatter.forwardc                 C   s   dt  | j| j|¡ S rF   )r   r   r   r   ©r.   r2   r	   r	   r
   r4     s    z_Scatter.backwardNr5   r	   r	   r	   r
   r     s   
r   c                   @   s$   e Zd Zedd„ ƒZedd„ ƒZdS )r   c                 C   s*   || _ || _| ¡ }tj||||d� |S ©N©r   r   )r   r   r-   r*   r   )r.   r   r   r   r   r	   r	   r
   r/      s
    z_Reduce.forwardc                 C   s   dt  | j| j|¡f S ©N)NNN)r   r   r   r   rR   r	   r	   r
   r4   (  s    z_Reduce.backwardNr5   r	   r	   r	   r
   r     s   
r   c                   @   s$   e Zd Zedd„ ƒZedd„ ƒZdS )r   c                 G   s:   || _ | ¡ }tdd„ |D ƒƒ}tj|t|ƒ||d� |S )Nc                 s   s   | ]}|  ¡ V  qd S r0   ©rC   rK   r	   r	   r
   rN   3  s     z*_Reduce_Scatter.forward.<locals>.<genexpr>rT   )r   rC   rD   r*   r   rQ   )r.   r   r   r   r   r	   r	   r
   r/   .  s
    z_Reduce_Scatter.forwardc                 C   s   dt  | j|¡ S rU   )r   r   r   rR   r	   r	   r
   r4   7  s    z_Reduce_Scatter.backwardNr5   r	   r	   r	   r
   r   -  s   
r   c                   @   s$   e Zd Zedd„ ƒZedd„ ƒZdS )r   c                    sD   ˆ   ¡ ‰ || _‡ fdd„ttj|d�ƒD ƒ}tj|ˆ |d� t|ƒS )Nc                    s   g | ]}t  ˆ ¡‘qS r	   ©r:   Ú
empty_like)r=   Ú_r?   r	   r
   r@   C  s    z&_AllGather.forward.<locals>.<listcomp>r)   )rC   r   rA   r*   rB   r   rD   )r.   r   r   Úout_tensor_listr	   r?   r
   r/   =  s    
ÿz_AllGather.forwardc                 G   s„   t j| jd�t jjkrFt  ¡ }t || ¡}tj	t
j| j|f|žŽ  n6dd„ |D ƒ}tj	| j|f|žŽ }tjt |¡dd�}d |fS )Nr)   c                 S   s   g | ]}t  |¡‘qS r	   rW   )r=   r   r	   r	   r
   r@   S  s     z'_AllGather.backward.<locals>.<listcomp>r   )Údim)r*   Úget_backendr   ÚBackendÚNCCLr+   r:   rX   r   r   r   r1   r   ÚsumÚstack)r.   rH   r,   r3   rE   Zgxsr	   r	   r
   r4   J  s    z_AllGather.backwardNr5   r	   r	   r	   r
   r   <  s   
r   c                   @   s$   e Zd Zedd„ ƒZedd„ ƒZdS )r   c                 C   s   || _ tj|| ¡ |d� |S r(   )r   r*   r   rC   )r.   r   r   r   r	   r	   r
   r/   Y  s    z_AllGatherBase.forwardc                 C   sª   t j| jd�t jjkr˜t j| jd�}t| ¡ ƒ}|d | dkrTtd|› d|› �ƒ‚|d t j| jd� |d< t	j
||j|jd�}t  ||tj| j¡ ntdƒ‚d |d fS )Nr)   r   zTensor with dimensions: z8 does not have first dimension divisible by world_size: ©ÚdeviceÚdtypezBackend not supported!)r*   r\   r   r]   r^   rB   rQ   rJ   ÚRuntimeErrorr:   Úemptyrb   rc   Z_reduce_scatter_baser   r1   )r.   r2   Z
world_sizeZout_sizer3   r	   r	   r
   r4   _  s    ÿz_AllGatherBase.backwardNr5   r	   r	   r	   r
   r   X  s   
r   c                   @   s$   e Zd Zedd„ ƒZedd„ ƒZdS )r   c                    s¶   || _ ‡ fdd„ttj|d�ƒD ƒ| _tj|d�}tdd„ ˆ D ƒƒ‰ tj|d�tjj	kršttj|d�ƒD ].}d }||kr€t
ˆ ƒ}tj|| |||d� qhntj|t
ˆ ƒ|d� t|ƒS )Nc                    s   g | ]}ˆ |   ¡ ‘qS r	   rI   r<   rM   r	   r
   r@   t  s    z%_AlltoAll.forward.<locals>.<listcomp>r)   c                 s   s   | ]}|  ¡ V  qd S r0   rV   rK   r	   r	   r
   rN   x  s     z$_AlltoAll.forward.<locals>.<genexpr>)r   rA   r*   rB   Úinput_tensor_size_listr+   rD   r\   r]   ZGLOOrQ   r   r    )r.   r   rZ   r   Zmy_rankr>   Úto_sendr	   rM   r
   r/   q  s$    
ÿýz_AlltoAll.forwardc                    s,   ‡ fdd„| j D ƒ}dtj| j|fˆ žŽ  S )Nc                    s(   g | ] }t j|ˆ d  jˆ d  jd�‘qS )r   ra   )r:   re   rb   rc   )r=   rJ   ©rH   r	   r
   r@   Š  s   ÿz&_AlltoAll.backward.<locals>.<listcomp>rG   )rf   r   r   r   )r.   rH   rE   r	   rh   r
   r4   ˆ  s    
þz_AlltoAll.backwardNr5   r	   r	   r	   r
   r   p  s   
r   c                   @   s$   e Zd Zedd„ ƒZedd„ ƒZdS )r!   c                 C   s4   || _ | ¡ | _|| _|| _tj|||||d� |S )N)r#   r$   r   )r   rJ   Ú
input_sizer#   r$   r*   r%   )r.   r   r   r#   r$   r"   r	   r	   r
   r/   ’  s    
ûz_AlltoAllSingle.forwardc              	   C   s8   t j| j|j|jd�}dt | j|| j| j	| 
¡ ¡f S )Nra   )NNNN)r:   re   ri   rb   rc   r!   r   r   r#   r$   rC   )r.   r2   r   r	   r	   r
   r4   ¡  s    ûÿz_AlltoAllSingle.backwardNr5   r	   r	   r	   r
   r!   ‘  s   
r!   c                   @   s$   e Zd Zedd„ ƒZedd„ ƒZdS )r&   c                 C   s(   || _ || _| ¡ }tj|||d� |S rS   )r   r   r-   r*   r'   )r.   r   r   r   r	   r	   r
   r/   °  s
    z_AllReduce.forwardc                 C   s   dt  | j| j|¡f S rF   )r&   r   r   r   rR   r	   r	   r
   r4   ¸  s    z_AllReduce.backwardNr5   r	   r	   r	   r
   r&   ¯  s   
r&   )r:   Ztorch.distributedÚdistributedr*   Ztorch.autogradr   r   r   ZWORLDr   r   r   r1   r   r   r   r   r    r%   r'   r   r   r   r   r   r   r   r   r!   r&   r	   r	   r	   r
   Ú<module>   s4   $û
!