+
    –°³js£  ã                  ó  a € 0 t $ R t^ RIHt ^ RIt^ RIt^ RIt^ RIH	t	 ^ RI
Ht ^ RIHt ^ RIHtHtHtHt ]'       d	   ^ RIHtHt ^ RIt^ RIHtHtHt  ^ R	IHtHt ]! ]!4      t"]#]]$],          3,          t%R
]&R&   ]'](])](,          3,          t*R
]&R&   Rs+R]&R&   Rs,R]&R&   Rs-R]&R&   R R lt.R R lt/R R lt0R R lt1R R lt2R R lt3R  R! lt4R" R# lt5R$ R% lt6R& R' lt7R(RR)R/R* R+ llt8]	! ]$4      t9R,]&R-&   Rs:R.]&R/&   R0 R1 lt;Rs<R.]&R2&   R3 R4 lt=. t>R5]&R6&   R7t?R8 R9 lt@R: R; ltAR< R= ltB]C! 4       tDR>]&R?&   ^ sER@]&RA&    ! RB RC]4      tFRD RE ltGRF RG ltH ! RH RI]P’                  4      tJ]C! 4       tKR>]&RJ&   RK RL ltLRM RN ltM]RORP/RQ RR ll4       tNRS RT ltORU RV ltPRW RX ltQRY RZ ltRR[ R\ ltSR] R^ ltTR_ R` ltURa Rb ltV^<sWR@]&Rc&   / tXRd]&Re&   Rf Rg ltYRh Ri ltZ]Rj Rk l4       t[R#   ]  d	    RtRt EL i ; i)la<  Annotate CUDA graph kernel nodes during capture.

During CUDA graph capture, ``mark_kernels`` records the current capture
frontier and the direct dependents already attached to that frontier.
On scope exit it walks only the newly added dependent edges to find the
nodes created within the scope. Each kernel, memcpy, or memset node found
is annotated by its ``toolsId`` so it can later be matched to profiler
trace events.

``mark_kernels`` now snapshots capture state from whatever stream is
current on scope entry, so that stream must already be participating in
the capture. ``mark_stream`` handles this by starting ``mark_kernels``
before switching to the target stream.

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.

Annotation recording is enabled per capture via ``torch.cuda.graph``'s
``enable_annotations`` argument, which also resolves and remaps the recorded
annotations to the exec graph automatically on context exit.

Usage during capture::

    from torch.cuda._graph_annotations import mark_kernels, get_kernel_annotations

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

    annotations = get_kernel_annotations()

When you need to drive this outside the context manager's automatic path,
``resolve_and_remap(graph)`` is shorthand for ``resolve_pending_annotations()``
followed by ``remap_to_exec_graph(graph)``; call those directly for finer
control (e.g. resolving once before remapping several graphs).
)ÚannotationsN)Údefaultdict)Úcontextmanager)Ú	getLogger)ÚAnyÚ
NamedTupleÚTYPE_CHECKINGÚ	TypeAlias)ÚIterableÚMapping)Ú_check_cuda_bindingsÚ_check_cuda_bindings_driverÚ_HAS_CUDA_BINDINGS)ÚdriverÚruntimer	   Ú_CaptureStateÚ_ExistingDirectDependentszbool | NoneÚ_tools_id_availableFÚboolÚ_annotations_enabledz
int | NoneÚ_capture_root_graph_idc               ó    € V ^8„  d   QhRRRR/# )é   Úenabledr   ÚreturnÚNone© )Úformats   "Ú^/home/luca/screen-checking/.venv/lib/python3.14/site-packages/torch/cuda/_graph_annotations.pyÚ__annotate__r   f   s   € ÷ &ñ & dð &¨tñ &ó    c                ó"   € V s V '       g   RsR# R# )z}Set whether annotation recording is active. Used by ``torch.cuda.graph``
to scope annotations to a capture; not a public API.N)r   r   )r   s   &r   Ú_set_annotations_enabledr"   f   s   € ð #ÐßØ!%Òñ r    c               ó    € V ^8„  d   QhRRRR/# )r   Úgraphr   r   Úintr   )r   s   "r   r   r   o   s   € ÷ ñ �Sð ˜Sñ r    c                ó@   € \        \        P                  ! V 4      4      # )zäThe driver's unique id for a ``cudaGraph_t``.

Identifies a graph across its whole lifetime, unlike the handle itself: that is a
pointer, so a graph created after another is destroyed can reuse the value and
compare equal to it.)r   Ú_cuda_runtimeÚcudaGraphGetId)r$   s   &r   Ú	_graph_idr)   o   s   € ô  Ü×$Ò$ UÓ+óð r    c               ó    € V ^8„  d   QhRRRR/# )r   Ústreamr   r   r   r   )r   s   "r   r   r   z   s   € ÷ 5ñ 5 Sð 5¨Tñ 5r    c                óÎ   € Rs \        '       d   \        4       '       d   R# \        P                  ! V P
                  R7      p\        V4      pVe   \        V^ ,          4      s R# R# )zÚRecord the top-level capture graph of the capture just begun on ``stream``.

Called by ``torch.cuda.graph`` right after ``capture_begin``, while ``stream`` is
still capturing into the top-level graph. Not a public API.N©Ú
init_value)r   r   Ú_is_tools_id_unavailabler'   ÚcudaStream_tÚcuda_streamÚ_get_capture_stater)   )r+   Ústream_handleÚstates   &  r   Úmaybe_stamp_capture_rootr5   z   s[   € ð "ÐßÓÔ#;×#=Ò#=ÙÜ!×.Ò.Ø×%Ñ%ô€Mô ˜}Ó-€EØÒÜ!*¨5°­8Ó!4Òñ r    c               ó   € V ^8„  d   QhRR/# ©r   r   r   r   )r   s   "r   r   r   ‹   s   € ÷ !ñ !˜ñ !r    c                 ó:  € \        \        R4      '       g8   \        P                  P	                  R4      p \
        P                  RV 4       R# \        P                  ! ^ 4      vrV\        P                  P                  8X  d   \
        P                  R4       R# R# )zÖProbe whether cudaGraphNodeGetToolsId is supported by the driver.

