U
    Jc                  	   @   s2  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
mZ d dlZd dlmZ d dlmZ d dlmZ dZdd	 Zd
d Zeeejeee
e	eef edddZejjeedddZe ejejedddZe ejedddZejddddZ ejedddZ!d eeeddddZ"dS )!    N)OrderedDict)AnyCallableDictListSetTupleUnion)
_BatchNorm)_is_namedtuple)PackedSequenceZ_fsdp_flattenedc                 C   s   t dd |  D S )Nc                 s   s   | ]}t |tV  qd S N)
isinstancer
   ).0mod r   A/tmp/pip-unpacked-wheel-gikjz4vx/torch/distributed/fsdp/_utils.py	<genexpr>   s    z&_contains_batchnorm.<locals>.<genexpr>)anymodules)moduler   r   r   _contains_batchnorm   s    r   c                 C   s&   |   D ]}t|trdd i|_qd S )NZmixed_precision)r   r   r
   Z_wrap_overrides)r   r   r   r   r   #_override_batchnorm_mixed_precision   s    
r   )fn	containerreturnc                    s2   t tjttttttf t	d fdd  |S )zFRecursively apply to all tensor in different kinds of container types.)xr   c                    s  t | r| S t| drVt| }t|D ] }|j}t|| t|| q0|S t	| t
r|  }|  D ]\}} |||< qp|S t	| tr | j | S t	| tr fdd|  D S t| r fdd| D }t| | S t	| tttfrt|  fdd| D S | S d S )NZ__dataclass_fields__c                    s   i | ]\}}| |qS r   r   )r   keyvalueapplyr   r   
<dictcomp>4   s      z4_apply_to_tensors.<locals>.apply.<locals>.<dictcomp>c                 3   s   | ]} |V  qd S r   r   r   elr   r   r   r   6   s     z3_apply_to_tensors.<locals>.apply.<locals>.<genexpr>c                 3   s   | ]} |V  qd S r   r   r"   r   r   r   r   9   s     )torchZ	is_tensorhasattrdataclassesreplacefieldsnamesetattrgetattrr   r   	__class__itemsr   datadictr   typelisttupleset)r   dcfr)   Zodr   r   resr    r   r   r   r    "   s0    






z _apply_to_tensors.<locals>.apply)
r	   r$   Tensorr   r   r   r   r   r   r   )r   r   r   r7   r   _apply_to_tensors   s    *r9   )root_module	module_fn	return_fnc                    s6   t jjtd fdd  | df|| |||S )ae  
    Performs a pre-order traversal of the modules in the hierarchy rooted at
    ``root_module``, applying ``module_fn`` at each module and finally
    returning a value using ``return_fn``. The traversal constructs the full
    module prefix name (e.g. "module.submodule." just like in model state dict)
    and makes that available to ``module_fn``.
    )r   prefixc                    sN   | |f|| |   D ].\}}|d k	r|| d } ||f|| qd S )N.)Znamed_children)r   r=   argskwargsZsubmodule_name	submodule
new_prefixr5   r;   r   r   r5   N   s
    z_apply_to_modules.<locals>.f )r$   nnModulestr)r:   r;   r<   r?   r@   r   rC   r   _apply_to_modules@   s    rH   )tensorsizer   c                 C   sP   |    | k}|sJ|    }t|dkd|  |   |  | S )z
    Allocate storage for ``tensor`` with the given size.

    Returns:
        bool: ``True`` if this method allocated storage and ``False`` if the
        storage was already allocated.
    r   z8Tensor storage should have been resized to be 0 but got )storagerJ   Znumelp_assertresize_)rI   rJ   Zalready_allocatedZtensor_storage_sizer   r   r   _alloc_storageZ   s    	rN   )rI   r   c                 C   s:   |    dk}|s4t|  dkd |   d | S )z
    Frees the underlying storage of ``tensor``.

    Returns:
        bool: ``True`` if the method freed the storage and ``False`` if the
        storage was already freed.
    r   zEFreeing a tensor's storage is unsafe when it is not the sole occupant)rK   rJ   rL   Zstorage_offsetrM   )rI   Zalready_freedr   r   r   _free_storagen   s    	
rO   c                 C   s   t | td dS )z
    Sets an attribute on ``tensor`` to mark it as flattened by FSDP. This is to
    avoid re-flattening it during nested construction.
    TN)r*   FSDP_FLATTENEDrI   r   r   r   _set_fsdp_flattened   s    rR   c                 C   s   t | tdS )z;Returns if ``tensor`` has been marked as flattened by FSDP.F)r+   rP   rQ   r   r   r   _is_fsdp_flattened   s    rS   T)condsraise_assertion_errorr   c                 C   s    | st | t  |rtdS )zThis is used as an alternate to ``assert`` when in the backward context
    to print the error message ``s`` since otherwise, it is swallowed.N)print	tracebackprint_stackAssertionError)rT   rU   rV   r   r   r   rL      s
    rL   )T)#r&   rX   collectionsr   typingr   r   r   r   r   r   r	   r$   Ztorch.nn.modules.batchnormr
   Z torch.nn.parallel.scatter_gatherr   Ztorch.nn.utils.rnnr   rP   r   r   r8   r9   rE   rF   rH   Zno_gradSizeboolrN   rO   rR   rS   rL   r   r   r   r   <module>   s2   $ $