o
    ZhWA                     @   s  d Z ddlZddlZddlmZ ddlZddlmZ ddlm	Z	 ddl
mZmZ ddlmZmZmZmZmZ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! erjddl"m#Z# G dd de$Z%G dd de$Z&ee'dZ(dd Z)G dd de!Z*dS )a
  
This module implements variable tracking for PyTorch optimizers during Dynamo tracing.

The OptimizerVariable class provides specialized handling for optimizer instances by:
- Optimizing the tracing of expensive optimizer initialization
- Managing optimizer state and parameter group tracking
- Handling tensor sources and guards for optimizer state tensors
- Supporting CUDA graph execution through static tensor address management
- Providing special handling for parameter gradients and optimizer state tensors

Key features include:
- Efficient initialization tracing via _init_group optimization
- Automatic marking of optimizer state tensors as static for CUDA graphs
- Proper source tracking for parameter groups, gradients, and state tensors
- Guard installation for optimizer state structure
- Support for both CPU and GPU tensor handling
- Cleanup of static tensor references via finalizers

The module integrates with Dynamo's broader tracing system while providing
optimizer-specific optimizations and safety guarantees.
    N)TYPE_CHECKING)getArtifactLogger)tree_map_only   )GuardBuilderinstall_guard)
AttrSourceConstDictKeySourceDictGetItemSourceGetItemSourceGlobalWeakRefSource
GradSource)GLOBAL_KEY_PREFIX   )VariableTracker)ConstantVariable)ConstDictVariable)ListVariable)GetAttrVariable)UserDefinedObjectVariable)InstructionTranslatorc                   @      e Zd ZdS )ArgMappingExceptionN__name__
__module____qualname__ r   r   P/var/www/auris/lib/python3.10/site-packages/torch/_dynamo/variables/optimizer.pyr   7       r   c                   @   r   )GuardInstallExceptionNr   r   r   r   r   r    ;   r   r    Z
perf_hintsc                 C   sN   ddl m} | jr%|| jjd}tjj| d u}|r#|p"|j	
| S |S dS )Nr   )get_managerFT)Ztorch._inductor.cudagraph_treesr!   is_cudadeviceindextorchZ_dynamoutilsZget_static_address_typeZcurrent_nodeZ_is_cuda_graph_recorded_tensor)xr!   managerZis_static_addressr   r   r   _is_static_for_cudagraphsB   s   
r)   c                       s   e Zd ZdddhejZ			d#	d$ fddZ				
			d% fddZd& fddZdd Zdd Z	dd Z
dd Zdd Zd&ddZ		d&dd Zd!d" Z  ZS )'OptimizerVariablegrad_to_sourcetensor_to_sourcestatic_tensor_namesNreturnc                    s8   t  j|fi | |pi | _|pi | _|pt | _d S N)super__init__r+   r,   setr-   )selfvaluer+   r-   r,   kwargs	__class__r   r   r1   \   s   

zOptimizerVariable.__init__argslist[VariableTracker]r5   dict[str, VariableTracker]r   c           
   
      s   |dkr]zD|  | |   | j|i |\}}| jj|i |}| | | ||||| dt| j }||| j | 	| t
|W S  ttfy\ }	 zW Y d}	~	nd}	~	ww t ||||S )zVThis is an optimization to avoid tracing the very slow initialization of the optimizer_init_groupZ__optimizer_N)graph_break_if_pending_mutationmove_step_if_cpuget_python_argsr4   r;   map_sources_and_install_guardsupdate_list_argsidstore_global_weakref_by_idcreate_finalizerr   creater   r    r0   call_method)
r3   txnamer8   r5   py_args	py_kwargsZret_valZmangled_name_r6   r   r   rE   i   s"   