Calls with a null node: cudaErrorInvalidValue means the API exists
in the driver (good), cudaErrorCallRequiresNewerDriver means it
does not (bad).
ÚcudaGraphNodeGetToolsIdzcuda-bindingszãcudaGraphNodeGetToolsId API not found in cuda-bindings. Current version: %s, required: >= 13.1.0. CUDA graph kernel annotations will be disabled. To enable annotations, upgrade cuda-bindings: pip install --upgrade cuda-bindingsFzvcudaGraphNodeGetToolsId requires a newer driver (missing cuda-compat?); CUDA graph kernel annotations will be disabledT)Úhasattrr'   Ú	importlibÚmetadataÚversionÚloggerÚwarningr9   ÚcudaError_tÚ cudaErrorCallRequiresNewerDriverÚinfo)Úcuda_bindings_versionÚerrÚ_s      r   Ú_probe_tools_idrF   ‹   sŽ   € ô ”=Ð";×<Ò<ä )× 2Ñ 2× :Ñ :¸?Ó KÐä�‰ð2ð
 "ô	
ñ Ü×3Ò3Ø	ó€G€Cð 	Ü×$Ñ$×EÑEô	Fô 	�‰ð=ô	
ñ
 Ùr    c               ó   € V ^8„  d   QhRR/# r7   r   )r   s   "r   r   r   ¯   s   € ÷ #ñ # $ñ #r    c                 ón   € \         '       g   R# \        e   \        '       * # \        4       s\        '       * # )z5Return True if cudaGraphNodeGetToolsId is not usable.T)r   r   rF   r   r    r   r/   r/   ¯   s.   € ÷ ÓÙÜÒ&Ü&Ô&Ð&Ü)Ó+ÐÜ"Ô"Ð"r    c               ó   € V ^8„  d   QhRR/# r7   r   )r   s   "r   r   r   º   s   € ÷ Hñ H�dñ Hr    c                 ól   € \         P                  P                  4       ;'       d    \        4       '       * # )aŸ  is_available() -> bool

Return whether CUDA graph annotation recording is supported.

Requires a CUDA device, the ``cuda-bindings`` package, and a driver
that supports ``cudaGraphNodeGetToolsId`` (CUDA >= 13.1 or an
equivalent cuda-compat package). When this returns ``False``,
:func:`mark_kernels` is a silent no-op and no annotations are
recorded.

The first call may probe the CUDA driver; the result is cached.
)ÚtorchÚcudaÚis_availabler/   r   r    r   rM   rM   º   s&   € ô �:‰:×"Ñ"Ó$×GÐGÔ-EÓ-GÔ)GÐGr    c               ó    € V ^8„  d   QhRRRR/# )r   r+   r   r   z_CaptureState | Noner   )r   s   "r   r   r   Ê   s   € ÷ *ñ *˜sð *Ð';ñ *r    c                óª   € \        \        P                  ! V 4      4      w  rr4rVV\        P                  P                  8w  d   R# V\        VRV 4      3# )zBReturn ``(graph, frontier)`` for an active capture, else ``None``.N)r   r'   ÚcudaStreamGetCaptureInfoÚcudaStreamCaptureStatusÚcudaStreamCaptureStatusActiveÚlist)r+   ÚstatusÚ_idr$   Ú_depsÚ
_edge_dataÚ	_num_depss   &      r   r2   r2   Ê   sZ   € ä7KÜ×.Ò.Øó	
ó8Ñ4€F�˜zð 	Ü×0Ñ0×NÑNô	Oñ Ø”$�u˜Z˜iÐ(Ó)Ð)Ð)r    c               ó    € V ^8„  d   QhRRRR/# )r   r$   r   r   ú	list[Any]r   )r   s   "r   r   r   Ù   s   € ÷ #ñ #˜3ð # 9ñ #r    c                ó¶   € \        \        P                  ! V 4      4      w  rV^ 8X  d   . # \        \        P                  ! WR7      4      w  r2\        VRV 4      # )z,Return the current root nodes for the graph.)ÚpNumRootNodesN)r   r'   ÚcudaGraphGetRootNodesrS   )r$   rE   Ú	num_rootsÚrootss   &   r   Ú_get_root_nodesr`   Ù   s_   € ä'Ü×+Ò+Øó	
ó�L€Að
 �A„~Øˆ	Ü+Ü×+Ò+Øô	
óÑ€Eô
 ��j�yÐ!Ó"Ð"r    c               ó    € V ^8„  d   QhRRRR/# )r   Únoder   r   rZ   r   )r   s   "r   r   r   ê   s   € ÷ -ñ -˜sð - yñ -r    c                óº   € \        \        P                  ! V 4      4      w   rV^ 8X  d   . # \        \        P                  ! WR7      4      w  r4p\        VRV 4      # )z-Return the direct dependents of a graph node.)ÚpNumDependentNodesN)r   r'   ÚcudaGraphNodeGetDependentNodesrS   )rb   rE   Únum_dependentsÚ
dependentsrW   s   &    r   Ú_get_dependent_nodesrh   ê   se   € ä/Ü×4Ò4Øó	
óÑ€A€qð
 ˜ÔØˆ	Ü-AÜ×4Ò4Øô	
ó.Ñ*€J˜Nô
 �
˜?˜NÐ+Ó,Ð,r    c               ó    € V ^8„  d   QhRRRR/# )r   rb   r   r   r   )r   s   "r   r   r   û   s   € ÷ 	ñ 	˜ð 	 ñ 	r    c                ó@   € \        \        P                  ! V 4      4      # )a  Return graph node type without tripping runtime bugs on newer node kinds.

The runtime ``cudaGraphNodeGetType`` can return ``cudaErrorUnknown`` (999)
for valid nodes whose driver type is ``CU_GRAPH_NODE_TYPE_BATCH_MEM_OP``.
Query via the driver API instead.
)r   Ú_cuda_driverÚcuGraphNodeGetType)rb   s   &r   Ú_get_node_typerm   û   s   € ô 'Ü×'Ò'¨Ó-óð r    Úexisting_direct_dependentsÚinclude_start_nodesc               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   Ústart_nodesrZ   rn   z _ExistingDirectDependents | Nonero   r   r   zdict[int, Any]r   )r   s   "r   r   r     s3   € ÷ !ñ !Øð!ð !Að!ð ð	!ð
 ñ!r    c               óÎ  € T;'       g    / pV  Uu0 uF  p\        V4      kK  	  pp/ p\        V 4      pV'       d   V  F  pW5\        V4      &   K  	  V'       d‡   VP                  4       pVP                  \        V4      \	        4       4      p\        V4       FB  p\        V4      p	W—9   g   W”9   d   K  VP                  V	4       W…V	&   VP                  V4       KD  	  KŽ  V# u upi )a  Walk dependent edges starting at ``start_nodes``.

