Ë
    M²jÅ:  ã                   óâ  — U d 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mZ 	 ddlmZ  ee«      Zdaedz  ed	<   d
aeed<   d*d„Zd*d„Zdefd„Zdededz  fd„Zdedefd„Zdedefd„Z ee«      Zeeee   f   ed<   da e!e   dz  ed<   de!e   fd„Z"g Z#ee$eeef      ed<   da%eed<   da&edz  ed<   ede'e(e'ef   z  fd„«       Z)d*d„Z*de	jV                  jX                  ddfd „Z-de(eee   f   fd!„Z.d*d"„Z/d#a0eed$<   i Z1e(eef   ed%<   de	jV                  jd                  defd&„Z3d'e'defd(„Z4ede	jV                  jd                  de'e(e'ef   z  fd)„«       Z5y# e$ r dZY �Œ>w xY w)+a„  Annotate CUDA graph kernel nodes during capture.

During CUDA graph capture, ``mark_kernels`` uses ``cudaGraphGetNodes``
to count nodes before and after the wrapped region.  Nodes at indices
``[before, after)`` are the ones added within the scope.  Each kernel
or memcpy node found is annotated by its ``toolsId`` so it can later
be matched to profiler trace events.

The annotations can be pickled and later merged into a Chrome profiler
trace using ``torch.cuda._annotate_cuda_graph_trace``.

Requires ``cuda.bindings`` package and a CUDA driver that supports
``cudaGraphNodeGetToolsId`` (CUDA >= 13.1 or appropriate cuda-compat).
When unavailable, ``mark_kernels`` silently becomes a no-op.

Usage during capture::

    from torch.cuda._graph_annotations import (
        enable_annotations,
        mark_kernels,
        resolve_pending_annotations,
        remap_to_exec_graph,
    )

    enable_annotations()

    with torch.cuda.graph(graph):
        with mark_kernels("phase_A"):
            y = workload_a(x)
        with mark_kernels("phase_B"):
            z = workload_b(y)
        resolve_pending_annotations()

    remap_to_exec_graph(graph)
é    )Údefaultdict)Úcontextmanager)Ú	getLogger)ÚAnyN)Ú_check_cuda_bindingsÚ_HAS_CUDA_BINDINGS)ÚruntimeÚ_tools_id_availableFÚ_annotations_enabledÚreturnc                  ó   — da y)z#Enable kernel annotation recording.TN©r   © ó    ú\/var/www/html/ia-enhanced/venv/lib/python3.12/site-packages/torch/cuda/_graph_annotations.pyÚenable_annotationsr   A   s
   € ð  Ñr   c                  ó   — da y)z$Disable kernel annotation recording.FNr   r   r   r   Údisable_annotationsr   G   s
   € ð !Ñr   c                  óF   — t         syt        du ryt        t        d«      syy)zBReturn True if we already know cudaGraphNodeGetToolsId is missing.TFÚcudaGraphNodeGetToolsId)r   r
   ÚhasattrÚ_cuda_runtimer   r   r   Ú_is_tools_id_unavailabler   M   s$   € åØÜ˜eÑ#ØÜ”=Ð";Ô<ØØr   Únodec                 óÜ   — t         €#	 t        t        j                  | «      «      }da |S t        t        j                  | «      «      S # t        $ r da t
        j                  d«       Y yw xY w)z<Return the toolsId for a graph node, or None if unavailable.NFzUcudaGraphNodeGetToolsId not available; CUDA graph kernel annotations will be disabledT)r
   r   r   r   Ú	ExceptionÚloggerÚinfo)r   Útools_ids     r   Ú_get_tools_idr    X   sƒ   € ô Ð"ð	Ü+Ü×5Ñ5ØóóˆHð #ÐØˆÜÜ×-Ñ-Øó	