zOptimizerVariable.call_methodrF   r   c                    sn   |dv rt | |t| j|dS |dkr0ddlm} | jjD ]}|d D ]}|| q#q| | t 	||S )N)r;   step)sourceparam_groupsr   mark_static_addressparams)
r   r   rL   
decoratorsrO   r4   rM   _set_capturabler0   var_getattr)r3   rF   rG   rO   grouppr6   r   r   rS      s   

zOptimizerVariable.var_getattrc                 C   s\   | j jD ]'}|d D ] }|jj}|jt|d }|r*||r*ddlm	} |dq
qd S )NrP   r   )UnsupportedzPending mutation on parameter)
r4   rM   outputside_effectsZid_to_variablegetrA   Zhas_pending_mutationexcrV   )r3   rF   grU   rX   variablerV   r   r   r   r<      s   z1OptimizerVariable.graph_break_if_pending_mutationc           	         s   ddl m}  fdd} jjD ]
}||rd|d< q jo#t jd}|t| jj|}|j	D ]}t
td}td|j	|< q3d S )Nr   LazyVariableTrackerc                    sJ   d}d}|  dg D ]}||jp|jM }|| jjvM }q
d| v o$|o$|S )NTrP   
capturable)rY   r"   Zis_xpur4   state)rT   Zall_uninitializedZall_gpurU   r3   r   r   safe_to_set_capturable   s   zAOptimizerVariable._set_capturable.<locals>.safe_to_set_capturableTr_   rM   ) r^   r4   rM   rL   r   realize_allr   builditemsr   Z_HashableTrackerr   rD   )	r3   rF   r^   rb   rT   rL   param_groups_vtZparam_group_vtkeyr   ra   r   rR      s    
z!OptimizerVariable._set_capturablec                    s<   fdd  fdd|D } fdd|  D }||fS )z9Get python values equivalent to the variable tracker argsc                    sl   t | tr	|  S t | tr| jsg S t | tr4t | jtr4t | jjt	r4| jjj
dkr4 jj| jj S t)NrM   )
isinstancer   Zas_python_constantr   rf   r   rL   r   baser   memberr4   rM   r$   r   )argra   r   r   map_arg   s   

z2OptimizerVariable.get_python_args.<locals>.map_argc                    s   g | ]} |qS r   r   ).0rl   rm   r   r   
<listcomp>       z5OptimizerVariable.get_python_args.<locals>.<listcomp>c                    s   i | ]	\}}| |qS r   r   )rn   kvro   r   r   
<dictcomp>   s    z5OptimizerVariable.get_python_args.<locals>.<dictcomp>)rf   )r3   r8   r5   new_argsZ
new_kwargsr   )rm   r3   r   r>      s   z!OptimizerVariable.get_python_argsc                 C   s@   | j j D ]\}}d|v r|d jr|d |j|d< qd S )NrK   )r4   r`   rf   Zis_cputor#   )r3   rU   r`   r   r   r   r=      s
   z"OptimizerVariable.move_step_if_cpuc                    s  ddl m  ddlm} i | _i | _ fdd}ttj|| j	j
 | jo)t| jd}|t|| j	j|}| jo>t| jd}t|| j	j
|}|  |jj|  t| j	j|jD ]\}}	t|d	 d
kr|d	 D ]6}
|
jd urd }t| j	j
 D ]\}}||