``existing_direct_dependents`` maps each node in ``start_nodes`` to
the direct dependent node keys that were already present at scope
entry. Those edges are skipped so the traversal only follows nodes
added after scope entry.
)r%   rS   ÚpopÚgetÚsetrh   ÚaddÚappend)
rq   rn   ro   rb   ÚseenÚdescendantsÚstackÚold_dependentsÚ	dependentÚdependent_keys
   &$$       r   Ú_collect_descendantsr~     sÍ   € ð "<×!AÐ!A¸rÐÙ"-Ó.¡+˜$ŒC�ŽI¡+€DÐ.Ø"$€KÜ�Ó€EçÛˆDØ%)œ˜D›	Ó"ñ  ÷ Ø�y‰y‹{ˆØ3×7Ñ7¼¸D»	Ä3Ã5ÓIˆÜ-¨dÖ3ˆIÜ 	›NˆMØÔ.°-Ô2GÙØ�H‰H�]Ô#Ø)2˜Ñ&Ø�L‰L˜Ö#ó 4ð Ðùò' /s   ‘C"zdefaultdict[int, list[Any]]Ú_kernel_annotationszset[Any] | NoneÚ_ANNOTATABLE_TYPESc               ó   € V ^8„  d   QhRR/# ©r   r   zset[Any]r   )r   s   "r   r   r   6  s   € ÷ ñ  ñ r    c                 óÜ   € \         f`   \        P                  p V P                  V P                  V P
                  V P                  V P                  V P                  V P                  0s \         # ©N)
r€   rk   ÚCUgraphNodeTypeÚCU_GRAPH_NODE_TYPE_KERNELÚCU_GRAPH_NODE_TYPE_MEMCPYÚCU_GRAPH_NODE_TYPE_MEMSETÚCU_GRAPH_NODE_TYPE_BATCH_MEM_OPÚCU_GRAPH_NODE_TYPE_EVENT_RECORDÚCU_GRAPH_NODE_TYPE_WAIT_EVENTÚCU_GRAPH_NODE_TYPE_HOST©Ú
node_typess    r   Ú_get_annotatable_typesr�   6  sb   € äÒ!Ü!×1Ñ1ˆ
à×0Ñ0Ø×0Ñ0Ø×0Ñ0Ø×6Ñ6Ø×6Ñ6Ø×4Ñ4Ø×.Ñ.ð
Ðô Ðr    Ú_NESTED_GRAPH_TYPESc               ó   € V ^8„  d   QhRR/# r‚   r   )r   s   "r   r   r   O  s   € ÷ ñ  ñ r    c                 ón   € \         f)   \        P                  p V P                  V P                  0s \         # r„   )r�   rk   r…   ÚCU_GRAPH_NODE_TYPE_GRAPHÚCU_GRAPH_NODE_TYPE_CONDITIONALr�   s    r   Ú_get_nested_graph_typesr•   O  s5   € äÒ"Ü!×1Ñ1ˆ
à×/Ñ/Ø×5Ñ5ð
Ðô Ðr    zlist[tuple[Any, list[int]]]Ú_pending_scopesÚcuda_graph_annotation_regionc               ó   € V ^8„  d   QhRR/# )r   r   údict[str, Any] | Noner   )r   s   "r   r   r   ‚  s   € ÷ ñ Ð.ñ r    c                 óž   € \         P                  P                  \        4      '       d$   \         P                  P	                  \        4      # R # r„   )rK   Ú_CÚ_is_key_in_tlsÚ_REGION_TLS_KEYÚ_get_obj_in_tlsr   r    r   Ú_current_regionrŸ   ‚  s/   € Ü‡x�x×Ñœ×/Ò/Ü�x‰x×'Ñ'¬Ó8Ð8Ùr    c               ó    € V ^8„  d   QhRRRR/# )r   Ú	collapsedúdict[str, Any]r   r™   r   )r   s   "r   r   r   ˆ  s   € ÷ ñ ˜^ð Ð0Eñ r    c                ób   € \        4       p\        P                  P                  \        V 4       V# )zEInstall ``collapsed`` as the current region; return the previous one.)rŸ   rK   r›   Ú_stash_obj_in_tlsr�   )r¡   Úprevs   & r   Ú_enter_regionr¦   ˆ  s#   € äÓ€DÜ	‡H�H×Ñœ°	Ô:Ø€Kr    c               ó    € V ^8„  d   QhRRRR/# )r   r¥   r™   r   r   r   )r   s   "r   r   r   �  s   € ÷ :ñ :Ð,ð :°ñ :r    c                ó    € V f&   \         P                  P                  \        4       R # \         P                  P	                  \        V 4       R # r„   )rK   r›   Ú_remove_obj_from_tlsr�   r¤   )r¥   s   &r   Ú_exit_regionrª   �  s-   € Ø‚|Ü�‰×%Ñ%¤oÖ6ä�‰×"Ñ"¤?°DÖ9r    r   Ú_HOOKED_KEYr%   Ú_annotation_generationc                  óD   € ] tR tRt$ RtR]R&   R]R&   R]R&   R	]R
&   RtR# )Ú_KernelScopei£  zGCapture-frontier snapshot taken at scope entry, consumed at scope exit.r   r$   rZ   Úfrontierzset[int] | NoneÚentry_root_keysr   Úentry_direct_dependentsr   N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú__annotations__Ú__static_attributes__r   r    r   r®   r®   £  s   ‡ ÙQàƒJØÓØ$Ó$Ø6×6r    r®   c               ó   € V ^8„  d   QhRR/# )r   r   z_KernelScope | Noner   )r   s   "r   r   r   ¬  s   € ÷ Sñ SÐ0ñ Sr    c                 ó¶  € \         P                  ! \        P                  P	                  4       P
                  R7      p \        V 4      pVf   R# Vw  r#RpV UUu/ uF1  p\        V4      \        V4       Uu0 uF  p\        V4      kK  	  upbK3  	  pppV'       g$   \        V4       Uu0 uF  p\        V4      kK  	  pp\        W#WG4      # u upi u uppi u upi )zJSnapshot the current stream's capture frontier; ``None`` if not capturing.r-   N)r'   r0   rK   rL   Úcurrent_streamr1   r2   r%   rh   r`   r®   )r+   Úcapture_stater$   r¯   r°   rb   Údepr±   s           r   Ú_begin_kernel_scoper¾   ¬  sÌ   € ä×'Ò'Ü—:‘:×,Ñ,Ó.×:Ñ:ô€Fô ' vÓ.€MØÒÙØ#�O€Eà'+€OáPXôÙPXÈŒˆD‹	Ô(<¸TÔ(BÓCÑ(B ”C˜–HÑ(BÑCÒCÑPXð ñ ÷ Ü1@ÀÔ1GÓHÑ1G¨œ3˜tž9Ñ1GˆÐHÜ˜¨ÓRÐRùò	 Dùóùò Is   ÁCÁ6CÂ