óð øô ò 	Ø"'ÐÜ�K‰KðAôñ ð	ús   ˆA Á A+Á*A+Ústreamc                 óŒ   — t        t        j                  | «      «      \  }}}}}}|t        j                  j                  k7  ry|S )z8Return the graph handle for the active capture, or None.N)r   r   ÚcudaStreamGetCaptureInfoÚcudaStreamCaptureStatusÚcudaStreamCaptureStatusActive)r!   ÚstatusÚ_idÚgraphÚ_depsÚ
_edge_dataÚ	_num_depss          r   Ú_get_capture_graphr,   r   sN   € ä7KÜ×.Ñ.Øó	
ó8Ñ4€FˆC�˜˜z¨9ð 	Ü×0Ñ0×NÑNò	Oð Ø€Lr   r(   c                 óL   — t        t        j                  | d¬«      «      \  }}|S )z2Return the number of nodes currently in the graph.r   ©ÚnumNodes)r   r   ÚcudaGraphGetNodes)r(   Ú_Únums      r   Ú_get_node_countr3   �   s*   € ä!Ü×'Ñ'Ø˜Aô	
ó�F€A€sð
 €Jr   Ú_kernel_annotationsÚ_ANNOTATABLE_TYPESc                  ó‚   — t         €4t        j                  j                  t        j                  j                  ha t         S ©N)r5   r   ÚcudaGraphNodeTypeÚcudaGraphNodeTypeKernelÚcudaGraphNodeTypeMemcpyr   r   r   Ú_get_annotatable_typesr;   “   s6   € äÐ!ä×+Ñ+×CÑCÜ×+Ñ+×CÑCð
Ðô Ðr   Ú_pending_scopesÚ_capture_graphÚ_last_capture_graph_idÚ
annotationc              #   ón  K  — t         r
t        «       rd–— yt        | t        «      rd| i} t	        j
                  t        j                  j                  «       j                  ¬«      }t        |«      }|€d–— y|at        |«      }d–— t        |«      }||kD  rt        j                  | ||f«       yy­w)aÚ  Context manager that records node index ranges for later annotation.

    During capture, calls ``cudaGraphGetNodes`` to count graph nodes before
    and after the scope.  Nodes at indices ``[before, after)`` were added
    inside the scope.  After capture, ``resolve_pending_annotations``
    enumerates all nodes and annotates kernel/memcpy nodes in those ranges.

    Must be called inside an active ``torch.cuda.graph()`` capture.  If the
    current stream is not capturing, or if ``cudaGraphNodeGetToolsId`` is not
    available, the context manager is a no-op.

    Args:
        annotation: Arbitrary object appended to the annotation list for
            every kernel/memcpy node whose index falls within this scope.
    NÚstr©Ú
