U
    Jc                  	   @   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
mZ d dlZd dlmZ d dlmZ d dlmZ dg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deeeddddZ dS )    N)OrderedDict)AnyCallableDictListSetTupleUnion)
_BatchNorm)_is_namedtuple)PackedSequencep_assertc                 C   s   t dd |  D S )Nc                 s   s   | ]}t |tV  qd S N)
isinstancer
   ).0mod r   @/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   r8   r   _apply_to_tensors   s    *r:   )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r6   r<   r   r   r6   N   s
    z_apply_to_modules.<locals>.f )r%   nnModulestr)r;   r<   r=   r@   rA   r   rD   r   _apply_to_modules@   s    rI   )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 )storagerK   Znumelr   resize_)rJ   rK   Zalready_allocatedZtensor_storage_sizer   r   r   _alloc_storageZ   s    	rN   )rJ   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)rL   rK   r   Zstorage_offsetrM   )rJ   Zalready_freedr   r   r   _free_storagen   s    	
rO   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)rP   rQ   rR   r   r   r   r      s
    )T)!r'   rT   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   __all__r   r   r9   r:   rF   rG   rI   Zno_gradSizeboolrN   rO   r   r   r   r   r   <module>   s.   $ $