CÂ)CÃCc               ó    € V ^8„  d   QhRRRR/# )r   Úscoper®   r   z	list[int]r   )r   s   "r   r   r   ¿  s   € ÷ *ñ *˜\ð *¨iñ *r    c                óÂ  € V P                   '       d#   \        V P                   V P                  R7      pM_\        V P                  4       Uu. uF3  p\        V4      V P                  ;'       g    \        4       9  g   K1  VNK5  	  pp\        VRR7      p\        4       p\        4       p\        4       p. pVP                  4        Fe  p\        V4      pW…9   d   VP                  VP                  4       W„9  d   K7  VP                  \        \         P"                  ! V4      4      4       Kg  	  V'       d&   \$        P&                  ! R\)        V4       R2^R7       V# u upi )zEWalk nodes captured since ``scope`` was begun; return their toolsIds.)rn   T)ro   z"mark_kernels: this scope contains zy nodes; the work inside them is in a separate cudaGraph_t that this walk does not descend into, so it is left unannotated©Ú
stacklevel)r¯   r~   r±   r`   r$   r%   r°   ru   r�   r•   Úvaluesrm   rv   Únamerw   r   r'   r9   ÚwarningsÚwarnÚsorted)	rÀ   Úscope_nodesrb   Ú	new_rootsÚannotatableÚnestedÚnested_seenÚ	tools_idsÚ	node_types	   &        r   Ú_end_kernel_scoperÐ   ¿  s9  € à‡~‡~€~Ü*Ø�N‰NØ',×'DÑ'Dô
‰ô (¨¯©Ô4ó
á4�Ü�4‹y ×!6Ñ!6×!?Ð!?¼#»%Ñ@÷ ˆDÙ4ð 	ð 
ô
 +¨9È$ÔOˆä(Ó*€KÜ$Ó&€FÜ›E€KØ€IØ×"Ñ"Ö$ˆÜ" 4Ó(ˆ	ØÔØ�O‰O˜IŸN™NÔ+ØÔ'ÙØ×ÑÜ Ü×5Ò5Øóóö	
ñ %÷ ô 	�ŠØ0´¸Ó1DÐ0Eð F.ð .ð õ		
ð ÐùòE
s   Á!EÁ.EÁ?Ec                  ó&   € ] tR tRtRtR R ltRtR# )Ú_BracketStateiì  a  Per-thread stack of open backward brackets for one hook pair.

Thread-local so concurrent executions of a retained node (separate
graph tasks on different engine threads) cannot interleave each
other's scope snapshots; within one thread pre/post pair up LIFO.

If the node throws, its posthook never runs (the engine's
call_function has no try/finally around fn) and the prehook's entry
is left on the stack. That is harmless. Say a retained node runs
three times on one thread and the second run throws:

    run 1: prehook push [e1]; posthook pops e1     -> []
    run 2: prehook push [e2]; node throws, no pop  -> [e2]
    run 3: prehook push [e2, e3]; posthook pops e3 -> [e2]

Pops always take the top, so the leaked e2 sits below all later
entries and every subsequent run still pops its own. The only loss
is e2 itself: that run's kernels go unrecorded, which is moot since
its backward failed. (The region/creation-hook TLS the prehook set
is not leaked -- the engine task's ThreadLocalStateGuard restores
those on unwind.)
c               ó   € V ^8„  d   QhRR/# ©r   r   r   r   )r   s   "r   r   Ú_BracketState.__annotate__  s   € ÷ #ñ #˜$ñ #r    c                	ó   € . V n         R # r„   ©rz   )Úselfs   &r   Ú__init__Ú_BracketState.__init__  s	   € à "ˆŽ
r    r×   N)r²   r³   r´   rµ   r¶   rÙ   r¸   r   r    r   rÒ   rÒ   ì  s   † ñ÷.#ñ #r    rÒ   Ú_SKIPPEDc               ó$   € V ^8„  d   QhRRRRRR/# )r   rb   r   Ú
generationr%   r   r   r   )r   s   "r   r   r     s!   € ÷ 5ñ 5˜cð 5¨sð 5°tñ 5r    c                óþ   € \        V \        P                  P                  P                  4      '       d   R# \
        V P                  9   d   R# \        4       pVf   R# RV P                  \
        &   \        WV4       R# )aU  Node creation hook: freeze the current region into ``node``'s bracket.

Reads the region TLS slot and, if a region is open, installs the node's
single backward hook pair closing over that snapshot. Every backward-
annotating ``mark_kernels`` scope pushes one of these (and so does an
executing hooked node, to cover nodes created during its backward), so
a node created under nested scopes sees several identical firings; the
``node.metadata`` marker makes only the first attach.

AccumulateGrad is always excluded: a leaf's node is created once and
cached (possibly during warmup), so which scope would own it is an
accident of first use, and its work (the ``.grad`` accumulation)
belongs to the leaf rather than to any forward region. If accumulation
ever needs annotation it should get a dedicated leaf-accumulation
region, not first-use assignment.
NT)	Ú
isinstancerK   r›   Ú
_functionsÚAccumulateGradr«   r<   rŸ   Ú_attach_backward_hooks)rb   rÝ   Úfrozens   && r   Ú_freeze_region_hookrä     s[   € ô" �$œŸ™×+Ñ+×:Ñ:×;Ò;ÙÜ�d—m‘mÔ#ÙÜÓ€FØ‚~ÙØ!%€D‡M�M”+ÑÜ˜4¨Ö4r    c               ó(   € V ^8„  d   QhRRRRRRRR/# )	r   rb   r   rã   r¢   rÝ   r%   r   r   r   )r   s   "r   r   r   +  s/   € ÷ D!ñ D! ð D!¨nð D!È#ð D!ÐRVñ D!r    c                ó¢   aaaa€ \        4       oR V3R lloR VVVV3R llpR V3R llpV P                  V4       V P                  V4       R# )aÝ  Register one pre/post hook pair bracketing ``node``'s backward execution.

``frozen`` is the region that was current when the node was created:
the annotations of every scope then open, already collapsed inner-wins.
The pair brackets the node's execution the same way ``mark_kernels``
brackets forward work: snapshot the capture frontier before, collect
the new nodes after. It runs on the autograd engine thread executing
the node, which during a whole-graph capture participates in the
capture; when backward runs outside a capture the prehook sees no
active capture and the pair is a no-op.

Executing the node is semantically re-entering its frozen region, so
the prehook merges ``frozen`` over the live region (a ``mark_kernels``
enclosing the whole ``backward()`` call, if any) and installs the
result while the node runs. That gives nodes created during its
backward (``create_graph=True``, checkpoint recomputation) the forward
region's ownership -- a creation hook is pushed alongside so they get
hooked even when this backward runs eagerly and no scope's hook is
live -- and it puts a ``mark_kernels`` opened inside the execution
dynamically inner, so it outranks ``frozen``, which outranks the
enclosing scope. The posthook records the merged region once; scope
completion order then yields exactly that precedence at resolve.

The pops are exception-safe without a finally: each engine task runs
under an ``at::ThreadLocalStateGuard`` that restores both the
creation-hook TLS and the region slot even when the node throws.

``generation`` is the annotation generation the owning scope was opened
under; the bracket only records (and only propagates to created nodes)
while it is current, so ``clear_kernel_annotations`` makes stale hooks
inert.
c               ó    € V ^8„  d   QhRRRR/# )r   Úchildr   r   r   r   )r   s   "r   r   Ú,_attach_backward_hooks.<locals>.__annotate__N  s   € ÷ /ñ /˜Sð / Tñ /r    c                ó    <€ \        V S4       R # r„   ©rä   )rè   rÝ   s   &€r   Úcreation_hookÚ-_attach_backward_hooks.<locals>.creation_hookN  s   ø€ Ü˜E :Ö.r    c               ó    € V ^8„  d   QhRRRR/# )r   Ú_grad_outputsr   r   r   r   )r   s   "r   r   ré   Q  s   € ÷ 2ñ 2˜sð 2 tñ 2r    c                ó‚  <€ S\         8w  g   \        4       '       d"   SP                  P                  \        4       R # / \        4       ;'       g    / CSCp\        V4      p\        P                  P                  P                  S4       \        '       d   \        4       MR pSP                  P                  W2V34       R # r„   )r¬   r/   rz   rw   rÛ   rŸ   r¦   rK   r›   Ú	_autogradÚ_push_node_creation_hookr   r¾   )rï   Úmergedr¥   rÀ   rì   rã   rÝ   r4   s   &   €€€€r   ÚprehookÚ'_attach_backward_hooks.<locals>.prehookQ  s�   ø€ ØÔ/Ô/Ô3K×3MÒ3MØ�K‰K×ÑœxÔ(Ùð 9”_Ó&×,Ð,¨"Ð8°Ð8ˆÜ˜VÓ$ˆÜ�‰×Ñ×3Ñ3°MÔBß)=Ó)=Ô#Ô%À4ˆØ�‰×Ñ˜E¨Ð0Ö1r    c               ó$   € V ^8„  d   QhRRRRRR/# )r   Ú_grad_inputsr   rï   r   r   r   )r   s   "r   r   ré   ^  s!   € ÷ 8ñ 8˜sð 8°3ð 8¸4ñ 8r    c                ó^  <€ SP                   '       g   R # SP                   P                  4       pV\        J d   R # Vw  r4p\        P                  P
                  P                  4        \        V4       Vf   R # \        V4      pV'       d!   / VCRR/Cp\        P                  Wv34       R # R # )NÚautograd_phaseÚbackward)rz   rs   rÛ   rK   r›   rñ   Ú_pop_node_creation_hookrª   rÐ   r–   rw   )	r÷   rï   ÚentryrÀ   r¥   ró   rÎ   Útaggedr4   s	   &&      €r   ÚposthookÚ(_attach_backward_hooks.<locals>.posthook^  s�   ø€ Ø�{�{ˆ{ÙØ—‘—‘Ó!ˆØ”HÓÙØ#Ñˆ�VÜ�‰×Ñ×2Ñ2Ô4Ü�TÔØŠ=ÙÜ% eÓ,ˆ	ßØ=˜Ð=Ð 0°*Ñ=ˆFÜ×"Ñ" FÐ#6Ö7ñ r    N)rÒ   Úregister_prehookÚregister_hook)rb   rã   rÝ   rô   rþ   rì   r4   s   &ff  @@r   râ   râ   +  sI   û€ ôB ‹O€E÷/ð /÷2ó 2÷8ð 8ð  	×Ñ˜'Ô"Ø×Ñ�xÖ r    rú   Tc               ó    € V ^8„  d   QhRRRR/# )r   Ú
annotationústr | dict[str, Any]rú   r   r   )r   s   "r   r   r   s  s   € ÷ 8ñ 8Ð1ð 8Àñ 8r    c             #  óâ  a"  € \         '       d   \        4       '       d   Rx € R# \        V \        4      '       d   RV /p \	        4       pVf   Rx € R# \
        e=   \        VP                  4      \
        8w  d   \        P                  ! R^R7       Rx € R# \        oR V3R llp\        / \        4       ;'       g    / CV C4      p V'       d@   \        P                  P                  P                  V4      ;_uu_ 4        Rx € RRR4       MRx € \!        V4       \#        V4      pV'       d   \$        P'                  W34       R# R#   + '       g   i     LH; i  \!        T4       i ; i5i)aÜ  mark_kernels(annotation, *, backward=True)

Context manager that annotates GPU work captured within its scope.

Must be used inside an active :class:`torch.cuda.graph` capture with
``enable_annotations=True``. Every kernel, memcpy, and memset node the
capture adds within the scope is tagged with :attr:`annotation`. Outside
a capture, with annotations disabled, or when :func:`is_available` is
``False``, the context manager is a no-op.

When scopes overlap on the same node (e.g. nested scopes), their
annotation dicts are merged key-by-key with the inner scope winning
common keys.

By default backward work is annotated too: autograd nodes created by
forward operations inside the scope get hooks (via
:class:`torch.autograd.graph.node_creation_hook`) that bracket their
backward execution, so when the backward pass is itself captured --
in the same capture as the forward or in a later one -- its kernels
are tagged with the same annotation, plus an ``"autograd_phase":
"backward"`` key marking them as backward work (``"autograd_phase"``
is therefore reserved: backward annotation overwrites it). When
backward runs outside a capture the hooks are a no-op. Ownership
extends to higher-order gradients: nodes created while a hooked node
executes (``create_graph=True``, checkpoint recomputation) inherit its
annotations, so a later grad-of-grad capture is attributed too.
``AccumulateGrad`` nodes are never annotated: a leaf's node is created
once and cached, so scope ownership would be an accident of first use.
Pass ``backward=False`` to annotate only the forward work, e.g. when a
wrapper implements its own backward attribution. The keyword's
presence also serves as the feature probe for that native backward
support: ``"backward" in inspect.signature(mark_kernels).parameters``.

Implementation: on entry, records the current stream's capture frontier
and its existing direct dependents; on scope exit, walks only the
dependent nodes added since entry (falling back to newly created graph
roots when the scope is the first captured work).

Args:
    annotation (str or dict): Metadata to attach to each captured node.
        A string ``s`` is recorded as ``{"name": s}``. Dict values must
        be picklable. The key ``"name"`` names the region in trace
        tooling; ``"stream"`` is reserved for stream-lane assignment.
    backward (bool): Whether to also annotate the backward kernels of
        autograd nodes created inside the scope. Default: ``True``.

.. note::
    The nodes to annotate must be reachable from the capture frontier of
    the stream that is current on scope entry. Work on a different
    already-capturing stream must be synchronized with the current
    stream first.

.. note::
    Child-graph and conditional nodes have bodies in a separate
    ``cudaGraph_t`` that this walk does not descend into, so their work is
    left unannotated and a warning is issued. Descending is possible
    (``cudaGraphNodeGetParams`` exposes the body graphs), but would not be
    enough on its own: a body's nodes are numbered in that graph's id space
    and are renumbered again when the exec graph inlines them, and nothing
    exposes that renumbering, so :func:`remap_to_exec_graph` could not key
    the annotations to what a profiler reports. For the same reason a scope
    *inside* a conditional body (``torch.cond`` / ``torch.while_loop``)
    records nothing at all.

.. warning::
    This API is in prototype and may change in future releases.

Example::

    >>> # xdoctest: +SKIP("requires cuda-bindings and driver >= 13.1")
    >>> g = torch.cuda.CUDAGraph()
    >>> x = torch.randn(8, device="cuda")
    >>> with torch.cuda.graph(g, enable_annotations=True):
    ...     with torch.cuda.graph_annotations.mark_kernels("phase_A"):
    ...         y = x + 1
NrÅ   zåmark_kernels: this scope is inside a CUDA graph conditional-node body (torch.cond / torch.while_loop), which is captured into a separate cudaGraph_t whose node ids are never remapped to the exec graph; nothing is annotated for itrÂ   c               ó    € V ^8„  d   QhRRRR/# )r   rb   r   r   r   r   )r   s   "r   r   Ú"mark_kernels.<locals>.__annotate__à  s   € ÷ .ñ .˜Cð . Dñ .r    c                ó    <€ \        V S4       R # r„   rë   )rb   rÝ   s   &€r   rì   Ú#mark_kernels.<locals>.creation_hookà  s   ø€ Ü˜D *Ö-r    )r   r/   rß   Ústrr¾   r   r)   r$   rÆ   rÇ   r¬   r¦   rŸ   rK   ÚautogradÚnode_creation_hookrª   rÐ   r–   rw   )r  rú   rÀ   rì   r¥   rÎ   rÝ   s   &$    @r   Úmark_kernelsr  r  s&  øé € ÷\  ÓÔ#;×#=Ò#=ÛÙä�*œc×"Ò"Ø˜jÐ)ˆ
äÓ!€EØ‚}ÛÙô 	Ò*Ü�e—k‘kÓ"Ô&<Ô<ô 	�Šð*ð õ	
ó 	Ùä'€J÷.ð .ô ÐDœ_Ó.×4Ð4°"ÐD¸ÐDÓE€DðßÜ—‘×%Ñ%×8Ñ8¸×GÕGÛ÷ HÐGó ä�TÔä! %Ó(€IßÜ×Ñ 
Ð6Ö7ñ ÷ H×Gûô
 	�TÕüsB   ƒB:E/Â>
E/Ã	E Ã1E ÄEÄE Ä8E/ÅE	ÅE ÅE,Å,E/c               ó    € V ^8„  d   QhRRRR/# ©r   Útorch_cuda_graphztorch.cuda.CUDAGraphr   r   r   )r   s   "r   r   r   õ  s   € ÷ .ñ .Ð3Gð .ÈDñ .r    c                ó´   € \         '       d   \        4       '       d   R# \        \        P                  ! V P                  4       4      4      V n        RV n        R# )aV  Record the captured graph's id on the graph object for later remap.

Called from ``capture_end`` in the window after capture ends and before the
graph is finalized, where the template ``cudaGraph_t`` is live for both
``keep_graph`` modes (and reachable via ``raw_cuda_graph``). ``remap_to_exec_graph``
later matches this graph's annotations to its exec id via this stamp, without
relying on call ordering. No-op if annotations are disabled or
``cudaGraphNodeGetToolsId`` is unavailable. Harmless when no ``mark_kernels``
regions run: the annotation map stays empty so resolve and remap are no-ops.
N)r   r/   r   r'   r(   Úraw_cuda_graphÚ_capture_graph_idÚ_remapped_exec_id©r  s   &r   Úmaybe_stamp_capture_graph_idr  õ  sK   € ÷  ÓÔ#;×#=Ò#=Ùô
 *>Ü×$Ò$Ø×+Ñ+Ó-ó	
ó*ÐÔ&ð *.ÐÖ&r    c               ó   € V ^8„  d   QhRR/# rÔ   r   )r   s   "r   r   r     s   € ÷  ñ   Tñ  r    c                 óØ  € \         '       g   R#  \        \        4      p \          F%  w  rV F  pW,          P                  V4       K  	  K'  	  V P	                  4        Fµ  w  r4\        V4      ^8X  d&   \        V,          P                  V^ ,          4       K:  / pV FW  p\        V\        4      '       d-   VP	                  4        F  w  rgVP                  Wg4       K  	  KE  VP                  RV4       KY  	  \        V,          P                  V4       K·  	  \         P                  4        R#   \         d    \        P                  R4        L8i ; i  \         P                  4        i ; i)z7Resolve pending scope toolsIds into kernel annotations.NrÅ   z"resolve_pending_annotations failed)r–   r   rS   rw   ÚitemsÚlenr   rß   ÚdictÚ
setdefaultÚ	Exceptionr>   Ú	exceptionÚclear)Úper_tools_idr  rÎ   Útools_idÚann_listró   ÚkeyÚvalues           r   Úresolve_pending_annotationsr%    s"  € ç‹?Ùð Ü4?ÄÓ4Eˆß%4Ñ!ˆJÛ%�ØÕ&×-Ñ-¨jÖ9ó &ñ &5ð #/×"4Ñ"4Ö"6ÑˆHÜ�8‹} Ô!Ü# HÕ-×4Ñ4°X¸aµ[ÔAÙà%'ˆFÛ&�
Ü˜j¬$×/Ò/Ø&0×&6Ñ&6Ö&8™
˜Ø×)Ñ)¨#Ö5ó '9ð ×%Ñ% f¨jÖ9ñ 'ô   Õ)×0Ñ0°Ö8ñ #7ô  	×ÑÖøô ô ?Ü×ÑÐ=Ö>ð?ûô 	×ÑÕús$   �DD- Ä- EÅE ÅEÅE ÅE)c               ó    € V ^8„  d   QhRRRR/# r  r   )r   s   "r   r   r   -  s   € ÷ ,7ñ ,7Ð*>ð ,7À4ñ ,7r    c                ób  € V P                   p\        '       d   Vf   R# \        \        P                  ! V P                  4       4      4      pV P                  f   TMV P                  pW28X  d   R# \        \        W24      p\        P                  4        \        P                  V4       W n        R# )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.

The graph's capture id is read from the ``_capture_graph_id`` stamped on it
by ``maybe_stamp_capture_graph_id`` in the capture_end window, so only the annotations
belonging to this graph are rekeyed. This is order-independent and correct
when several graphs are captured in sequence: call once per graph. Graphs
captured with annotations disabled have no capture id and are skipped.

The exec graph id is only defined once the graph is instantiated. With
``keep_graph=True`` instantiation is deferred past the ``torch.cuda.graph()``
context, so the remap is driven from the graph's ``instantiate()``/
``replay()`` instead of context exit. Each ``instantiate()`` (even on an
unmodified template) produces a fresh exec graph id, so this rekeys from
wherever the annotations are currently keyed -- the capture id before the
first remap, the previous exec id after a re-instantiate -- to the current
exec id. ``_remapped_exec_id`` tracks that current key; when it already
matches the live exec id (e.g. replay after instantiate) this is a no-op.
N)
r  r   r   r'   ÚcudaGraphExecGetIdÚraw_cuda_graph_execr  Ú_rekey_annotationsr  Úupdate)r  Úcapture_graph_idÚexec_graph_idÚcurrent_key_idÚremappeds   &    r   Úremap_to_exec_graphr0  -  sœ   € ð. (×9Ñ9ÐßÓÐ"2Ò":Ùä(Ü×(Ò(Ø×0Ñ0Ó2ó	
ó€Mð ×-Ñ-Ò5ñ 	à×/Ñ/ð ð
 Ô&Ùä!Ô"5°~ÓU€HÜ×ÑÔÜ×Ñ˜xÔ(Ø)6Ö&r    c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r   zdict[int, list[Any]]r,  r%   r-  r   r   )r   s   "r   r   r   \  s0   € ÷ ñ Ø%ðàðð ðð ñ	r    c                óð   € / pV P                   ! 4        F^  w  rEV^ ,	          V8w  d   WSV&   K  VR,          pV^ ,          V,          pWs9   d   W7,          P                  V4       KQ  \        V4      W7&   K`  	  V# )a³  Rekey one graph's annotations from its capture id to its exec id.