u r|} nq~|r|t|| j	j
|
 t|t||  nqm|	|t d	}d}g }tt|d	 |!|D ]3\}\}}|j}|| j|< t"|d}|jd ur|| j|j< t#|jsd}|$| qt%|&t'j( q|st)*t+j,rdd |D }t)-d| q]t| j	j
 D ]D\}\}}t|t||}|jj|  t| D ]%\}\}}t.|tjrR|| jvrR|| jvrRt|t||| j|< q.qd S )Nr   rN   r   r]   c                    s    |  d S r/   r   )r'   rN   r   r   mark_static   s   zEOptimizerVariable.map_sources_and_install_guards.<locals>.mark_staticrM   r`   rP   r   TgradFc                 S   s   g | ]}|  qS r   rG   )rn   srcr   r   r   rp   A  rq   zDOptimizerVariable.map_sources_and_install_guards.<locals>.<listcomp>)zGrad tensors %s will be copied during cudagraphs execution.If using cudagraphs and the grad tensor addresses will be the same across runs, use torch._dynamo.decorators.mark_static_address to elide this copy.)/rQ   rO   Zlazyr^   r+   r,   r   r%   Tensorr4   r`   rL   r   rd   r   re   rM   ZrealizerW   Zguard_on_key_orderaddrG   ziprf   lenrx   	enumeratekeysr
   r	   Zgetitem_constr   rD   Zunpack_var_sequencer   r)   appendr   Z
make_guardr   ZCONSTANT_MATCHperf_hint_logisEnabledForloggingDEBUGwarningri   )r3   rF   r^   rw   Zparams_groups_sourcerg   Zstate_sourceZstate_vtrT   Zgroup_vtparamZ	key_indexirr   Z	params_vtZ
all_staticZnon_static_gradsZp_indrU   Zp_vtZparam_sourceZgrad_sourceidxr4   Zp_state_sourceZ	inner_idxrs   r   rN   r   r?      s   











z0OptimizerVariable.map_sources_and_install_guardsc                 C   s   ddl m} || jv r!|| | j| }| j|j|  n%|| jv r,| j| }n|| |	t
|}t|}| j|j|  t|||S )z%Wrap state tensor in a TensorVariabler   rN   )rQ   rO   r,   r-   r|   rW   Zmodule_key_namerG   r+   rB   r   r   r   re   )r3   rF   Ztensor_valuerO   rL   Zglobal_namer   r   r   wrap_tensor\  s   


zOptimizerVariable.wrap_tensorc              	   C   s   t ||D ]G\}}t|trLt|tsJ dt|D ]0\}}	|jj| t|	tj	r7|j
| ||	 q|jo?t|j|}
|j
t||	|
 qqdS )z7Update the args and kwargs to the traced optimizer callz-py_arg should be a list in optimizer variableN)r}   ri   r   listr   rW   rX   Zmutationr%   r{   rf   r   r   rL   r   r   re   )r3   rF   r8   r5   rH   rI   rl   Zpy_argr   valrL   r   r   r   r@   v  s   
z"OptimizerVariable.update_list_argsc                    s4   | j  | j|jj fdd}|j| d S )Nc                    s     fdd}t | d S )Nc                     sJ   D ] }  j | d   j| d  jrj  jr"j  qd S r/   )_bufferspop_parametersZparams_flatclearZparams_flat_unwrap_subclassesry   )gmnames_to_deletetcr   r   clear_static_tensor_refs  s   

z\OptimizerVariable.create_finalizer.<locals>.init_finalizer.<locals>.clear_static_tensor_refs)weakreffinalize)r   r   r   r   r4   )r   r   init_finalizer  s   	z:OptimizerVariable.create_finalizer.<locals>.init_finalizer)r-   r4   rW   Ztracing_contextZadd_graph_finalizer)r3   rF   r   r   r   r   rC     s
   z"OptimizerVariable.create_finalizer)NNN)r.   N)r8   r9   r5   r:   r.   r   )rF   r   )r   r   r   r   Z_nonvar_fieldsr1   rE   rS   r<   rR   r>   r=   r?   r   r@   rC   __classcell__r   r   r6   r   r*   T   s>    
! 
q
r*   )+__doc__r   r   typingr   r%   Ztorch._loggingr   Ztorch.utils._pytreer   Zguardsr   r   rL   r   r	   r
   r   r   r   r&   r   rj   r   Zconstantr   Zdictsr   listsr   miscr   Zuser_definedr   Ztorch._dynamo.symbolic_convertr   	Exceptionr   r    r   r   r)   r*   r   r   r   r   <module>   s.    