init_value)r   r   Ú
isinstancerA   r   ÚcudaStream_tÚtorchÚcudaÚcurrent_streamÚcuda_streamr,   r=   r3   r<   Úappend)r?   r!   r(   Ústart_countÚ	end_counts        r   Úmark_kernelsrM   §   s¨   è ø€ õ"  Ô#;Ô#=ÛØä�*œcÔ"Ø˜ZÐ(ˆ
ä×'Ñ'Ü—:‘:×,Ñ,Ó.×:Ñ:ô€Fô ˜vÓ&€EØ€}ÛØð €Nä! %Ó(€Kã	ä Ó&€Ià�;ÒÜ×Ñ 
¨K¸ÐCÕDð ùs   ‚B3B5c                  óˆ  — t         sdayt        j                  t        j
                  j                  «       j                  ¬«      } t        | «      }|€t        }|€*t        j                  d«       t         j                  «        y	 t        |«      }|dk(  r.t         j                  «        da	 t         j                  «        dayt        t        j                  ||¬«      «      \  }}|dkD  rt        |d   «      }|r|dz	  ndat#        «       }t%        d„ t'        t         «      D «       d„ ¬	«      }d}g }t)        |«      D �]«  }	|r)|d
   d   |	k  r|j+                  «        |r|d
   d   |	k  rŒ|t-        |«      k  rL||   d   |	k  rA||   \  }
}}}||	kD  r|j/                  ||
f«       |dz  }|t-        |«      k  r||   d   |	k  rŒA|sŒŒ||	   }t        t        j0                  |«      «      }||vrŒ´t        |«      }|€Ct        j                  d«       t         j                  «        da t         j                  «        dayt-        |«      dk(  r t2        |   j/                  |d   d   «       �Œ2i }t5        |«      D ]R  \  }}
t7        |
t8        «      r+|
j;                  «       D ]  \  }}|j=                  ||«       Œ ŒA|j=                  d|
«       ŒT t2        |   j/                  |«       �Œ® 	 t         j                  «        day# t>        $ r t        jA                  d«       Y Œ7w xY w# t         j                  «        daw xY w)a	  Resolve pending scope index ranges into kernel annotations.

    Enumerates all graph nodes and annotates kernel/memcpy nodes whose
    indices fall within recorded scope ranges. Must be called while still
    inside the ``torch.cuda.graph()`` capture context.
    NrB   z6resolve_pending_annotations: no graph handle availabler   r.   é    c              3   ó6   K  — | ]  \  }\  }}}||||f–— Œ y ­wr7   r   )Ú.0ÚiÚannÚstartÚends        r   ú	<genexpr>z.resolve_pending_annotations.<locals>.<genexpr>  s,   è ø€ ò á(�AÑ(˜˜U Cð �e˜S !Ô$ñùs   ‚c                 ó"   — | d   | d    | d    fS )Né   é   é   r   )Úss    r   ú<lambda>z-resolve_pending_annotations.<locals>.<lambda>  s   € ˜1˜Q™4 ! A¡$ ¨¨1©¨Ð.€ r   )ÚkeyéÿÿÿÿrX   z:resolve_pending_annotations: toolsId unavailable, abortingÚnamez"resolve_pending_annotations failed)!r<   r=   r   rE   rF   rG   rH   rI   r,   r   ÚwarningÚclearr3   r   r0   r    r>   r;   ÚsortedÚ	enumerateÚrangeÚpopÚlenrJ   ÚcudaGraphNodeGetTyper4   ÚreversedrD   ÚdictÚitemsÚ
setdefaultr   Ú	exception)r!   r(   r2   ÚnodesÚ	first_tidÚannotatableÚsorted_scopesÚ	scope_ptrÚactive_stackrR   rS   Ú
_start_idxÚend_idxÚ_idxr   Ú	node_typer   Úmergedr1   ÚakÚavs                        r   Úresolve_pending_annotationsrz   Ô   s[  € õ ØˆØô ×'Ñ'Ü—:‘:×,Ñ,Ó.×:Ñ:ô€Fô ˜vÓ&€EØ€}ÜˆØ€}Ü�‰ÐOÔPÜ×ÑÔØðZÜ˜eÓ$ˆØ�!Š8Ü×!Ñ!Ô#Ø!ˆNØôh 	×ÑÔØ‰ôg *Ü×+Ñ+Ø ôó
‰
ˆˆsð �Š7Ü% e¨A¡hÓ/ˆIÙ:C i°2¢oÈÐ"ä,Ó.ˆô ñä,5´oÓ,Fôñ /ô
ˆð ˆ	Ø.0ˆä�s“ó 0	=ˆAá <°Ñ#3°AÑ#6¸!Ò#;Ø× Ñ Ô"ñ  <°Ñ#3°AÑ#6¸!Ó#;ð œc -Ó0Ò0°]À9Ñ5MÈaÑ5PÐTUÒ5UØ1>¸yÑ1IÑ.��Z ¨$Ø˜Q’;Ø ×'Ñ'¨°#¨Ô7Ø˜Q‘�	ð	 œc -Ó0Ò0°]À9Ñ5MÈaÑ5PÐTUÓ5Uñ  Øà˜‘8ˆDÜ,Ü×2Ñ2ØóóˆIð
  Ñ+Øä$ TÓ*ˆHØÐÜ—‘ØPôô  ×%Ñ%Ô'Ø!%�Øô* 	×ÑÔØ‰ô) �<Ó  AÒ%Ü# HÑ-×4Ñ4°\À!±_ÀQÑ5GÖHð *,�Ü& |Ó4ò 7‘F�A�sÜ! #¤tÔ,Ø&)§i¡i£kò 6™F˜B Ø"×-Ñ-¨b°"Õ5ñ6ð ×)Ñ)¨&°#Õ6ð7ô $ HÑ-×4Ñ4°VÖ<ña0	=ôh 	×ÑÔØ‰øô	 ò ?Ü×ÑÐ=Ö>ð?ûô 	×ÑÔØ‰úsF   Â&L ÃB(L Å-AL ÇA$L ÉB+L Ë-L) ÌL&Ì#L) Ì%L&Ì&L) Ì)MÚtorch_cuda_graphc                 ó¼  — t         syt        j                  | j                  «       ¬«      }t	        t        j
                  |«      «      }t        }i }t         j                  «       D ]K  \  }}|dz	  }|�||k7  r|||<   Œ|dz  }|dz  |z  }	|	|v r||	   j                  |«       Œ>t        |«      ||	<   ŒM t         j                  «        t         j                  |«       y)a\  Remap annotation keys from capture graph ID to exec graph ID.

    During capture, toolsId encodes the capture graph's ID in the upper
    32 bits. After instantiation, the profiler uses the exec graph's ID.
    This function rewrites the keys so annotations match the trace.

    Must be called after the ``torch.cuda.graph()`` context exits.
    NrB   rO   l   ÿÿ )r4   r   ÚcudaGraphExec_tÚraw_cuda_graph_execr   ÚcudaGraphExecGetIdr>   rj   ÚextendÚlistra   Úupdate)
