a
    dZW                     @   sh  d Z ddlZddlZddl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 ddlZddl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!m"Z" erddlm#Z# ddl$m%Z% ddl&m'Z' er
ddl(m)Z)m*Z*m+Z+ e,e-Z.e" Z/eej0j1ej2j0j1ej2j0j3f Z4G dd dZ5G dd dZ6G dd deZ7dS )z<Profiler to check if there are any bottlenecks in your code.    N)	lru_cachepartial)Path)	AnyCallableContextManagerDictListOptionalTypeTYPE_CHECKINGUnion)nnTensor)record_function)is_cuda_available)Profiler)MisconfigurationException)_KINETO_AVAILABLE)rank_zero_warnWarningCache)	EventList)RemovableHandle)LightningModule)ProfilerActionProfilerActivitytensorboard_trace_handlerc                   @   sr   e Zd ZdZejddddZejeeedddZ	ejeeeed	d
dZ
ddddZeeeddddZdS )RegisterRecordFunctionad  While profiling autograd operations, this class will add labels for module names around the forward
    function.

    The Lightning PyTorch Profiler will activate this feature automatically. It can be deactivated as follows:

    Example::
        from pytorch_lightning.profilers import PyTorchProfiler
        profiler = PyTorchProfiler(record_module_names=False)
        Trainer(profiler=profiler)

    It can be used outside of Lightning as follows:

    Example::
        from pytorch_lightning import Trainer, seed_everything
        with RegisterRecordFunction(model):
            out = model(batch)
    N)modelreturnc                 C   s   || _ i | _i | _d S N)_model_records_handles)selfr    r%   l/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/pytorch_lightning/profilers/pytorch.py__init__B   s    zRegisterRecordFunction.__init__)_inputrecord_namer   c                 C   s"   t d| }|  || j|< |S )Nz[pl][module])r   	__enter__r"   )r$   r(   r)   r*   recordr%   r%   r&   _start_recording_forwardG   s    
z/RegisterRecordFunction._start_recording_forward)r(   __outputr*   r   c                 C   s   | j | d d d  |S r    )r"   __exit__)r$   r(   r.   r/   r*   r%   r%   r&   _stop_recording_forwardN   s    z.RegisterRecordFunction._stop_recording_forwardr   c                 C   sz   | j  D ]j\}}|r
t|j dt|j }| d| }|t| j|d}|t| j	|d}||g| j
|< q
d S )N.z: )r*   )r!   Znamed_modulestype
__module____name__Zregister_forward_pre_hookr   r-   Zregister_forward_hookr1   r#   )r$   module_namemoduleZ	full_namer*   Zpre_forward_handleZpost_forward_handler%   r%   r&   r+   R   s    z RegisterRecordFunction.__enter__)r4   value	tracebackr   c                 C   s,   | j  D ]}|D ]}|  qq
i | _ d S r    )r#   valuesremove)r$   r4   r9   r:   Zhandleshr%   r%   r&   r0   `   s    zRegisterRecordFunction.__exit__)r6   r5   __qualname____doc__r   Moduler'   r   strr-   r1   r+   r   r0   r%   r%   r%   r&   r   /   s   r   c                   @   s   e Zd ZdZeddddZddddZedd	d
dZeddddZ	e
edddZe
edddZe
edddZe
edddZe
edddZddddZe
edddZedddd ZdS )!ScheduleWrapperzThis class is used to override the schedule logic from the profiler and perform recording for both
    `training_step`, `validation_step`.N)scheduler   c                 C   s   t std|| _|   d S )NzEYou are trying to use `ScheduleWrapper` which require kineto install.)r   ModuleNotFoundError	_schedulereset)r$   rC   r%   r%   r&   r'   k   s    zScheduleWrapper.__init__r2   c                 C   sF   d| _ d| _d| _d| _d| _d| _d| _d| _d | _d | _	d | _
