o
    oiD                  	   @   s*  U d dl Z d dlmZ d dlmZmZ d dlmZ d dlm	Z	m
Z
mZmZmZ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 d	lm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% 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/ d dl0m1Z1 edee2e	f dZ3dZ4dZ5e6e7d< G dd dZ8G dd de/Z9G dd dZ:d e	d!e	fd"d#Z;d$ee	ef d!eee	ej<f eee2e	f  f fd%d&Z=d'ej<d(ee2e	f d!efd)d*Z>d+e6d,e	d!dfd-d.Z?d$e@d!e6fd/d0ZAd1e
d!e
fd2d3ZBeBejCe_CdS )4    N)deepcopy)partialwraps)
MethodType)AnyCallableDict	GeneratorIteratorListMappingOptionalTupleTypeVarUnionoverload)is_overridden)apply_to_collection)Tensor)nn)OptimizedModule)_IncompatibleKeys)	Optimizer)
DataLoader)override)	Precision)Strategy)move_data_to_device)_set_sampler_epoch)_DeviceDtypeModuleMixin)OptimizableT_destination)bound)training_stepvalidation_step	test_steppredict_stepF_in_fabric_backwardc                	   @   s   e Zd Zddededeee  ddfddZe	defdd	Z
deeef fd
dZdeeef ddfddZddee defddZdedefddZdS )_FabricOptimizerN	optimizerstrategy	callbacksreturnc                 C   s8   || _ || _|p	g | _td|jj | j|jfi | _dS )a  FabricOptimizer is a thin wrapper around the :class:`~torch.optim.Optimizer` that delegates the optimizer
        step calls to the strategy.

        The underlying wrapped optimizer object can be accessed via the property :attr:`optimizer`.

        Args:
            optimizer: The optimizer to wrap
            strategy: Reference to the strategy for handling the optimizer step

        FabricN)
_optimizer	_strategy
_callbackstype	__class____name__)selfr)   r*   r+    r5   M/home/ubuntu/.local/lib/python3.10/site-packages/lightning/fabric/wrappers.py__init__:   s   
"z_FabricOptimizer.__init__c                 C      | j S N)r.   r4   r5   r5   r6   r)   K      z_FabricOptimizer.optimizerc                 C   s   | j | jS r9   )r/   get_optimizer_stater)   r:   r5   r5   r6   
state_dictO   s   z_FabricOptimizer.state_dictr=   c                 C   s   | j | d S r9   )r)   load_state_dict)r4   r=   r5   r5   r6   r>   R   s   z _FabricOptimizer.load_state_dictclosurec                 C   s   |d urd|ini }t | jdrt| jjtr| jj}n| j}| jj|fi |}| jD ]}t|dd }t	|r?|| j|d q,|S )Nr?   modelon_after_optimizer_step)r*   r)   )
hasattrr/   
isinstancer@   r    r)   optimizer_stepr0   getattrcallable)r4   r?   kwargsr)   outputcallbackhookr5   r5   r6   stepU   s   

z_FabricOptimizer.stepitemc                 C   s   t | j|S r9   )rE   r.   r4   rL   r5   r5   r6   __getattr__f   s   z_FabricOptimizer.__getattr__r9   )r3   
__module____qualname__r   r   r   r   r   r7   propertyr)   r   strr   r=   r>   r   rK   rN   r5   r5   r5   r6   r(   9   s    $r(   c                       s  e Zd Z	d0dejdedeej ddf fddZedejfdd	Z	e
d
ededefddZeddddedededefddZeddddededeeef fddZe
	d1dee dededeeeef  fddZe
	d2deeef dededefddZdeeef ddfdd Zd!edefd"d#Zded$edefd%d&Zd'edefd(d)Ze
d*edef fd+d,Ze
d$ed-eddf fd.d/Z  Z S )3_FabricModuleNforward_moduler*   original_moduler,   c                    s4   t    || _|p|| _|| _tt| _d| _dS )a  The FabricModule is a thin wrapper around the :class:`torch.nn.Module` and handles precision / autocast
        automatically for the forward pass.

        The underlying wrapped module can be accessed via the property :attr:`module`.

        Args:
            forward_module: The module to wrap the ``forward`` method on.
            strategy: Reference to the strategy for handling precision etc.
            original_module: The original, unmodified module as passed into the
                :meth:`lightning.fabric.fabric.Fabric.setup` method. This is needed when attribute lookup
                on this wrapper should pass through to the original module.

        TN)	superr7   _forward_module_original_moduler/   set_LIGHTNING_MODULE_STEP_METHODS_forward_methods_fabric_module_initialized)r4   rT   r*   rU   r2   r5   r6   r7   k   s   



z_FabricModule.__init__c                 C   s   | j p| jS r9   )rX   rW   r:   r5   r5   r6   module   s   z_FabricModule.moduleargsrG   c                 O   sp   | j j}|||f\}}|  | j|i |}W d   n1 s$w   Y  ||}t|t| jd |S )ziCasts all inputs to the right precision and handles autocast for operations in the module forward method.Ndtypefunction)	r/   	precisionconvert_inputforward_contextrW   convert_outputr   r   _register_backward_hook)r4   r_   rG   rc   rH   r5   r5   r6   forward   s   