A toolsId packs the graph id in the upper 32 bits and the node id in the
lower 32. Only entries whose upper bits match ``capture_graph_id`` are
rewritten to ``exec_graph_id``; entries from other graphs (already remapped
to their own exec ids, or pending their own remap) are kept as-is. When two
capture-side ids collide on the same rekeyed id their lists are merged.
l   ÿÿ )r  ÚextendrS   )r   r,  r-  r/  r!  r"  Únode_idÚnew_tools_ids   &&&     r   r*  r*  \  sz   € ð &(€HØ)×/Ò/Ö1ÑˆØ�r�>Ð-Ô-Ø!)�XÑÙØ˜ZÕ'ˆØ%¨Õ+¨wÕ6ˆØÔ#ØÕ"×)Ñ)¨(Ö3ä%)¨(£^ˆHÓ"ñ 2ð €Or    c               ó    € V ^8„  d   QhRRRR/# r  r   )r   s   "r   r   r   w  s   € ÷ *ñ *Ð(<ð *Àñ *r    c                ó0   € \        4        \        V 4       R# )zÅResolve any pending scopes and remap one graph in a single call.

Shorthand for ``resolve_pending_annotations()`` followed by
``remap_to_exec_graph(graph)``; the pair normally run after a capture.
N)r%  r0  r  s   &r   Úresolve_and_remapr8  w  s   € ô  Ô!ÜÐ(Ö)r    c               ó   € V ^8„  d   QhRR/# )r   r   zMapping[int, list[Any]]r   )r   s   "r   r   r   �  s   € ÷ ñ Ð 7ñ r    c                 ó   € \         # )a9  get_kernel_annotations() -> Mapping[int, list]

Return the live registry of recorded kernel annotations.

Keys are opaque integers matching the ``graph node id`` field that
CUPTI-based profilers attach to kernel events; values are the lists of
annotation dicts recorded for that node. The registry accumulates
across captures and is global to the process.

The returned mapping is a **live view**: it is updated in place when a
graph is instantiated (annotation keys are rekeyed to the executable
graph's ids), so a reference obtained early stays current. Keys are
valid for joining against a profiler trace once the corresponding
graphs have been instantiated. Treat the mapping as read-only; snapshot
it with ``dict(...)`` if isolation is needed.

.. warning::
    This API is in prototype and may change in future releases.

Example::

    >>> # xdoctest: +SKIP("requires cuda-bindings and driver >= 13.1")
    >>> annotations = torch.cuda.graph_annotations.get_kernel_annotations()
    >>> with open("annotations.pkl", "wb") as f:
    ...     pickle.dump(dict(annotations), f)
)r   r   r    r   Úget_kernel_annotationsr;  �  s
   € ô6 Ðr    c               ó   € V ^8„  d   QhRR/# rÔ   r   )r   s   "r   r   r   Ÿ  s   € ÷  ñ   $ñ  r    c                 óp   € \         P                  4        \        P                  4        \        ^,          sR# )a”  clear_kernel_annotations() -> None

Clear all recorded kernel annotations.

The annotation registry is process-global and accumulates across
captures; long-running workloads that capture many graphs should clear
it once recorded annotations have been consumed (e.g. after saving
them alongside a profiler trace).

Clearing forgets everything recorded so far and revokes recording from
every scope opened before the clear: backward hooks that
:func:`mark_kernels` attached to existing autograd nodes stay on the
graph but become inert. Scopes opened after the clear record normally.

.. warning::
    This API is in prototype and may change in future releases.
N)r   r  r–   r¬   r   r    r   Úclear_kernel_annotationsr>  Ÿ  s'   € ô& ×ÑÔÜ×ÑÔÜ˜aÕÒr    c               ó    € V ^8„  d   QhRRRR/# )r   Úexec_graph_idszIterable[int]r   r   r   )r   s   "r   r   r   ·  s   € ÷ %ñ %¨mð %Àñ %r    c                ó    € \        V 4      pV'       g   R# \         Uu. uF  q"^ ,	          V9   g   K  VNK  	  up F
  p\        V K  	  R# u upi )zºDrop kernel-annotation entries whose exec graph id (tools_id >> 32) is in