d S )Nr   F)_num_training_step_num_validation_step_num_test_step_num_predict_step_training_step_reached_end_validation_step_reached_end_test_step_reached_end_predict_step_reached_end_current_action_prev_schedule_action_start_action_namer$   r%   r%   r&   rF   q   s    zScheduleWrapper.reset)start_action_namer   c                 C   s
   || _ d S r    )rQ   )r$   rS   r%   r%   r&   setup   s    zScheduleWrapper.setup)current_actionr   c                 C   s
   || _ d S r    )rO   )r$   rU   r%   r%   r&   pre_step   s    zScheduleWrapper.pre_stepc                 C   s   | j d usJ | j dS )Ntraining_steprO   endswithrR   r%   r%   r&   is_training   s    zScheduleWrapper.is_trainingc                 C   s   | j d usJ | j dS )Nvalidation_steprX   rR   r%   r%   r&   is_validating   s    zScheduleWrapper.is_validatingc                 C   s   | j d usJ | j dS )N	test_steprX   rR   r%   r%   r&   
is_testing   s    zScheduleWrapper.is_testingc                 C   s   | j d usJ | j dS )Npredict_steprX   rR   r%   r%   r&   is_predicting   s    zScheduleWrapper.is_predictingc                 C   s4   | j r| jS | jr| jS | jr$| jS | jr0| jS dS )Nr   )rZ   rG   r\   rH   r^   rI   r`   rJ   rR   r%   r%   r&   num_step   s    zScheduleWrapper.num_stepc                 C   s   | j r|  jd7  _nt| jr`| jd us*J | jdrP| jdkr^|  jd7  _q|  jd7  _n*| jrv|  jd7  _n| jr|  j	d7  _	d S )N   Zon_fit_startr   )
rZ   rG   r\   rQ   rY   rH   r^   rI   r`   rJ   rR   r%   r%   r&   _step   s    
zScheduleWrapper._stepc                 C   s4   | j r| jS | jr| jS | jr$| jS | jr0| jS dS )NF)rZ   rK   r\   rL   r^   rM   r`   rN   rR   r%   r%   r&   has_finished   s    zScheduleWrapper.has_finishedr   )ra   r   c                 C   s   | j d u s| jrtjS |   | t| jd}| jtj	krL|tj
krLtj	}|tjkr| jrdd| _n(| jrrd| _n| jrd| _n| jrd| _|| _|S )Nr   T)rO   rd   r   NONErc   rE   maxra   rP   RECORDZWARMUPZRECORD_AND_SAVErZ   rK   r\   rL   r^   rM   r`   rN   )r$   ra   actionr%   r%   r&   __call__   s"    
zScheduleWrapper.__call__)r6   r5   r>   r?   r   r'   rF   rA   rT   rV   propertyboolrZ   r\   r^   r`   intra   rc   rd   ri   r%   r%   r%   r&   rB   g   s&   rB   c                       sF  e Zd Zh dZh dZd+eeeef  ee e	e	e	e
ee e	edd
 fdd	Zedd
ddZeee
ef dddZe	dddZeedee dddZed dddZeddddZeddddZedddZdddd Zee ed!d"d#Zddd$d%Zddd&d'Z ee dd( fd)d*Z!  Z"S ),PyTorchProfiler>   rW   r]   r_   r[   >	   Zcuda_time_totalZ	cuda_timecountZself_cpu_memory_usageZcpu_memory_usageZself_cuda_memory_usageZcuda_memory_usageZcpu_timeZcpu_time_totalNFT   )
dirpathfilenamegroup_by_input_shapes	emit_nvtxexport_to_chrome	row_limitsort_by_keyrecord_module_namesprofiler_kwargsr   c	           
         s   t  j||d |o|	dd| _|| _|| _|| _|pP|	ddrHdnd d| _|| _|	| _	d| _