r{   Úexec_handleÚexec_graph_idÚcapture_graph_idÚremappedr   Úann_listÚgraph_idÚnode_idÚnew_tools_ids
             r   Úremap_to_exec_graphr‹   I  sï   € õ Øä×/Ñ/Ø#×7Ñ7Ó9ô€Kô )Ü×(Ñ(Øó	
ó€Mô .ÐØ%'€HÜ1×7Ñ7Ó9ò 4Ñˆ�(Ø˜r‘>ˆØÐ'¨HÐ8HÒ,Hà!)ˆH�XÑØØ˜ZÑ'ˆØ%¨Ñ+¨wÑ6ˆØ˜8Ñ#Ø�\Ñ"×)Ñ)¨(Õ3ä%)¨(£^ˆH�\Ò"ð4ô ×ÑÔÜ×Ñ˜xÕ(r   c                  ó   — t         S )zBReturn the current kernel annotation map (toolsId -> annotations).)r4   r   r   r   Úget_kernel_annotationsr�   t  s   € äÐr   c                  óX   — t         j                  «        t        j                  «        day)z9Clear all recorded kernel annotations and pending scopes.N)r4   ra   r<   r=   r   r   r   Úclear_kernel_annotationsr�   y  s!   € ô ×ÑÔÜ×ÑÔØ�Nr   é<   Ú_stream_id_counterÚ_stream_id_mapc                 óh   — | j                   }|t        vrt        t        |<   t        dz  at        |   S )z;Return a small, stable stream ID for the given CUDA stream.rX   )rI   r’   r‘   )r!   r]   s     r   Ú_get_stream_idr”   ˆ  s7   € ð ×
Ñ
€CØ
”.Ñ Ü0Œ�sÑÜ˜aÑÐÜ˜#ÑÐr   Úpg_keyc                 óP   — | t         vrt        t         | <   t        dz  at         |    S )z:Return a unique stream ID for the given process group key.rX   )r’   r‘   )r•   s    r   Úget_stream_for_pgr—   ’  s,   € ð ”^Ñ#Ü!3Œ�vÑÜ˜aÑÐÜ˜&Ñ!Ð!r   c              #   óR  K  — t         s-t        j                  j                  | «      5  d–— ddd«       y| j                  t        j                  j                  «       j                  k(  rt        |«      5  d–— ddd«       yt        |t        «      rd|i}t        |t        «      rt        | «      |d<   t        j                  j                  | «      5  t        |«      5  d–— ddd«       ddd«       y# 1 sw Y   yxY w# 1 sw Y   yxY w# 1 sw Y   Œ*xY w# 1 sw Y   yxY w­w)uT  Switch to stream, inject its ID into annotation, and mark kernels.

    If *stream* is already the current stream, no stream switch or stream ID
    injection happens â€” the kernels stay on whatever stream is active (which
    keeps the trace faithful when e.g. FSDP uses the current stream for
    copy-in instead of a separate one).
    NrA   r!   )r   rF   rG   r!   rI   rH   rM   rD   rA   ri   r”   )r!   r?   s     r   Úmark_streamr™   ›  sö   è ø€ õ  Ü�Z‰Z×Ñ˜vÓ&ñ 	Û÷	àØ×ÑœUŸZ™Z×6Ñ6Ó8×DÑDÒDÜ˜*Ó%ñ 	Û÷	ð 	ô �j¤#Ô&Ø Ð,ˆJÜ�j¤$Ô'Ü#1°&Ó#9ˆJ�xÑ Ü�Z‰Z×Ñ˜vÓ&ñ 	Ü˜jÓ)ñ Û÷÷	ð 	÷	àú÷	ð 	ú÷ð ú÷	ð 	üse   ‚&D'¨C7­A	D'Á6DÁ;AD'ÃDÃ!DÃ&DÃ.	D'Ã7D Ã<D'ÄDÄD'ÄD	ÄDÄD$Ä D')r   N)6Ú__doc__Úcollectionsr   Ú
