U
    •Ê¹j™)  ã                   @   sš   d dl Z d dlZd dlmZ d dlmZmZmZmZm	Z	m
Z
 d dlmZ dddœdd„Zdd	d
„Zddd„Zddd„Zdddœdd„Zdddœdd„ZdS )é    N)Únccl)Ú_take_tensorsÚ_flatten_dense_tensorsÚ_unflatten_dense_tensorsÚ_reorder_tensors_asÚ_get_device_indexÚ_handle_complex)ÚList)Úoutc                C   sb   t | ƒ} |dk|dkA s,td|› d|› �ƒ‚|dk	rPdd„ |D ƒ}tj | |¡S tj | |¡S dS )aï  Broadcasts a tensor to specified GPU devices.

    Args:
        tensor (Tensor): tensor to broadcast. Can be on CPU or GPU.
        devices (Iterable[torch.device, str or int], optional): an iterable of
          GPU devices, among which to broadcast.
        out (Sequence[Tensor], optional, keyword-only): the GPU tensors to
          store output results.

    .. note::
        Exactly one of :attr:`devices` and :attr:`out` must be specified.

    Returns:
        - If :attr:`devices` is specified,
            a tuple containing copies of :attr:`tensor`, placed on
            :attr:`devices`.
        - If :attr:`out` is specified,
            a tuple containing :attr:`out` tensors, each containing a copy of
            :attr:`tensor`.
    NzFExactly one of 'devices' and 'out' must be specified, but got devices=z	 and out=c                 S   s   g | ]}t |ƒ‘qS © ©r   ©Ú.0Údr   r   úU/var/www/html/bwave/python/venv/lib/python3.8/site-packages/torch/nn/parallel/comm.pyÚ
<listcomp>"   s     zbroadcast.<locals>.<listcomp>)r   ÚRuntimeErrorÚtorchÚ_CZ
_broadcastZ_broadcast_out)ÚtensorÚdevicesr
   r   r   r   Ú	broadcast   s    ÿr   é    c                 C   s,   dd„ |D ƒ}dd„ | D ƒ} t j | ||¡S )a/  Broadcasts a sequence tensors to the specified GPUs.
    Small tensors are first coalesced into a buffer to reduce the number
    of synchronizations.

    Args:
        tensors (sequence): tensors to broadcast. Must be on the same device,
          either CPU or GPU.
        devices (Iterable[torch.device, str or int]): an iterable of GPU
          devices, among which to broadcast.
        buffer_size (int): maximum size of the buffer used for coalescing

    Returns:
        A tuple containing copies of :attr:`tensor`, placed on :attr:`devices`.
    c                 S   s   g | ]}t |ƒ‘qS r   r   r   r   r   r   r   7   s     z'broadcast_coalesced.<locals>.<listcomp>c                 S   s   g | ]}t |ƒ‘qS r   ©r   ©r   Útr   r   r   r   8   s     )r   r   Z_broadcast_coalesced)Útensorsr   Úbuffer_sizer   r   r   Úbroadcast_coalesced(   s    r   c                    sb  t |dd�}| d  ¡ }d‰ t| ƒD ]~\}}|jjdks@tdƒ‚| ¡ |krP|‰ | ¡ |kr$d dd	„ | ¡ D ƒ¡}d d
d	„ |D ƒ¡}td|› d|› d|› �ƒ‚q$ˆ dkr´t	dƒ‚t
| ƒdkrÈ| d S t | ¡ròt | ˆ  ¡}tj| |ˆ d� nlt | ˆ  jj|¡}‡ fdd„t| ƒD ƒ}	| ˆ  |	d j|dd� }|	dd… D ]}
| |
j|dd�¡ �qB|S )aì  Sums tensors from multiple GPUs.

    All inputs should have matching shapes, dtype, and layout. The output tensor
    will be of the same shape, dtype, and layout.

    Args:
        inputs (Iterable[Tensor]): an iterable of tensors to add.
        destination (int, optional): a device on which the output will be
            placed (default: current device).

    Returns:
        A tensor containing an elementwise sum of all inputs, placed on the
        :attr:`destination` device.
    T)Úoptionalr   NÚcpuz+reduce_add expects all inputs to be on GPUsÚxc                 s   s   | ]}t |ƒV  qd S ©N©Ústr©r   r!   r   r   r   Ú	<genexpr>S   s     zreduce_add.<locals>.<genexpr>c                 s   s   | ]}t |ƒV  qd S r"   r#   r%   r   r   r   r&   T   s     zinput z has invalid size: got z, but expected zLreduce_add expects destination to be on the same GPU with one of the tensorsé   )ÚoutputÚrootc                    s   g | ]\}}|ˆ kr|‘qS r   r   )r   Úir   ©Z