z_FabricModule.forward.)prefix	keep_varsdestinationri   rj   c                C      d S r9   r5   r4   rk   ri   rj   r5   r5   r6   r=         z_FabricModule.state_dictc                C   rl   r9   r5   )r4   ri   rj   r5   r5   r6   r=      rn    Fc                 C   s   | j j|||dS )N)rk   ri   rj   )rX   r=   rm   r5   r5   r6   r=      s
   Tr=   strictc                 K   s   | j jd||d|S )N)r=   rp   r5   )rX   r>   )r4   r=   rp   rG   r5   r5   r6   r>      s   z_FabricModule.load_state_dictmethodc                 C   s   t |ttfstdt|j t |tr|n|j}|dkr#tdt t| j|dts?t	d| dt| jj d| d| j
| dS )	z]Mark a method as a 'forward' method to prevent it bypassing the strategy wrapper (e.g., DDP).z(Expected a method or a string, but got: rh   z>You cannot mark the forward method itself as a forward method.NzYou marked 'z' as a forward method, but `.z$` does not exist or is not a method.)rC   r   rR   	TypeErrorr1   r3   
ValueErrorrE   rX   AttributeErrorr[   add)r4   rq   namer5   r5   r6   mark_forward_method   s   z!_FabricModule.mark_forward_methodmethod_namec                    sR    dksJ j jdtdtdtf fdddtdtdtffdd}|S )	Nrh   r_   rG   r,   c                     s"   j _tj  }|| i |S r9   )rX   rh   rE   )r_   rG   rq   )ry   original_forwardr4   r5   r6   wrapped_forward   s   zC_FabricModule._redirection_through_forward.<locals>.wrapped_forwardc                     s    j _ j| i |S r9   )rX   rh   )r_   rG   )r4   r{   r5   r6   call_forward_module   s   zG_FabricModule._redirection_through_forward.<locals>.call_forward_module)rX   rh   r   )r4   ry   r|   r5   )ry   rz   r4   r{   r6   _redirection_through_forward   s
   z*_FabricModule._redirection_through_forwardrw   c                    sL   ddt dt ddffdd tdt d	t dt f fd
d}|S )zTracks whether any submodule in ``self._original_module`` was called during the execution of ``method`` by
        registering forward hooks on all submodules.F___r,   Nc                     s   d d S )NTr5   )r~   r   )module_calledr5   r6   rJ      s   zA_FabricModule._wrap_method_with_module_call_tracker.<locals>.hookr_   rG   c                     sp   g }j  D ]
}||  q| i |}r-tdtj j d dd|D ]}|  q/|S )NzYou are calling the method `rr   z()` from outside the model. To avoid issues with the currently selected strategy, explicitly mark it as a forward method with `fabric_model.mark_forward_method(z)` after `fabric.setup()`.)rX   modulesappendregister_forward_hookRuntimeErrorr1   r3   remove)r_   rG   handlesr^   rH   handlerJ   rq   r   rw   r4   r5   r6   _wrapped_method   s   
zL_FabricModule._wrap_method_with_module_call_tracker.<locals>._wrapped_method)r   r   )r4   rq   rw   r   r5   r   r6   %_wrap_method_with_module_call_tracker   s
   $z3_FabricModule._wrap_method_with_module_call_trackertensorc                    sL   |j s|S td jtd}t fdddD }tt|p|}|| |S )Nbackwardparentc                 3   s"    | ]}t | jjtd V  qdS )r   N)r   r/   rc   r   ).0rq   r:   r5   r6   	<genexpr>   s
    
z8_FabricModule._register_backward_hook.<locals>.<genexpr>)pre_backwardr   post_backward)requires_gradr   r/   r   anyr   _backward_hookregister_hook)r4   r   strategy_requiresprecision_requiresrJ   r5   r:   r6   rg      s   
z%_FabricModule._register_backward_hookrL   c                    s   |dkr|| j v r| j| jkr| |S zt |W S  tyB   t d}t||}t	|r>| j| jkr>| 
||}| Y S w )Nr[   rX   )r[   rW   rX   r}   rV   rN   ru   rE   inspectismethodr   )r4   rL   rU   attrr]   r5   r6   rN      s   