contextlibr   Úloggingr   Útypingr   rF   Útorch.cuda._utilsr   r   Úcuda.bindingsr	   r   ÚImportErrorÚ__name__r   r
   ÚboolÚ__annotations__r   r   r   r   Úintr    r,   r3   r�   r4   r5   Úsetr;   r<   Útupler=   r>   rA   ri   rM   rz   rG   Ú	CUDAGraphr‹   r�   r�   r‘   r’   ÚStreamr”   r—   r™   r   r   r   ú<module>rª      s1  ðò"õH $Ý %Ý Ý ã ß Fðõñ 
�8Ó	€ð
 $(Ð �T˜D‘[Ó 'ð #Ð �dÓ "ó ó!ð $ó ð˜ð   d¡
ó ð4˜sð  só ð˜3ð  3ó ñ 4?¸tÓ3DÐ �[  d¨3¡i Ñ0Ó Dð '+Ð �C˜‘H˜t‘OÓ *ð  C¡ó ð /1€��e˜C  c˜MÑ*Ñ+Ó 0ð €�Ó ð &*Ð ˜˜d™
Ó )ð ð)E˜S 4¨¨S¨¡>Ñ1ò )Eó ð)EóXrðj()¨%¯*©*×*>Ñ*>ð ()À4ó ()ðV  S¨$¨s©) ^Ñ 4ó ó
ð Ð �CÓ Ø!#€��S˜#�X‘Ó #ð˜5Ÿ:™:×,Ñ,ð °ó ð"˜cð " có "ð ð˜Ÿ
™
×)Ñ)ð °s¸TÀ#ÀsÀ(¹^Ñ7Kò ó ñøðU ò ØƒMðús   ©E# Å#E.Å-E.