U
    JcS                     @   s   U d Z ddlmZmZmZ ddlZddlmZ ddlmZ	 ddlm
Z
 ddlmZ dd	lmZmZ g Zee ed
< G dd dZG dd de	ZG dd dejjZG dd dejjZG dd dejjZdS )uY  Portal keeps a tensor in the pocket plane. The tensor becomes hidden to the
autograd engine. The shared context of three functions (:class:`PortalBlue`,
:class:`PortalOrange`, and :class:`PortalCopy`) out of the computation graph is
one of the most important feature of :mod:`torchpipe.skip`.

The metaphor is inspired by Portal™ from Valve.

    )ListOptionalTupleN)Tensor   )Context)Copy)	get_phony)AbstractStream
get_device__all__c                   @   s   e Zd ZdZee eddddZedddZeee d	d
dZ	e
e
eedddZddddZee eddddZee dddZeddddZedddZdS )PortalzA portal for a tensor.N)tensortensor_lifereturnc                 C   s   |  || d | _d S N)
put_tensorgradselfr   r    r   O/tmp/pip-unpacked-wheel-gikjz4vx/torch/distributed/pipeline/sync/skip/portal.py__init__    s    zPortal.__init__)r   c                 C   s.   |   }|dkr"ttdddS t| |S )a:  Creates a :class:`PortalBlue` which hides the underlying tensor from
        the autograd engine.

        Join the returning phony to the main lane of the autograd graph to
        assure the correct backpropagation::

            PortalBlue --+
                         |
            ---------- Join --

        NcpuFZrequires_grad)
use_tensorr	   torchdevice
PortalBlueapplyr   r   r   r   r   blue$   s    zPortal.blue)phonyr   c                 C   s&   |    | jdkr|  S t| |S )a9  Creates a :class:`PortalOrange` which retrieves the hidden tensor
        without losing ability of backpropagation.

        Give a phony forked from the main lane of an autograd graph::

                +-- PortalOrange --+
                |                  |
            -- Fork --------- f(a, b) --

        N)check_tensor_lifer   r   PortalOranger   )r   r"   r   r   r   orange7   s    
zPortal.orange)prev_streamnext_streamr"   r   c                 C   s,   | j dkrttdddS t| |||S )zCopies the hidden tensor by a :class:`PortalCopy`.

        Give a phony and use the returning phony to keep backpropagation::

                +-- PortalCopy --+
                |                |
            -- Fork ---------- Join --

        Nr   Fr   )r   r	   r   r   
PortalCopyr   )r   r&   r'   r"   r   r   r   copyI   s    

zPortal.copyc                 C   s   | j dkrtdd S )Nr   z!tensor in portal has been removed)r   RuntimeError)r   r   r   r   r#   X   s    
zPortal.check_tensor_lifec                 C   s    || _ |dkr|| _nd| _dS )z!Stores a tensor into this portal.r   N)r   r   r   r   r   r   r   \   s    zPortal.put_tensorc                 C   s0   |    | j}|  jd8  _| jdkr,d| _|S )zRetrieves the underlying tensor and decreases the tensor  life. When
        the life becomes 0, it the tensor will be removed.
           r   N)r#   r   r   r    r   r   r   r   }   s    
zPortal.use_tensor)r   r   c                 C   s
   || _ dS )z#Stores a gradient into this portal.N)r   r   r   r   r   r   put_grad   s    zPortal.put_gradc                 C   s"   | j dkrtd| j }d| _ |S )zaRetrieves and removes the underlying gradient. The gradient is
        always ephemeral.
        Nz,grad in portal has been removed or never set)r   r*   r,   r   r   r   use_grad   s
    
zPortal.use_grad)__name__
__module____qualname____doc__r   r   intr   r!   r%   r
   r)   r#   r   r   r-   r.   r   r   r   r   r      s   !r   c                   @   s   e Zd ZU eed< dS )r   portalN)r/   r0   r1   r   __annotations__r   r   r   r   r      s   
r   c                   @   sF   e Zd ZdZeeeeedddZeeee	def dddZ
dS )	r   z=Hides a tensor from the autograd engine by a :class:`Portal`.)ctxr4   r   r   c                 C   s   || _ t|jdd}| S NFr   )r4   r	   r   detach)r6   r4   r   r"   r   r   r   forward   s    zPortalBlue.forwardNr6   
grad_phonyr   c                 C   s   | j  }d |fS r   )r4   r.   )r6   r;   r   r   r   r   backward   s    
zPortalBlue.backwardr/   r0   r1   r2   staticmethodr   r   r   r9   r   r<   r   r   r   r   r      s   r   c                   @   sB   e Zd ZdZeeeeedddZeeee	d dddZ
d	S )
r$   z3Retrieves the hidden tensor from a :class:`Portal`.)r6   r4   r"   r   c                 C   s"   || _ | }|d k	st| S r   )r4   r   AssertionErrorr8   )r6   r4   r"   r   r   r   r   r9      s    zPortalOrange.forwardNN)r6   r   r   c                 C   s   | j | dS )Nr@   )r4   r-   )r6   r   r   r   r   r<      s    zPortalOrange.backwardNr=   r   r   r   r   r$      s
   r$   c                   @   sF   e Zd ZdZeeeeeeedddZ	eeee
d dddZd	S )
r(   zfCopies the hidden tensor in a :class:`Portal`. It replaces the hidden
    tensor with copied one.
    )r6   r4   r&   r'   r"   r   c                 C   sB   || _ |jd k	stt| |||j\|_tt|dd}| S r7   )r4   r   r?   r   r9   r	   r   r8   )r6   r4   r&   r'   r"   r   r   r   r9      s
    zPortalCopy.forwardNNNNr:   c                 C   s.   | j }|jd k	stt| |j\}}|_dS )NrA   )r4   r   r?   r   r<   )r6   r;   r4   _r   r   r   r<      s    zPortalCopy.backwardN)r/   r0   r1   r2   r>   r   r   r
   r   r9   r   r<   r   r   r   r   r(      s       r(   )r2   typingr   r   r   r   r   r)   r   ZCopyContextr   r"   r	   streamr
   r   r   strr5   r   ZautogradZFunctionr   r$   r(   r   r   r   r   <module>   s    