d| _d| _d| _d| _i | _d| _d| _tr| |	 | j| jvrtd	| j d
| j ddS )a  This profiler uses PyTorch's Autograd Profiler and lets you inspect the cost of.

        different operators inside your model - both on the CPU and GPU

        Args:
            dirpath: Directory path for the ``filename``. If ``dirpath`` is ``None`` but ``filename`` is present, the
                ``trainer.log_dir`` (from :class:`~pytorch_lightning.loggers.tensorboard.TensorBoardLogger`)
                will be used.

            filename: If present, filename where the profiler results will be saved instead of printing to stdout.
                The ``.txt`` extension will be used automatically.

            group_by_input_shapes: Include operator input shapes and group calls by shape.

            emit_nvtx: Context manager that makes every autograd operation emit an NVTX range
                Run::

                    nvprof --profile-from-start off -o trace_name.prof -- <regular command here>

                To visualize, you can either use::

                    nvvp trace_name.prof
                    torch.autograd.profiler.load_nvprof(path)

            export_to_chrome: Whether to export the sequence of profiled operators for Chrome.
                It will generate a ``.json`` file which can be read by Chrome.

            row_limit: Limit the number of rows in a table, ``-1`` is a special value that
                removes the limit completely.

            sort_by_key: Attribute used to sort entries. By default
                they are printed in the same order as they were registered.
                Valid keys include: ``cpu_time``, ``cuda_time``, ``cpu_time_total``,
                ``cuda_time_total``, ``cpu_memory_usage``, ``cuda_memory_usage``,
                ``self_cpu_memory_usage``, ``self_cuda_memory_usage``, ``count``.

            record_module_names: Whether to add module names while recording autograd operation.

            \**profiler_kwargs: Keyword arguments for the PyTorch profiler. This depends on your PyTorch version

        Raises:
            MisconfigurationException:
                If arg ``sort_by_key`` is not present in ``AVAILABLE_SORT_KEYS``.
                If arg ``schedule`` is not a ``Callable``.
                If arg ``schedule`` does not return a ``torch.profiler.ProfilerAction``.
        )rp   rq   Zrecord_shapesFuse_cudacudacpuZ_time_totalNzFound sort_by_key: z. Should be within z. )superr'   get_group_by_input_shapes
_emit_nvtx_export_to_chrome
_row_limit_sort_by_key_record_module_names_profiler_kwargsprofilerfunction_events_lightning_module	_register_parent_profiler_recording_maprQ   rE   r   _init_kinetoAVAILABLE_SORT_KEYSr   )
r$   rp   rq   rr   rs   rt   ru   rv   rw   rx   	__class__r%   r&   r'      s,    : 
zPyTorchProfiler.__init__)rx   r   c                 C   s   d|v }d|v | _ |dd }|d ur\t|s<td| |d}t|ts\td| |   |rl|n|  }|d urt|n|| _| j| j	d< |dd }|p| 
 | j	d< |dd| _|d	d
| _|ddp| j}|| j	d< d S )NrC   on_trace_readyz&Schedule should be a callable. Found: r   zASchedule should return a `torch.profiler.ProfilerAction`. Found: 
activitiesZexport_to_flame_graphFmetricZself_cpu_time_total
with_stack)_has_on_trace_readyr}   callabler   
isinstancer   _default_schedulerB   rE   r   _default_activities_export_to_flame_graph_metric)r$   rx   Zhas_schedulerC   rh   r   r   r%   r%   r&   r   >  s*    

zPyTorchProfiler._init_kinetor2   c                 C   s~   | j d usJ | jd usJ | jj}| j jr2|jS | j jrNt|jt|j S | j j	r`t|j
S | j jrrt|jS tdd S )NzUnsupported schedule)rE   r   trainerrZ   Znum_training_batchesr\   sumZnum_val_batchesZnum_sanity_val_batchesr^   Znum_test_batchesr`   Znum_predict_batchesNotImplementedError)r$   r   r%   r%   r&   _total_stepsW  s    

zPyTorchProfiler._total_stepsc                 C   s.   | j d uo,| jd uo,| jdk o,| jj|  kS )N   )r   rE   r   r   rR   r%   r%   r&   _should_override_schedulef  s    
z)PyTorchProfiler._should_override_schedulerb   c                   C   s   t rtjjddddS d S )Nrb      )waitZwarmupactive)r   torchr   rC   r%   r%   r%   r&   r   n  s    z!PyTorchProfiler._default_scheduler   c                 C   sF   g }t s|S | jddr&|tj | jdt rB|tj |S )NZuse_cpuTry   )r   r   r}   appendr   ZCPUr   ZCUDA)r$   r   r%   r%   r&   r   u  s    z#PyTorchProfiler._default_activities)action_namer   c                 C   s   | j d u rhtj rtj  | jd ur4| j| |   | j  }|d urT|| _ | j	d urh| j	  | j
d ur| jd u r| jrt| j
| _| j  | j d ur|| jvrtd| }|  || j|< d S )Nz[pl][profile])r   r   autogradZ_profiler_enabledZ_disable_profilerrE   rT   _create_profilersr+   r   r   r   r   r   r   r   )r$   r   r   Z	recordingr%   r%   r&   start  s$    







zPyTorchProfiler.startc                    s    j v r&j   d d d  j  = tr0jr4d S jd urt fddjD rtjtjj	sjJ j
d urj
   rtd d _