root_indexr   r   r   a   s      zreduce_add.<locals>.<listcomp>)ÚdeviceZnon_blocking)r   ÚsizeÚ	enumerater,   ÚtypeÚAssertionErrorZ
get_deviceÚjoinÚ
ValueErrorr   Úlenr   Zis_availabler   Z
empty_likeÚreduceÚtoZadd_)ÚinputsÚdestinationZ
input_sizer*   ZinpÚgotÚexpectedÚresultZdestination_deviceZnonrootÚotherr   r+   r   Ú
reduce_add<   s0    
r<   c                    sþ   dd„ | D ƒ}g }g }t | Ž D ]x}tdd„ |D ƒƒrXt||ƒ}| |¡ | |d ¡ qt ||ƒD ] \}}	| |	jr||	 ¡ n|	¡ qb| |d d ¡ q‡ fdd„|D ƒ}
t |
Ž D ]<}dd„ |D ƒ}t||ƒ}t||d ƒD ]}	| |	j¡ qÜq²tt	||ƒƒS )	a]  Sums tensors from multiple GPUs.

    Small tensors are first coalesced into a buffer to reduce the number
    of synchronizations.

    Args:
        inputs (Iterable[Iterable[Tensor]]): iterable of iterables that
            contain tensors from a single device.
        destination (int, optional): a device on which the output will be
            placed (default: current device).
        buffer_size (int): maximum size of the buffer used for coalescing

    Returns:
        A tuple of tensors containing an elementwise sum of each group of
        inputs, placed on the ``destination`` device.
    c                 S   s   g | ]}g ‘qS r   r   )r   Ú_r   r   r   r   |   s     z(reduce_add_coalesced.<locals>.<listcomp>c                 s   s   | ]}|j V  qd S r"   )Ú	is_sparser   r   r   r   r&   �   s     z'reduce_add_coalesced.<locals>.<genexpr>r   éÿÿÿÿc                    s   g | ]}t |ˆ ƒ‘qS r   )r   )r   r   ©r   r   r   r   ‰   s     c                 S   s   g | ]}t |ƒ‘qS r   )r   )r   Úchunkr   r   r   r   Œ   s     )
ÚzipÚallr<   Úappendr>   Zto_denser   ÚdataÚtupler   )r6   r7   r   Zdense_tensorsr(   Z	ref_orderZtensor_at_gpusr:   Zcollr   ZitrsÚchunksZflat_tensorsZflat_resultr   r@   r   Úreduce_add_coalescedi   s$    


rH   c                C   s|   t | ƒ} |dkr6dd„ |D ƒ}ttj | ||||¡ƒS |dk	rLtd|› �ƒ‚|dk	rbtd|› �ƒ‚ttj | |||¡ƒS dS )a<  Scatters tensor across multiple GPUs.

    Args:
        tensor (Tensor): tensor to scatter. Can be on CPU or GPU.
        devices (Iterable[torch.device, str or int], optional): an iterable of
          GPU devices, among which to scatter.
        chunk_sizes (Iterable[int], optional): sizes of chunks to be placed on
          each device. It should match :attr:`devices` in length and sums to
          ``tensor.size(dim)``. If not specified, :attr:`tensor` will be divided
          into equal chunks.
        dim (int, optional): A dimension along which to chunk :attr:`tensor`.
          Default: ``0``.
        streams (Iterable[torch.cuda.Stream], optional): an iterable of Streams, among
          which to execute the scatter. If not specified, the default stream will
          be utilized.
        out (Sequence[Tensor], optional, keyword-only): the GPU tensors to
          store output results. Sizes of these tensors must match that of
          :attr:`tensor`, except for :attr:`dim`, where the total size must
          sum to ``tensor.size(dim)``.

    .. note::
        Exactly one of :attr:`devices` and :attr:`out` must be specified. When
        :attr:`out` is specified, :attr:`chunk_sizes` must not be specified and
        will be inferred from sizes of :attr:`out`.

    Returns:
        - If :attr:`devices` is specified,
            a tuple containing chunks of :attr:`tensor`, placed on
            :attr:`devices`.
        - If :attr:`out` is specified,
            a tuple containing :attr:`out` tensors, each containing a chunk of
            :attr:`tensor`.
    Nc                 S   s   g | ]}t |ƒ‘qS r   r   r   r   r   r   r   º   s     zscatter.<locals>.<listcomp>zI'devices' must not be specified when 'out' is specified, but got devices=zQ'chunk_sizes' must not be specified when 'out' is specified, but got chunk_sizes=)r   rF   r   r   Z_scatterr   Z_scatter_out)r   r   Zchunk_sizesÚdimÚstreamsr
   r   r   r   Úscatter–   s    "ÿÿrK   c                C   sp   dd„ | D ƒ} |dkrF|dkr(t  d¡ t|ddd�}tj | ||¡S |dk	r\td|› �ƒ‚tj | ||¡S dS )	a²  Gathers tensors from multiple GPU devices.

    Args:
        tensors (Iterable[Tensor]): an iterable of tensors to gather.
          Tensor sizes in all dimensions other than :attr:`dim` have to match.
        dim (int, optional): a dimension along which the tensors will be
          concatenated. Default: ``0``.
        destination (torch.device, str, or int, optional): the output device.
          Can be CPU or CUDA. Default: the current CUDA device.
        out (Tensor, optional, keyword-only): the tensor to store gather result.
          Its sizes must match those of :attr:`tensors`, except for :attr:`dim`,
          where the size must equal ``sum(tensor.size(dim) for tensor in tensors)``.
          Can be on CPU or CUDA.

    .. note::
        :attr:`destination` must not be specified when :attr:`out` is specified.

    Returns:
        - If :attr:`destination` is specified,
            a tensor located on :attr:`destination` device, that is a result of
            concatenating :attr:`tensors` along :attr:`dim`.
        - If :attr:`out` is specified,
            the :attr:`out` tensor, now containing results of concatenating
            :attr:`tensors` along :attr:`dim`.
    c                 S   s   g | ]}t |ƒ‘qS r   r   r   r   r   r   r   à   s     zgather.<locals>.<listcomp>Nr?   zjUsing -1 to represent CPU tensor is deprecated. Please use a device object or string instead, e.g., "cpu".T)Z	allow_cpur   zQ'destination' must not be specified when 'out' is specified, but got destination=)ÚwarningsÚwarnr   r   r   Z_gatherr   Z_gather_out)r   rI   r7   r
   r   r   r   ÚgatherÆ   s    ÿÿrN   )N)r   )N)Nr   )NNr   N)r   N)rL   r   Z
torch.cudar   Ztorch._utilsr   r   r   r   r   r   Útypingr	   r   r   r<   rH   rK   rN   r   r   r   r   Ú<module>   s     

-
-0