exec_graph_ids, so the map does not grow across the run. Run by the annotation
resolver's graph-destroy handler.N)ru   r   )r@  ÚidsÚkr#  s   &   r   Úremove_kernel_annotationsrD  ·  sE   € ô ˆnÓ
€CßÙÝ.ÓAÑ.�a°rµ'¸S±.—�Ñ.ÔAˆÜ Ò$ó BùÒAs
   žA²AÚ_stream_id_counterzdict[int, int]Ú_stream_id_mapc               ó    € V ^8„  d   QhRRRR/# )r   r+   útorch.cuda.Streamr   r%   r   )r   s   "r   r   r   É  s   € ÷ ñ Ð,ð °ñ r    c                ó~   € V P                   pV\        9  d   \        \        V&   \        ^,          s\        V,          # )z;Return a small, stable stream ID for the given CUDA stream.)r1   rF  rE  )r+   r#  s   & r   Ú_get_stream_idrJ  É  s7   € ð ×
Ñ
€CØ
”.Ô Ü0Œ�sÑÜ˜aÕÐÜ˜#ÕÐr    c               ó    € V ^8„  d   QhRRRR/# )r   Úpg_keyr
  r   r%   r   )r   s   "r   r   r   Ó  s   € ÷ "ñ "˜cð " cñ "r    c                óf   € V \         9  d   \        \         V &   \        ^,          s\         V ,          # )z:Return a unique stream ID for the given process group key.)rF  rE  )rL  s   &r   Úget_stream_for_pgrN  Ó  s,   € ð ”^Ô#Ü!3Œ�vÑÜ˜aÕÐÜ˜&Õ!Ð!r    c               ó    € V ^8„  d   QhRRRR/# )r   r+   rH  r  r  r   )r   s   "r   r   r   Ý  s   € ÷ ñ Ð)ð Ð7Kñ r    c           	   #  óþ  "  € \         '       g7   \        P                  P                  V 4      ;_uu_ 4        Rx € RRR4       R# V P                  \        P                  P                  4       P                  8X  d#   \        V4      ;_uu_ 4        Rx € RRR4       R# \        V\        4      '       d   RV/p\        V\        4      '       d   \        V 4      VR&   \        V4      ;_uu_ 4        \        P                  P                  V 4      ;_uu_ 4        Rx € RRR4       RRR4       R#   + '       g   i     R# ; i  + '       g   i     R# ; i  + '       g   i     LB; i  + '       g   i     R# ; i5i)uZ  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). When switching to a different stream,