z_FabricModule.__getattr__valuec                    s|   t | ddst || d S | j}t||}|t| v }|s)|s)t||| d S |r1t||| |r<t || d S d S )Nr\   F)rE   rV   __setattr__rX   rB   dirsetattr)r4   rw   r   rU   original_has_attrfabric_has_attrr]   r5   r6   r     s   
z_FabricModule.__setattr__r9   )Nro   F)T)!r3   rO   rP   r   Moduler   r   r7   rQ   r^   r   r   rh   r   r!   rR   boolr=   r   r   r   r>   r   r   rx   r   r}   r   r   rg   rN   r   __classcell__r5   r5   r]   r6   rS   j   sb    $(	
$rS   c                   @   st   e Zd Zddedeej ddfddZedeej fddZde	fd	d
Z
deee eeddf f fddZdS )_FabricDataLoaderN
dataloaderdevicer,   c                 C   s$   | j |j  || _|| _d| _dS )a  The FabricDataLoader is a wrapper for the :class:`~torch.utils.data.DataLoader`. It moves the data to the
        device automatically if the device is specified.

        Args:
            dataloader: The dataloader to wrap
            device: The device to which the data should be moved. By default the device is `None` and no data
                transfers will be made (identical behavior as :class:`~torch.utils.data.DataLoader`).

        r   N)__dict__update_dataloader_device_num_iter_calls)r4   r   r   r5   r5   r6   r7   +  s   

z_FabricDataLoader.__init__c                 C   r8   r9   )r   r:   r5   r5   r6   r   :  r;   z_FabricDataLoader.devicec                 C   s
   t | jS r9   )lenr   r:   r5   r5   r6   __len__>  s   
z_FabricDataLoader.__len__c                 c   sZ    t | j| j |  jd7  _| jd u rt| jE d H  d S | jD ]	}t|| jV  q!d S )N   )r   r   r   r   iterr   rM   r5   r5   r6   __iter__A  s   

z_FabricDataLoader.__iter__r9   )r3   rO   rP   r   r   torchr   r7   rQ   intr   r   r
   r   r	   r   r5   r5   r5   r6   r   *  s    (r   
collectionr,   c                 C   sN   dt tttf dt tjttf fdd}tttg}|t	 t
| t||dS )Nobjr,   c                 S   sH   t t| d  }trt|jd S t | tr| jS t | tr"| jS | S Nr   )rC   _unwrap_compiledrS   rW   r(   r)   r   r   )r   	unwrappedr5   r5   r6   _unwrapP  s   

z _unwrap_objects.<locals>._unwrapr`   )r   rS   r(   r   r   r   r   r   r   r   r   tuple)r   r   typesr5   r5   r6   _unwrap_objectsO  s   


r   r   c                 C   s8   t | trt| dd }du rtd| j|fS | dfS )zRemoves the :class:`torch._dynamo.OptimizedModule` around the object if it is wrapped.

    Use this function before instance checks against e.g. :class:`_FabricModule`.

    _compile_kwargsNzFailed to determine the arguments that were used to compile the module. Make sure to import lightning before `torch.compile` is used.)rC   r   rE   r   	_orig_mod)r   compile_kwargsr5   r5   r6   r   a  s   

r   r^   r   c                 C   s   t j| fi |S r9   )r   compile)r^   r   r5   r5   r6   _to_compiledq  s   r   requires_backwardr~   c                 G   s   | rt s
tdd S d S )NzwThe current strategy and precision selection requires you to call `fabric.backward(loss)` instead of `loss.backward()`.)r'   r   )r   r~   r5   r5   r6   r   u  s
   r   c                 C   s   t | \} }t| tttfS )aZ  Checks if an object was set up by Fabric.

    A :class:`~torch.nn.Module` may be wrapped by a :class:`_FabricModule`, a :class:`~torch.optim.Optimizer`
    may be wrapped by a :class:`_FabricOptimizer`, or a :class:`~torch.utils.data.DataLoader` may be wrapped by
    :class:`_FabricDataLoader`.

    Args:
        obj: The object to test.

    )r   rC   rS   r(   r   )r   r~   r5   r5   r6   
is_wrapped}  s   r   
compile_fnc                    s&   t  dtdtdtf fdd}|S )aZ  Wraps the ``torch.compile`` function and captures the compile arguments.

    We extract the compile arguments so that we can reapply ``torch.compile`` in ``Fabric.setup()`` with the
    same arguments as the user passed to the original call. The arguments get stored in a dictionary
    ``_compile_kwargs`` on the returned compiled module.

    r_   rG   r,   c                     sH   | r
t | d tjs | i |S | d } |fi |}t||_|S r   )rC   r   r   r   r   )r_   rG   r@   compiled_modelr   r5   r6   _capture  s   
z)_capture_compile_kwargs.<locals>._capture)r   r   )r   r   r5   r   r6   _capture_compile_kwargs  s   
r   )Dr   copyr   	functoolsr   r   r   r   typingr   r   r   r	   r
   r   r   r   r   r   r   r   r   lightning_utilitiesr   #lightning_utilities.core.apply_funcr   r   r   torch._dynamor   torch.nn.modules.moduler   torch.optimr   torch.utils.datar   typing_extensionsr   lightning.fabric.pluginsr   lightning.fabric.strategiesr   lightning.fabric.utilitiesr   lightning.fabric.utilities.datar   -lightning.fabric.utilities.device_dtype_mixinr    lightning.fabric.utilities.typesr    rR   r!   rZ   r'   r   __annotations__r(   rS   r   r   r   r   r   r   objectr   r   r   r5   r5   r5   r6   <module>   sF   
81 A%8 