o
    ?߱i-#                     @   s   d 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
Z
ddlmZ edd	d
ZdefddZdedefddZddededB defddZdededefddZG dd deZdS )z>
Timer: helps measure CPU and CUDA times easily and reliably.
    N)ContextDecorator)
ContextVarwraps)Callable)log_timer_activeF)defaultreturnc                   C   s   t  S N)r   get r   r   U/data/cameron/vidgen/cosmos-predict2.5/cosmos_predict2/_src/imaginaire/utils/timer.pyin_timer_region!   s   r   time_usc                 C   sD   | dkr| d }|ddS | dkr| d }|ddS | ddS )	z3
    Automatically format time in nanoseconds.
        .Aư>.2f s     @@MbP? ms usr   )r   time_stime_msr   r   r   _autoformat_time_us%   s   r   unitc                 C   sd   |du rt | S |dkr| ddS |dkr| d ddS |dkr*| d	 dd
S td| d)ze
    Automatically format time in nanoseconds either automatically or based on
    desired unit.
    Nusr   r   msr   r   sr   r   
Time unit  is not supported.)r   NotImplementedErrorr   r   r   r   r   format_time_str4   s   r$   c                 C   s<   |dkr| S |dkr| d S |dkr| d S t d| d)z;
    Format time in nanoseconds based on desired unit.
    r   r   r   r   r   r    r!   )r"   r#   r   r   r   format_timeH   s   r%   c                   @   s   e Zd ZdZ					d)dedB dedededB d	ef
d
dZdefddZdd Zdd Z	de
de
fddZdd ZdefddZdefddZdefddZdefdd Zd!d" Zd*d#ejdB d$ejjdB fd%d&Zd'd( ZdS )+TimeraN  
    Reliable CPU and CUDA Timer.

    Args:
        tag (str | None): Optional tag used in logs/prints.

        measure_cpu (bool): Whether to measure CPU time (using `time`). Default: `True`.

        measure_cuda (bool): Whether to measure CUDA time (using CUDA events). Default: `True`.

        unit (str | None): Optional time unit. Must be either "s" (seconds), "ms" (microseconds),
            "us" (nanoseconds), or None (format automatically based on value).

        debug (bool): Whether to log results in debug mode instead of info. Default is False.

    Examples:
        ```python
        with Timer(measure_cpu=True, measure_cuda=True, unit="ms"):
            model(x)
        ```

        ```python
        @Timer(measure_cpu=True, measure_cuda=True, unit="ms")
        def func(x):
            return model(x)
        ```
    NTFtagmeasure_cpumeasure_cudar   debugc                 C   s   || _ || _d| _d| _d| _d| _d | _d | _d | _d | _	|d u r$dn|| _
|| _| jd ur=| jdvr=td| j d|| _d S )NFr   unknown)r   r   r   r    r!   )r(   r)   measuredcpu_time_uscuda_time_usbusycpu_time_startcuda_start_eventcuda_end_eventcuda_streamr'   r   r"   r*   )selfr'   r(   r)   r   r*   r   r   r   __init__v   s   
zTimer.__init__msgc                 C   s"   | j r
t | d S t| d S r   )r*   r   info)r4   r6   r   r   r   _log   s   z
Timer._logc                 C   s   t d| _|   d S )NT)r   settokenstartr4   r   r   r   	__enter__   s   zTimer.__enter__c                 C   s    |    |   t| j d S r   )endreportr   resetr:   )r4   exc_type	exc_value	tracebackr   r   r   __exit__   s   zTimer.__exit__funcr
   c                    s   t   fdd}|S )Nc                     s*       | i |}    |S r   )r;   r>   r?   )argskwargsresultrE   r4   r   r   wrapper   s
   zTimer.__call__.<locals>.wrapperr   )r4   rE   rJ   r   rI   r   __call__   s   zTimer.__call__c              	   C   s   | j r| jr| d| j d|   d|    dS | j r.| d| j d|    dS | jrA| d| j d|    dS t )z'
        Reports measurements.
        zTime spent on z: CPU: z, CUDA: z: zCUDA time spent on N)r(   r)   r8   r'   get_cpu_time_strget_cuda_time_strr"   r<   r   r   r   r?      s   *  zTimer.reportc                 C   V   | j std| j d| jstd| jdu rtd| jdus#J t| j| jdS )z/
        Returns CPU time measurement.
        (CPU timer is disabled (self.measure_cpu=).No measurements were made yet!Nz=No unit was specified. Please use get_cpu_time_str() instead.r   )r(   RuntimeErrorr,   r   r%   r-   r<   r   r   r   get_cpu_time      
zTimer.get_cpu_timec                 C   rN   )z0
        Returns CUDA time measurement.
        *CUDA timer is disabled (self.measure_cuda=rP   rQ   Nz>No unit was specified. Please use get_cuda_time_str() instead.rR   )r)   rS   r,   r   r%   r.   r<   r   r   r   get_cuda_time   rU   zTimer.get_cuda_timec                 C   6   | j std| j d| jstdt| j| jdS )z@
        Returns CPU time measurement in string format.
        rO   rP   rQ   rR   )r(   rS   r,   r$   r-   r   r<   r   r   r   rL      
   zTimer.get_cpu_time_strc                 C   rX   )zA
        Returns CUDA time measurement in string format.
        rV   rP   rQ   rR   )r)   rS   r,   r$   r.   r   r<   r   r   r   rM      rY   zTimer.get_cuda_time_strc                 C   s   d| _ d| _d| _dS )z.
        Resets recorded measurements
        Fr   N)r,   r-   r.   r<   r   r   r   r@      s   
zTimer.resetcuda_devicer3   c                 C   s   | j rtdd| _ | jr|dur|ntj|| _| j  | jr't		 | _
| jrCtjjdd| _tjjdd| _| j| j dS dS )aY  
        Start time measurements.

        Args:
            cuda_device (torch.device | None): CUDA device. Will use default CUDA device if not indicated.

            cuda_stream (torch.cuda.Stream | None): CUDA stream to use for CUDA time measurement.
                Will use default stream for current CUDA device if not indicated.
        z"Already called Timer.start() once!TN)enable_timing)r/   rS   r)   torchcudacurrent_streamr3   synchronizer(   timer0   Eventr1   r2   record_event)r4   rZ   r3   r   r   r   r;      s   


zTimer.startc                 C   sx   | j std| jr| j| j | j  | jr't | _	| j	| j
 d | _| jr4| j| jd | _d| _ d| _dS )zt
        Ends time measurements.

        NOTE: must be done on the same CUDA device and stream as start().
        z7Timer.start() must be called exactly once before end()!r   r   FTN)r/   rS   r)   r3   rb   r2   r_   r(   r`   Zcpu_time_endr0   r-   r1   elapsed_timer.   r,   r<   r   r   r   r>     s   


z	Timer.end)NTTNF)NN)__name__
__module____qualname____doc__strboolr5   r8   r=   rD   r   rK   r?   floatrT   rW   rL   rM   r@   r\   devicer]   Streamr;   r>   r   r   r   r   r&   Y   s<    
"r&   r   )rg   r`   
contextlibr   contextvarsr   	functoolsr   typingr   r\   %cosmos_predict2._src.imaginaire.utilsr   r   ri   r   rj   rh   r   r$   r%   r&   r   r   r   r   <module>   s   