this snapshots the current capturing branch before the target stream
runs marked work. If the target stream is already capturing, the marked
work must still be synchronized with the current stream so it is
reachable from that snapped frontier.
NrÅ   r+   )r   rK   rL   r+   r1   r»   r  rß   r
  r  rJ  )r+   r  s   &&r   Úmark_streamrQ  Ü  só   é € ÷  ÓÜ�Z‰Z×Ñ˜v×&Õ&Û÷ 'áØ×ÑœUŸZ™Z×6Ñ6Ó8×DÑDÔDÜ˜*×%Õ%Û÷ &Ñ%ô �j¤#×&Ò&Ø  *Ð-ˆJÜ�j¤$×'Ò'Ü#1°&Ó#9ˆJ�xÑ Ü˜*×%Õ%Ü—‘×"Ñ" 6×*Õ*Û÷ +÷ &Ñ%÷ 'Ö&áúç%×%Ð%ú÷ +×*ú÷ &×%Ð%üse   ‚4E=¶D.»AE=ÂEÂAE=Ã/(E)ÄE	ÄE)Ä$
E=Ä.D?	Ä9	E=ÅE	Å	E=ÅE&Å!E)Å)E:	Å4	E=)\Ú__conditional_annotations__r¶   Ú
__future__r   Úimportlib.metadatar;   Ú	threadingrÆ   Úcollectionsr   Ú
contextlibr   Úloggingr   Útypingr   r   r   r	   Úcollections.abcr
   r   rK   Útorch.cuda._utilsr   r   r   Úcuda.bindingsr   rk   r   r'   ÚImportErrorr²   r>   ÚtuplerS   r   r·   r  r%   ru   r   r   r   r   r"   r)   r5   rF   r/   rM   r2   r`   rh   rm   r~   r   r€   r�   r�   r•   r–   r�   rŸ   r¦   rª   Úobjectr«   r¬   r®   r¾   rÐ   ÚlocalrÒ   rÛ   rä   râ   r  r  r%  r0  r*  r8  r;  r>  rD  rE  rF  rJ  rN  rQ  )rR  s   @r   Ú<module>ra     sN  øðô)õV #ã Û Û Ý #Ý %Ý ß <Ó <÷ ß1ã ÷ñ ð÷ñ 
�8Ó	€ð !  d¨3¥i Õ0€ˆyÓ 0Ø'+¨C°°Sµ¨MÕ':Ð ˜9Ó :ð
 $(Ð �[Ó 'ð #Ð �dÓ "ð &*Ð ˜
Ó )õ&õõ5õ"!õH#õHõ *õ#õ"-õ"	ð!ð DHð!ð !&÷	!ñJ 4?¸tÓ3DÐ Ð0Ó Dð '+Ð �OÓ *õð, (,Ð �_Ó +õðH 02€Ð,Ó 1ð 1€õõõ:ñ “8€ˆSÓ ð  Ð ˜Ó ô7�:ô 7õSõ&*ôZ#�I—O‘Oô #ñ@ “€ˆ#Ó õ5õ8D!ðN ð8Àtö 8ó ð8õD.õ4 õ<,7õ^õ6*õõ< õ0%ð Ð �CÓ Ø!#€�Ó #õõ"ð ôó òøðm ô Ø€LØƒMðús   ÁG0 Ç0G?Ç>G?