tjjjj_td d fdd}js|j_j
d urj
jj_j  jdd d S )	Nc                 3   s   | ]}  |V  qd S r    )rY   ).0func)r   r%   r&   	<genexpr>      z'PyTorchProfiler.stop.<locals>.<genexpr>zpThe PyTorch Profiler default schedule will be overridden as there is not enough steps to properly record traces.r   r   c                    s   j d urxjr2ttj j dd}||  jrtjj j dd}t	| t
jjjsfJ | j|jd ntd d S )N )r   	extensionz.stack)r   z?The PyTorchProfiler failed to export trace as `dirpath` is None)rp   r   r   rA   Z_prepare_filenamer   ospathjoinr   r   r   r   profileZexport_stacksr   r   )r   handlerr   r   r$   r%   r&   r     s    
z,PyTorchProfiler.stop.<locals>.on_trace_readyZ	Frameworkzpytorch-lightning)r   r0   r   r   r   anySTEP_FUNCTIONSr   r   r   rE   rV   r   warning_cachewarnZ_default_schedule_fnrC   	_PROFILERr   r   ra   Zstep_numstepZadd_metadata)r$   r   r   r%   r   r&   stop  s,    

"


zPyTorchProfiler.stopc                 C   s   | j ddr| jrdS |   | js*dS | jrjtsj| j d}| jd u rN|nt	j
| j|}| j| | jj| jd}|j| j| jd}d|i}| |S )NZenabledTr   z_trace.json)rr   )Zsort_byru   records)r   r}   r   _delete_profilersr   r   r   Z
local_rankrp   r   r   r   Zexport_chrome_traceZkey_averagesr~   tabler   r   Z_stats_to_str)r$   rq   Zpath_to_tracedatar   Zrecorded_statsr%   r%   r&   summary  s    
zPyTorchProfiler.summaryc                 C   sh   | j d urd S | jr@| jd u r,tjj  | _| tjj j| _ n$d | _| t	rVtj jntjj j| _ d S r    )
r   r   r   r   rz   r   _create_profilerr   rs   r   rR   r%   r%   r&   r     s    

z!PyTorchProfiler._create_profilersr   c                    s4   t |jj  fdd| j D }|f i |S )Nc                    s   i | ]\}}| v r||qS r%   r%   )r   kvZinit_parametersr%   r&   
<dictcomp>  r   z4PyTorchProfiler._create_profiler.<locals>.<dictcomp>)inspect	signaturer'   
parametersr   items)r$   r   kwargsr%   r   r&   r     s    z PyTorchProfiler._create_profilerc                 C   sT   | j r
d S tr0t| jtjjs"J | j | _n t| jtjjjsFJ | jj| _d S r    )	r   r   r   r   r   r   eventsr   r   rR   r%   r%   r&   _cache_functions_events  s    z'PyTorchProfiler._cache_functions_eventsc                 C   s   | j d ur(| j d d d  |   d | _ | jd ur<| j  | jd ur\| jd d d  d | _| jd ur|| jd d d  d | _d S r    )r   r0   r   rE   rF   r   r   rR   r%   r%   r&   r     s    




z!PyTorchProfiler._delete_profilers)stager   c                    s:   |    t| jD ]}| | qi | _t j|d d S )N)r   )r   listr   r   r|   teardown)r$   r   r   r   r%   r&   r     s
    zPyTorchProfiler.teardown)NNFFTro   NT)#r6   r5   r>   r   r   r
   r   rA   r   rk   rl   r   r'   r   rj   floatr   r   staticmethodr   r   r   r	   r   r   r   r   r   r   r   r   r   r   r   __classcell__r%   r%   r   r&   rm      sL           U
0rm   )8r?   r   loggingr   	functoolsr   r   pathlibr   typingr   r   r   r   r	   r
   r   r   r   r   r   r   Ztorch.autograd.profilerr   Z"lightning_fabric.accelerators.cudar   Z$pytorch_lightning.profilers.profilerr   Z&pytorch_lightning.utilities.exceptionsr   Z#pytorch_lightning.utilities.importsr   Z%pytorch_lightning.utilities.rank_zeror   r   r   Ztorch.utils.hooksr   Zpytorch_lightning.core.moduler   Ztorch.profilerr   r   r   	getLoggerr6   logr   r   r   r   rs   r   r   rB   rm   r%   r%   r%   r&   <module>   s4   ,
8s