ó
    Eñioš ã                  ó¦  • S SK Jr  S SKrS SKrS SKrS SKrS SKrS SKrS SKJ	r	  S SK
Jr  S SKJrJrJrJr  S SKrS SKJr  S SKJr  S SKJr  S	S
KJrJrJr  S	SKJr  \(       a  S	SKJrJr  S	SK J!r!J"r"J#r#J$r$  S	SK%J&r&J'r'J(r(J)r)J*r*J+r+J,r,  S	SK-J.r.  \R^                  " \05      r1\Rd                  Rg                  \0S5      r4\(       a  S SK5J6r6    SES jr7SFS jr8SFS jr9    SFS jr:    SFS jr;\ " S S5      5       r<SGS jr=SHS jr>SIS jr?SJSKS jjr@S rASLS jrBS rC    SMS  jrD    SNS! jrE    SOS" jrFS# rGS$ rHS% rI        SPS& jrJ          SQS' jrK            SRS( jrL              SSS) jrM              STS* jrN                  SUS+ jrO                      SVS, jrP          SWS- jrQ    SXS. jrR                SYS/ jrS    SZS0 jrT          S[S1 jrU    S\S2 jrV\ " S3 S45      5       rW    SXS5 jrX                    S]S6 jrY                    S^S7 jrZ              STS8 jr[                S_S9 jr\          SWS: jr]    S`S; jr^SFS< jr_SaS= jr`S> raS? rb    SFS@ jrcSbSA jrdScSB jreSC rf        SdSD jrgg)eé    )ÚannotationsN)Údefaultdict)Ú	dataclass)ÚAnyÚOptionalÚTYPE_CHECKINGÚUnion)Útrace_structured)ÚStorageWeakRef)Ú
OrderedSeté   )ÚconfigÚconfig_commsÚir)ÚWeakDep)ÚIRNodeÚ	Operation)Úestimate_peak_memory_allocfreeÚFreeableInputBufferÚget_freeable_input_bufÚSNodeMemory)Úcontains_collectiveÚcontains_waitÚfind_recursive_deps_of_nodeÚfind_recursive_users_of_nodeÚis_collectiveÚis_fallback_opÚis_wait)ÚVÚoverlap)ÚBaseSchedulerNodec                óV  • SSK Jn  0 n0 nU  H&  nUR                  5       X$'   U" U5      c  M   X$   X4'   M(     SS KJn  SSKJn  UR                  5       nU" 5       n[        U5       V	s/ s H  n	/ PM     n
n	UR                  U
[        UR                  5       5      U5        [        R                  " [        R                  " U
5      SS9R                  R                  5       n[!        UR#                  5       5       H  u  pÄX¼   X4'   M     U  H  nXC;   a  X4   X$'   X$   Ul        M     g s  sn	f )Nr   )Ú_get_mm_like_fn)Ú_get_default_group)Údim)Útorch._inductor.schedulerr#   Úget_estimated_runtimeÚtorch.distributedÚdistributedÚ"torch.distributed.distributed_c10dr$   Úget_world_sizeÚrangeÚall_gather_objectÚlistÚvaluesÚtorchÚmedianÚtensorÚtolistÚ	enumerateÚkeysÚoverride_estimated_runtime)Úsnodesr#   Úruntime_estimationsÚruntime_estimations_for_mmsÚsnodeÚdistr$   Ú
world_sizeÚpgÚ_Ú$gathered_runtime_estimations_for_mmsÚ"median_runtime_estimations_for_mmsÚidxs                ÚR/home/mande/repo/quber/.venv/lib/python3.13/site-packages/torch/_inductor/comms.pyÚ6align_runtime_estimations_across_all_distributed_ranksrC   4   s3  € õ :àÐØ"$ÐãˆØ%*×%@Ñ%@Ó%BÐÑ"Ù˜5Ó!Ó-Ø1DÑ1KÐ'Ó.ñ õ
 %ÝEà×$Ñ$Ó&€JÙ	Ó	€Bä˜*Ô%ó?Ú%ˆq‹Ñ%ð )ð ?ð 	×ÑØ,ÜÐ(×/Ñ/Ó1Ó2Ø
ôô
 */¯ªÜ�ŠÐ9Ó:Àñ*ç�f�V‰V‹Xð 'ô  Ð ;× @Ñ @Ó BÖC‰
ˆØ-OÑ-TÐ#Ó*ñ Dó ˆØÓ/Ø)DÑ)KÐÑ&Ø+>Ñ+EˆÖ(ò ùò?s   Á'D&c                ó   • [        U SSSS9$ )z/
Greedily schedules waits as late as possible.
FT©Úraise_commsÚ
sink_waitsÚreorder_for_overlap©Ú_schedule_for_comm©r7   s    rB   rG   rG   Z   s   € ô Ø˜E¨dÈñð ó    c                ó   • [        U SSSS9$ )z0
Greedily schedules comms as early as possible.
TFrE   rI   rK   s    rB   rF   rF   c   s   € ô Ø˜D¨UÈñð rL   c                ó   • [        U SSSS9$ )a˜  
This achieves the following overall scheduling procedure:
    Step 1: Given that we've currently scheduled comm N, we now schedule all compute nodes
        that are required for comm N + 1 but do not depend on comm N, to run at the same time with comm N.
    Step 2: If all those compute nodes are sufficient to overlap comm N, we're done.
        Otherwise, we now need to look elsewhere to find compute that overlaps with comm N.
        We prioritize compute nodes that are needed sooner.
    Step 3: We schedule the compute nodes dependent on comm N and required for comm N + 1.
    Step 4: We schedule comm N + 1.
    Repeat this for subsequent comm nodes.
TrE   rI   rK   s    rB   Úreorder_compute_for_overlaprO   l   s   € ô Ø˜D¨TÀtñð rL   c                ó    • [        U 5      u  pU$ )a+  
Reorders communication ops relative to computation ops to improve communication-compute overlapping and hide comm
latency.  Stops moving a particular op if it reaches a point that would have increased the peak memory footprint.

Currently, follows these heuristics (subject to change or tune):
- never reorders collectives relative to one another, for SPMD safety
- has an option for per-collective prefetch limit, but does not enable it by default
- limits the total number of reorder steps to some factor of the graph size to prevent worst-case quadratic
  performance

Prerequisite: sink_comms_and_waits - ensure comm and wait nodes are scheduled as late as possible, respecting data
dependencies.  That allows reorder_communication_preserving_peak_memory to take a best case peak-memory snapshot,
and then monotonically improve latency by moving collectives backward in time.

Peak memory impact is computed in an iterative fashion.  First, memory use at each timestep is computed, and global
peak memory is computed as a max over timesteps.  Then, when swapping any two adjacent nodes, only the curr-memory
for the earlier of the nodes after the swap is affected.  This enables checking step by step whether a swap is
peak-memory-safe, and bailing out if not.  Example:

0   n0      C0
1   n1      C0 + Allocs(n1) - Frees(n1)
2   n2      C0 + Allocs(n1) - Frees(n1) + Allocs(n2) - Frees(n2)

0   n0      C0
1   n2      C0 + Allocs(n2) - Frees(n2)    <-- After moving n2 to Time 1, only time1 memory changes
2   n1      C0 + Allocs(n2) - Frees(n2) + Allocs(n1) - Frees(n1)

)Ú6_reorder_communication_preserving_peak_memory_internal)r7   Úreordered_snodesÚ
node_statss      rB   Ú,reorder_communication_preserving_peak_memoryrT      s   € ô@ 	?¸vÓFñ !Ðð ÐrL   c                  ó¨   • \ rS rSr% SrSrS\S'   SrS\S'   SrS\S	'   S
r	S\S'   Sr
S\S'   SrS\S'   SrS\S'   SrS\S'   SrS\S'   \S 5       rSrg)ÚReorderInfoé¥   z=
Debug info describing how an individual snode was reordered
ÚNoneÚstrÚlimiting_factorr   ÚintÚmovesÚgroupedÚ Úgrouped_infoç      ð¿ÚfloatÚ	comm_timeÚ	comp_timeÚinitial_exposedÚfinal_exposedÚoverlap_infoc                ó4   • U R                   U R                  -
  $ ©N©rd   re   ©Úselfs    rB   ÚimprovementÚReorderInfo.improvementµ   ó   € à×#Ñ# d×&8Ñ&8Ñ8Ð8rL   © N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__rZ   Ú__annotations__r\   r]   r_   rb   rc   rd   re   rf   Úpropertyrl   Ú__static_attributes__ro   rL   rB   rV   rV   ¥   st   ‡ ñð "€O�SÓ!Ø€Eˆ3ƒNØ€GˆSÓØ€L�#ÓØ€IˆuÓØ€IˆuÓØ!€O�UÓ!Ø€M�5ÓØ€L�#Óàñ9ó ó9rL   rV   c                ó¾   • U c  g[        U [        R                  R                  R                  R
                  5      (       a  g[        U SS 5      =n(       a  SU;   a  gg)NFTÚpython_kernel_nameÚextern_kernels)r   r0   ÚopsÚatenÚ#_scaled_dot_product_flash_attentionÚdefaultÚgetattr)Únodery   s     rB   Úis_gemm_liker�   º   s]   € Ø�|ØäØÜ�	‰	�‰×:Ñ:×BÑB÷ñ ð ô & dÐ,@À$ÓGÐGÐÕGØ
Ð0Ó
0ØØrL   c                ó�   • SSK Jn  [        X5      (       a  [        S U R                   5       5      $ [        U R                  5      $ )Nr   ©ÚGroupedSchedulerNodec              3  ó8   #   • U  H  n[        U5      v •  M     g 7frh   )Úcontains_gemm_like)Ú.0Úxs     rB   Ú	<genexpr>Ú%contains_gemm_like.<locals>.<genexpr>Ï   s   é € Ð?²,¨QÔ% a×(Ð(²,ùó   ‚)r&   r„   Ú
isinstanceÚanyr7   r�   r€   )r:   r„   s     rB   r†   r†   Ë   s4   € Ý>ä�%×.Ñ.ÜÑ?°%·,²,Ó?Ó?Ð?ä˜EŸJ™JÓ'Ð'rL   c                óš   • SSK Jn  [        X5      (       a-  U R                  (       a  U R                   H  nU" U5        M     g U" U 5        g )Nr   rƒ   )r&   r„   rŒ   Útemp_groupingr7   )r:   Úfnr„   Ú_snodes       rB   Ú_temp_group_visit_leavesr’   Ô   s6   € Ý>ä�%×.Ñ.°5×3F×3FØ—l”lˆFÙˆvŽJò #ñ 	ˆ5�	rL   c                ó¸   • SnU R                    HG  nU(       a  US-  nX#R                  5       -  nU(       d  M*  U[        U R                  5       5       -  nMI     U$ )Nr^   r>   )r7   Úget_namer.   Úget_buffer_names)r:   Ú	with_bufsÚretÚns       rB   Ú_group_namer™   Þ   sV   € Ø
€CØ�\Œ\ˆÞØ�3‰JˆCØ�z‰z‹|Ñˆßˆ9Ø”d˜5×1Ñ1Ó3Ó4Ð5Ñ6ŠCñ ð €JrL   c                óH   • [        U [        5      =(       a    U R                  $ rh   )rŒ   r   Úis_fake)Úds    rB   Ú_is_fake_depr�   é   s   € Ü�aœÓ!×/ a§i¡iÐ/rL   c                ój   • SR                  U  Vs/ s H  oR                  5       PM     sn5      $ s  snf )NÚ~)Újoinr”   )ÚgnsÚgns     rB   Ú_group_namesr£   í   s'   € Ø�8‰8©SÓ1ªS r—[‘[–]©SÑ1Ó2Ð2ùÒ1s   �0c                óŽ   • [        X5      n[        XU5      u  pEpg[        [        X5      5      nSUS'   [	        U5      n	UUUUUU	4$ )z*Initialize memory tracking data structures)r   r   N)r   r   ÚdictÚzipÚ_build_candidate_buffer_map)
r7   Úgraph_inputsÚgraph_outputsÚname_to_freeable_input_bufÚpeak_memoryÚsnodes_curr_memoryÚsnodes_allocfreeÚbuf_to_snode_last_useÚ_curr_memoryÚcandidate_buffer_maps
             rB   Ú_initialize_memory_trackingr±   ñ   sl   € ä!7¸Ó!MÐä&Ø°ó	
ñ M€KÐ%5ô
 œ˜FÓ7Ó8€Là€L�Ñô 7Ð7LÓMÐð 	ØØØØ"Øðð rL   c                ó    • 0 n0 n[        U 5       H3  u  p4US:”  a  XS-
     OSX'   U[        U 5      S-
  :  a  XS-      OSX$'   M5     U S   nXU4$ )z/Create double-linked list structure from snodesr   r   N)r4   Úlen)r7   Ú_prevÚ_nextÚir:   Ú_heads         rB   Ú_initialize_double_linked_listr¸   
  sh   € ð €EØ€EÜ˜fÖ%‰ˆØ()¨A«�v !™e’}°4ˆ‰Ø()¬C°«K¸!©OÓ(;�v !™e’}Àˆ‹ñ &ð �1‰I€EØ˜ÐÐrL   c                ó¨   • [        [        5      nU  H3  nUR                  R                   H  nX   R	                  U5        M     M5     [        U5      $ )ae  
Build inverted index: node -> set of buffers where node appears in successors.

This optimization reduces buffer iteration from O(total_buffers) to O(buffers_per_node).
Since buffer successors are immutable during reordering, this map doesn't need updates.

Returns:
    dict mapping each node to the set of buffers that have this node in their successors
)r   r   Ú
mpi_bufferÚ
succ_nodesÚaddr¥   )r®   Únode_to_candidate_bufsÚbufÚ	succ_nodes       rB   r§   r§     sT   € ô CNÜóCÐó %ˆàŸ™×2Ô2ˆIØ"Ñ-×1Ñ1°#Ö6ó 3ñ %ô
 Ð&Ó'Ð'rL   c           	     ón   • U  Vs0 s H#  o[        S UR                  5        5       5      _M%     sn$ s  snf )zÒ
Pre-compute output name sets for all nodes.

This optimization avoids creating OrderedSet objects repeatedly during
exposed time calculations.

Returns:
    dict mapping each node to a set of its output names
c              3  ó@   #   • U  H  oR                  5       v •  M     g 7frh   ©r”   ©r‡   Úos     rB   r‰   Ú/_precompute_node_output_sets.<locals>.<genexpr>@  s   é € ÐDÒ0C¨1Ÿ*™*Ÿ,˜,Ò0Cùó   ‚)r   Úget_outputs)r7   r:   s     rB   Ú_precompute_node_output_setsrÈ   3  s?   € ñ SYóÚRXÈŒzÑD°×0AÑ0AÔ0CÓDÓDÒDÑRXñð ùò s   …*2c                ób   • [        U 5      (       a  [        R                  $ [        R                  $ rh   )r   r   Ú*reorder_sink_runtime_estimations_comm_multÚ.reorder_sink_runtime_estimations_non_comm_mult©r:   s    rB   Ú_op_runtime_estimate_multrÍ   D  s'   € ô ˜5×!Ñ!Ü×FÑFÐFä×FÑFÐFrL   c                óN   • [        U R                  SS5      =n(       a  SU;   a  gg)z¾
Filtering out ops that contain Collective and Wait inside and considered as Collectives.
See contains_collective function.
If the op contains Wait inside - consider as Synchronous compute.
ry   Nz-torch.ops._dtensor.shard_dim_alltoall.defaultFT)r   r€   )r:   ry   s     rB   Úis_async_collectiverÏ   M  s-   € ô % U§Z¡ZÐ1EÀtÓLÐLÐÕLØ:Ð>PÓPØàrL   c                ó"   • [        U [        5      $ rh   )r   rÏ   rÌ   s    rB   Úcontains_async_collectiverÑ   Z  s   € Ü˜uÔ&9Ó:Ð:rL   c                óP   • / nU n Ub  UR                  U5        XA:X  a   U$ X$   nM"  )a!  
Traverse doubly-linked list from head to tail and return nodes as a list.

Args:
    head: Starting node of the segment
    tail: Ending node of the segment (inclusive)
    next_dict: Dictionary mapping each node to its next node

Returns:
    List of nodes from head to tail (inclusive)
)Úappend)ÚheadÚtailÚ	next_dictr—   r˜   s        rB   Ú_group_nodes_from_linked_listr×   ^  s<   € ð  €CØ€AØ
Ø‰=Ø�J‰J�qŒMØ‹9Øà€Jð ‰Lˆñ rL   c                ó,   • X    nX1   n[        XT-  5      $ )zf
Check if a wait node corresponds to a given collective node.
Uses pre-computed sets for O(1) lookup.
)Úbool)Úcollective_snodeÚ
wait_snodeÚnode_output_setsÚnode_dep_setsÚcollective_outsÚ
unmet_depss         rB   Ú!_is_corresponding_collective_waitrà   y  s"   € ð 'Ñ8€OØÑ*€JÜ�
Ñ,Ó-Ð-rL   c                óà  ^^• TU    nSmX0   nSn/ nX   n	U	bÒ  XI   n
X¦-  (       a  USU	R                  5        S3-  nO­[        U	5      (       a(  [        U	5      (       d  OŒUR                  U	5        X   n	M`  [	        U	5      (       a(  SnU H  n[        X	X45      (       d  M  Sn  O   U(       a  O=TnS
UU4S jjn[        Xž5        TnUSU	R                  5        S	Xý-
   S3-  nX   n	U	b  MÒ  UTU4$ )zË
Calculate exposed communication time by iterating directly over linked list.
Avoids O(N) list construction for each call.

The collective_snode is the starting point, iteration continues via next_dict.
ç        r^   z->W[Ú]FTc                ó   >• TTU    -  mg rh   ro   ©r‘   rc   Úruntimess    €€rB   Úaccumulate_timeÚ9_coll_exposed_communication_time.<locals>.accumulate_time·  ó   ø€ à˜ &Ñ)Ñ)‰IrL   Ú+Ú[©r‘   r!   ÚreturnrX   )r”   r   rÑ   rÓ   r   rà   r’   )rÚ   rÖ   ræ   rÜ   rÝ   rb   rÞ   rf   Úcollectives_foundr:   rß   Úhas_wait_for_collectives_foundÚ_collÚcomp_time_beforerç   Úcomp_time_afterrc   s     `             @rB   Ú _coll_exposed_communication_timeró   ˆ  s;  ù€ ð Ð)Ñ*€IØ€IØ&Ñ8€OØ€LØ13ÐàÑ'€EØ
Ñ
Ø"Ñ)ˆ
à×'Ø˜d 5§>¡>Ó#3Ð"4°AÐ6Ñ6ˆLØä˜u×%Ñ%Ü,¨U×3Ñ3Øà!×(Ñ(¨Ô/Ø!Ñ(�ÙÜ˜×ÑØ-2Ð*Û*�Ü4Ø$Ð-=÷ó ð 6:Ð2Ùñ +ö .Øà$Ð÷	*ð 	*ô 	! Ô8Ø#ˆØ˜!˜EŸN™NÓ,Ð-¨Q¨Ñ/QÐ.RÐRSÐTÑTˆàÑ ˆðG Ó
ðJ �i Ð-Ð-rL   c                óÞ  ^^• SnSmSn/ nX    n	U	bØ  [        U	5      (       a  UR                  U	5        [        U	5      (       aj  [        X�XE5      (       a  TU	   nUSU	R	                  5        S3-  nOy[        U	5      (       d  SmX)   n	Mz  U H  n
[        XšXE5      (       d  M  Sm  O   X)   n	Mž  TnSUU4S jjn[        Xœ5        TnUSU	R	                  5        SXÛ-
   S3-  nX)   n	U	b  MØ  UTU4$ )	zâ
Calculate exposed communication time for a wait operation by iterating
directly over linked list backwards. Avoids O(N) list construction.

Iterates from wait_snode backwards using prev_dict to find corresponding collective.
râ   r^   z->C[rã   c                ó   >• TTU    -  mg rh   ro   rå   s    €€rB   rç   Ú9_wait_exposed_communication_time.<locals>.accumulate_timeó  ré   rL   rê   rë   rì   )r   rÓ   r   rà   r”   rÑ   r’   )rÛ   rÔ   Ú	prev_dictræ   rÜ   rÝ   rb   rf   Úwaits_foundr:   Úwrñ   rç   rò   rc   s      `          @rB   Ú _wait_exposed_communication_timerú   Ä  s<  ù€ ð €IØ€IØ€LØ+-€KàÑ!€EØ
Ñ
Ü˜×ÑØ×Ñ˜uÔ%Ü˜u×%Ñ%Ü0ØÐ#3÷ñ ð % U™O�	Ø $ u§~¡~Ó'7Ð&8¸Ð :Ñ:�Øä,¨U×3Ñ3Ø�	Ø!Ñ(�Ùã$�AÜ8ØÐ"2÷ó ð %(˜	Ùñ %ð "Ñ(�Ùà$Ð÷	*ð 	*ô 	! Ô8Ø#ˆØ˜!˜EŸN™NÓ,Ð-¨Q¨Ñ/QÐ.RÐRSÐTÑTˆàÑ ˆðG Ó
ðJ �i Ð-Ð-rL   c                óp   • X0   nU(       a  XU'   XcU'   XB   nU(       a  XU'   XtU '   X#U '   XU'   XP:X  a  U$ U$ )aQ  
Swap positions of candidate and group in doubly-linked list.

Transforms:
candidate_prev -> candidate -> group_head...group_tail -> group_tail_next
Into:
candidate_prev -> group_head...group_tail -> candidate -> group_tail_next

Args:
    candidate: Node to swap with group
    group_head: First node of group
    group_tail: Last node of group
    prev_dict: Dictionary mapping nodes to their previous nodes
    next_dict: Dictionary mapping nodes to their next nodes
    head: Current head of the linked list

Returns:
    New head of the linked list (may change if candidate was the head)
ro   )Ú	candidateÚ
group_headÚ
group_tailr÷   rÖ   rÔ   Úcandidate_prevÚgroup_tail_nexts           rB   Ú _perform_double_linked_list_swapr     sa   € ð8 Ñ)€NÞØ$.�.Ñ!Ø*ˆjÑð  Ñ+€OÞØ%.�/Ñ"Ø*ˆiÑð &ˆiÑØ%ˆjÑð ÓØÐØ€KrL   c                ón  • 0 nSn	U(       d&  [        X4-
  Xr   S   U-
  UR                  -   5      n	X˜4$ U* n
U HS  nX{   S   U
-   nXÈU'   [        Xœ5      n	UR                  U5      nUc  M2  U H  nX®R                  R                  -  n
M     MU     Xr   S   U
-   UR                  -   nXøU '   [        XŸ5      n	X˜4$ )aã  
Calculate potential peak memory after swapping candidate with group (reorder version).

Computes new memory levels for all affected nodes and returns the potential
peak memory along with cached post-allocation memory values for each node.

Args:
    candidate: Node being moved
    gns: Group nodes
    group_tail: Last node of group
    group_peak_memory: Current peak memory within the group
    candidate_delta_mem: Net memory change from candidate (alloc - free)
    candidate_allocfree: Candidate's allocation/free info
    group_n_to_bufs_after_swap_dealloc_by_candidate: Buffers whose deallocation moves to candidate
    curr_memory: Current memory state dict

Returns:
    Tuple of (potential_peak_memory, post_alloc_update_dict)
r   r   )ÚmaxÚ
size_allocÚgetrº   Ú	size_free)rü   r¡   rþ   Úgroup_peak_memoryÚcandidate_delta_memÚcandidate_allocfreeÚ/group_n_to_bufs_after_swap_dealloc_by_candidateÚcurr_memoryÚ_post_alloc_updateÚpotential_peakÚmem_after_reorder_deltar¢   Úgn_post_alloc_memÚbufsr¾   Úcandidate_mem_post_allocs                   rB   Ú(_calculate_potential_peak_memory_reorderr  1  s   € ð> 8:ÐØ€NÞ:äØÑ3ØÑ# AÑ&Ø!ñ"à!×,Ñ,ñ-ó
ˆð Ð1Ð1ð %8Ð#7ÐÛˆØ'™O¨AÑ.Ð1HÑHÐØ!2˜2ÑÜ˜^Ó?ˆà>×BÑBÀ2ÓFˆØÓÛ�à'¯>©>×+CÑ+CÑCÒ'ó ñ ð 	Ñ Ñ"Ø
!ñ	"à
×
(Ñ
(ñ	)ð ð
 %=�yÑ!Ü˜ÓB€NØÐ-Ð-rL   c
                ó  • U(       dH  U H  n
Xz   nUS   U-
  US   U-
  4Xz'   M     Xr   S   UR                   -   nXÄR                  -
  nUU4Xp'   gUR                  5        H  nU H  nXU'   M	     M     SnU HS  nUU   n[        S UU    5       5      nUU-  nU	U   =R                  U-  sl        UU	U   R                  -
  nUU4UU'   MU     X`   nX�   =R                  U-  sl        XÉU    R                  -
  nUU4Xp'   g)a  
Update memory tracking structures after swap (reorder version).

Updates curr_memory, buf_to_snode_last_use, and snodes_allocfree dictionaries
to reflect the new memory state after swapping candidate with group.

Args:
    candidate: Node that was moved
    gns: Group nodes
    group_tail: Last node of group
    candidate_delta_mem: Net memory change from candidate (alloc - free)
    candidate_allocfree: Candidate's allocation/free info
    group_n_to_bufs_after_swap_dealloc_by_candidate: Buffers whose deallocation moves to candidate
    post_alloc_update: Cached post-allocation memory values
    curr_memory: Current memory state dict (mutated)
    buf_to_snode_last_use: Buffer to last-use node mapping (mutated)
    snodes_allocfree: Node allocation/free info dict (mutated)
r   r   Nc              3  óN   #   • U  H  nUR                   R                  v •  M     g 7frh   ©rº   r  ©r‡   r¾   s     rB   r‰   Ú=_update_memory_tracking_after_swap_reorder.<locals>.<genexpr>­  s!   é € ð 2
âI�ð �N‰N×$Ö$ÚIùó   ‚#%)r  r  r/   Úsum)rü   r¡   rþ   r  r	  r
  Úpost_alloc_updater  r®   r­   r¢   ÚcmÚ_candidate_post_alloc_memÚ_candidate_post_free_memr  r¾   Ú"size_free_to_move_to_candidate_sumr˜   Ú_gn_post_alloc_memÚsize_free_to_move_to_candidateÚgn_post_free_memÚcandidate_post_free_mems                         rB   Ú*_update_memory_tracking_after_swap_reorderr#  t  sy  € ö< ;ÛˆBØ‘ˆBà�1‘Ð+Ñ+Ø�1‘Ð+Ñ+ðˆK‹Oñ ð Ñ# AÑ&Ð)<×)GÑ)GÑGð 	"ð &×(EÑ(EÑEð 	!ð &Ø$ð"
ˆÑð 	ð @×FÑFÖHˆÛˆCØ)2 #Ó&ó ñ Ið /0Ð&ÛˆØ"3°AÑ"6ÐÜ.1ñ 2
àFÀqÒIó2
ó /
Ð&ð 	+Ð.LÑLÐ*à˜Ñ×%Ò%Ð)GÑGÕ%Ø 2Ð5EÀaÑ5H×5RÑ5RÑ RÐØ,Ð.>Ð?ˆ�A‹ñ ð !2Ñ <ÐØÑ×)Ò)Ð-OÑOÕ)à!°YÑ$?×$IÑ$IÑIð ð 	"Øð€KÒrL   c                ó¼   • [        [        5      nUR                  U [        5       5      n[        U5      nU H!  nX'   nX†;   d  M  XH   R	                  U5        M#     U$ )a^  
Find buffers whose last use will change after swapping candidate with group.

When we swap [candidate [group]] to [[group] candidate], some buffers that
were last used by a group node will now be last used by candidate instead.
This affects memory deallocation timing.

Args:
    candidate: The node being moved
    gns: Group nodes being swapped with candidate
    buf_to_snode_last_use: Mapping of buffers to their current last-use nodes
    candidate_buffer_map: Pre-computed map of node -> buffers using that node

Returns:
    Dict mapping group nodes to buffers that will change their last-use node
)r   r.   r  r   rÓ   )	rü   r¡   r®   r°   r
  Úcandidate_bufsÚgns_setr¾   Úsnode_last_uses	            rB   Ú#_find_buffers_with_changed_last_user(  Á  sb   € ô0 	”DÓð 4ð *×-Ñ-¨i¼»ÓF€NÜ˜‹o€GãˆØ.Ñ3ˆØÕ$Ø;ÑK×RÑRÐSVÖWñ ð
 ;Ð:rL   c                óÄ   • [         R                  (       d%  [        U 5      (       a  SSU R                  5        34$ [         R                  (       d  [        U 5      (       a  gg)aA  
Check if a candidate node can be grouped with collective during reordering.

This pass processes collectives left to right, so we avoid grouping with
already-processed collectives based on configuration.

Args:
    candidate: Node to check for groupability

Returns:
    Tuple of (is_groupable, reason_if_not_groupable)
Fzcandidate contains_collective )Fr†   ©TN)r   Ú(reorder_iterative_group_with_collectivesrÑ   r”   Ú)reorder_iterative_use_runtime_estimationsr†   ©rü   s    rB   Ú_is_node_groupable_for_reorderr.  è  sU   € ô$ ×@×@Ü$ Y×/Ñ/àØ0°×1CÑ1CÓ1EÐ0FÐGðð ô ×A×AÜ˜i×(Ñ(Ø.ØrL   c                ó  ^• U nU Vs0 s H  oˆXx   R                   _M     n	n[        U	 Vs/ s H  o‰U   PM	     sn5      n
[        U Vs/ s H  o‡U   R                  PM     sn5      nSU
 SU S3m/ SQnUR                  5        VVs/ s HŽ  u  p�[	        U5      UR
                  S-  UR                  S-  UR                  S-  UR                  S-  UR                   S-  UR                  UR                  UR                  UR                  UR                  /PM�     nnn[        R                  R                  S5      (       a  SSKJn  TU" UUS	9-  mO8TS
-  mT[#        U5      S-   -  mTSR%                  ['        ["        U5      5      -  m[)        USU5      n[+        U5      U:X  d   e[-        UXV5      u  n    nTSU 3-  mTSU 3-  m[.        R1                  T5        [3        SS U4S jS9  U$ s  snf s  snf s  snf s  snnf )a�  
Format reordering statistics, log them, and return final node list.

Computes improvement metrics, creates a formatted table (using tabulate if
available), validates the reordered node count, recalculates peak memory,
and logs all information.

Args:
    stats: Per-node reordering statistics
    head: Head of the reordered linked list
    next_dict: Linked list next pointers
    original_snodes_num: Original number of nodes (for validation)
    peak_memory: Initial peak memory before reordering
    name_to_freeable_input_buf: Buffer memory tracking info
    graph_outputs: Graph output names

Returns:
    Final reordered list of scheduler nodes
zAreorder_communication_preserving_peak_memory improved overlap by z
 ns after z reorders.
)zCollective nodeúcomm_time(us)úcomp_time(us)úinitial exposed(us)úfinal exposed(us)úimprovement(us)úlimiting factorr\   r]   r_   rf   ç     @�@Útabulater   ©r7  ©Úheadersú>Please `pip install tabulate` to nicely render overlap stats.
Ú
Nz
 peak_memory_before:z
 peak_memory_after:Úartifactc                 ó   • SSS.$ )NrT   Ústring©ÚnameÚencodingro   ro   rL   rB   Ú<lambda>Ú2_format_and_log_reordering_stats.<locals>.<lambda>a  s   € ØBØ ò
rL   c                 ó   >• T $ rh   ro   )Úreorder_log_strs   €rB   rC  rD  e  s   ø€ ™?rL   ©Úmetadata_fnÚ
payload_fn)rl   r  r\   ÚitemsÚnode_summaryrb   rc   rd   re   rZ   r]   r_   rf   Ú	importlibÚutilÚ	find_specr7  rY   r    Úmapr×   r³   r   Úoverlap_logÚinfor
   )ÚstatsrÔ   rÖ   Úoriginal_snodes_numr«   rª   r©   rS   r:   rl   Útotal_improvementÚtotal_movesr:  Ú	node_infoÚrowsr7  Ú
new_snodesÚnew_peak_memoryr>   rF  s                      @rB   Ú _format_and_log_reordering_statsrZ    sL  ø€ ð8 €JÙEOÓPÂZ¸E˜*Ñ+×7Ñ7Ò7ÁZ€KÐPÜ¹[ÓIº[°E¨Ô/¹[ÑIÓJÐÜ¹JÓGºJ°5 %Ñ(×.Ô.¹JÑGÓH€Kð LÐL]ÐK^ð _Ø�˜lð	,ð ò€Gð6 !+× 0Ñ 0Ô 2ôò !3ÑˆEô ˜ÓØ×Ñ #Ñ%Ø×Ñ #Ñ%Ø×%Ñ%¨Ñ+Ø×#Ñ# cÑ)Ø×!Ñ! CÑ'Ø×%Ñ%Ø�O‰OØ×ÑØ×"Ñ"Ø×"Ñ"ó	
ñ !3ð 	ñ ô  ‡~�~×Ñ 
×+Ñ+Ý%à™8ØØñ
ñ 	
‰ð
 	ØMñ	
ˆð 	œ3˜w›<¨$Ñ.Ñ.ˆØ˜4Ÿ9™9¤S¬¨d£^Ó4Ñ4ˆä.¨t°T¸9ÓE€JÜˆz‹?Ð1Ó1Ð1Ð1Ü=ØÐ.ó Ñ€O�Q˜˜1ð Ð/°¨}Ð=Ñ=€OØÐ.¨Ð.?Ð@Ñ@€Oä×Ñ�_Ô%ÜØñ
ô +òð ÐùòK QùÚIùÚGùó&s   ˆG3«G8Á	G=ÂBHc                óœ  • SnU  H  n[        U5      (       d  M  Sn  O   U(       d  U 0 4$ [        U 5      n[        [        R                  R
                  R                  5       5      n[        [        R                  R                  5       5      n[        XU5      u  nnnn	n
nU  Vs0 s H  nU[        U5      [        U5      -  _M     nnU  Vs0 s H#  o"[        S UR                  5        5       5      _M%     nnU  Vs0 s H   nU[        S UR                   5       5      _M"     nn0 nSn[        U 5      u  nnn[        R                   nSnUn[        R"                  nSnUGb  UU   Gb  UU   nU(       a  GO[%        U5      (       d  UnM-  Ub  UU:¼  a  GOèUS-  n['        5       =nUU'   [)        UUXÍU5      u  nnnUUl        UUl        UU-
  =Ul        Ul        UUl        UU   nUnUn 0 n!Sn"UU   S   n#[        UU   5      n$[        UU   5      n%UGbY  [        R4                  (       a5  UR0                  [        R6                  * UR*                  -  :  a	  S	Ul        GO[        R:                  (       d  [        U5      (       a	  S
Ul        GOáU$U%-
  n&U&(       d  Sn'OUU   n([=        U(U&-  5      n'U'(       Ga  [?        U5      u  n)n*U)(       a±  UnU$RA                  UU   5        U%RA                  UU   5        [        R4                  (       aC  [C        U5      (       a  [E        UUUUUU5      u  nnn+UU4U!U'   [%        U5      (       d  U"UU   -  n"[G        U#UU   S   5      n#U=RH                  S-  sl$        UU   nGMl  SURK                  5        SUR                  5        V,s/ s H  n,U,RK                  5       PM     sn, SU* 3n-U-Ul        GO¢[        R4                  (       Gab  [%        U5      (       dè  UU   n.U.S:”  aÜ  [        U!5      S:”  aÍ  [G        SUR*                  UR,                  -
  5      n/[G        SUR*                  UR,                  -
  U.-
  5      n0U0U/-
  n1U!RM                  5        H/  u  n2n3[G        SU2U3-
  5      n4[G        SU2U3-
  U.-   5      n5U1U5U4-
  -  n1M1     U1S:”  a  SU. SU1 3Ul        GO¼U!RO                  5        H  u  n6u  n2n3U2U3U.-
  4U!U6'   M     OjU"S:”  ad  [)        UUXÍU5      u  nnn+[G        SUU-
  5      n/[G        SUU-
  U"-   5      n0U0U/-
  n1U1S:”  a&  SURK                  5        SU" SU1 SU SU 3
Ul        GO*[Q        UU U5      n7UU   n8U8RR                  U8RT                  -
  n9[W        UU7X›5      n:[Y        UU7U U#U9U8U:U5      u  n;n<U;U-
  U[        RZ                  -  :”  a  SU; SU 3Ul        OµU=R\                  S-  sl.        US-  n[_        UUU UUU5      n[)        UUXÍU5      u  nnnUUl        UUl        UUl        UU-
  Ul        [a        UU7U U9U8U:U<UU	U5
        U(       a4  SSK1J2n=  U=" UU7[g        U75      [Q        USU5      U
UUUUSU:5      nU(       a  OUU   nUb  GMY  UnUb	  UU   b  GM  [        Rh                  (       d  [Q        USU5      n>U>U4$ [k        UUUUUU
U5      n>U>U4$ s  snf s  snf s  snf s  sn,f )z|
Internal testing helper that also returns debug info.
Returns:
    - reordered snodes list
    - dict {snode: ReorderInfo}
FTc              3  ó@   #   • U  H  oR                  5       v •  M     g 7frh   rÂ   rÃ   s     rB   r‰   ÚI_reorder_communication_preserving_peak_memory_internal.<locals>.<genexpr>�  ó   é € ÐCÒ/B¨!Ÿ™Ÿ˜Ò/BùrÆ   c              3  ó^   #   • U  H#  n[        U5      (       a  M  UR                  v •  M%     g 7frh   ©r�   rA  ©r‡   rœ   s     rB   r‰   r]  “  ó    é € ð 
Ú4�q¼LÈ¿O‹FˆA�FŽFÒ4ùó   ‚-š-r   Nr   râ   ú unexposed by runtime estimationszcollective orderingú$data dependency detected
 candidate:z(outs:z)
 non_group_reason:úcandidate has compute z,, group contains waits, total_exposed_delta z
candidate z is collective, group_runtime:z, exposed_delta:z c_comm_time:z c_comp_time:úpeak memory new:ú	 vs base:©Ú!_debug_iterative_memory_recomputerT   )6r   r³   r   r   Úgraphr¨   r5   Úget_output_namesr±   Úestimate_op_runtimerÍ   Ú	frozensetrÇ   Úunmet_dependenciesr¸   r   Ú(reorder_iterative_debug_limit_to_reorderÚ(reorder_iterative_debug_memory_recomputerÑ   rV   ró   rb   rc   rd   re   rf   r,  Ú)reorder_iterative_extra_comm_comp_overlaprZ   Ú,reorder_iterative_unsafe_collectives_reorderrÙ   r.  Úupdater   rú   r  r]   r”   r/   rJ  r×   r  r  r(  r  Ú$reorder_iterative_peak_memory_budgetr\   r  r#  Úcomms_debugrj  r£   Úreorder_sink_verbose_loggingrZ  )?r7   Úhas_collectivesr:   rS  r¨   r©   r«   r¯   r­   r®   rª   r°   ræ   rÜ   rÝ   rR  rU  r´   rµ   r·   Ú debug_num_collectives_to_reorderÚnum_processed_collectivesÚcurrÚ debug_iterative_memory_recomputeÚiterative_recompute_errorÚ
_next_currrQ  rb   rc   rf   rü   rý   rþ   Úgroup_waitsÚgroup_runtimer  Úgroup_unmet_deps_namesÚgroup_output_namesÚdata_deps_namesÚdata_depÚcandidate_out_namesÚis_groupable_resultÚgrouping_reasonr>   rÄ   ÚmsgÚ	c_runtimeÚexposed_beforeÚexposed_afterÚexposed_deltaÚgw_comm_timeÚgw_comp_timeÚgw_exposed_beforeÚgw_exposed_afterÚgwr¡   r	  r  r
  r  r  rj  rX  s?                                                                  rB   rQ   rQ   k  sŠ  € ð €OÛˆÜ˜u×%Ó%Ø"ˆOÙñ ö Ø�rˆzÐä˜f›+Ðä$.¬q¯w©w×/CÑ/C×/HÑ/HÓ/JÓ$K€LÜ%/´·±×0HÑ0HÓ0JÓ%K€Mô 	$ F¸-ÓHñØØØØØ"Øñ
 ó0âˆEð 	Ô" 5Ó)Ô,EÀeÓ,LÑLÒLÙð ð 0ñ RXóAÚQWÈŒyÑC¨u×/@Ñ/@Ô/BÓCÓCÒCÑQWð ð Añ ó	>ò ˆEð 	Œyñ 
Ø!×4Ò4ó
ó 
ò 	
ñ ð	 ð >ð 35€Eà€Kä8¸Ó@Ñ€Eˆ5�%ô 	×=Ñ=ð %ð &'ÐØ(-€Dä×=Ñ=ð %ð !&Ðà
Ò
˜u T™{Ò6Ø˜4‘[ˆ
Þ$Ùä(¨×.Ñ.ØˆDÙà+Ñ7Ø%Ð)IÓIáØ! QÑ&Ð!ä(›]Ð*ˆˆu�T‰{Ü-MØ�%˜°]ó.
Ñ*ˆ	�9˜lð #ˆŒØ"ˆŒØ4=À	Ñ4IÐIˆÔ˜tÔ1Ø(ˆÔà˜$‘Kˆ	Øˆ
Øˆ
ØˆØˆØ(¨Ñ.¨qÑ1Ðô ",¨M¸$Ñ,?Ó!@ÐÜ'Ð(8¸Ñ(>Ó?ÐàÒ#Ü×E×EØ×"Ñ"Ü×IÑIÐIØ—.‘.ñ!ó!ð (J�Ô$Ùô !×M×MÜ'¨	×2Ñ2à'<�Ô$Ùð 5Ð7IÑIˆOÞ"Ø ‘ð '7°yÑ&AÐ#ÜÐ 3°oÑ EÓF�çÜ7UØó8Ñ4Ð# _ö 'Ø!*�Jð +×1Ñ1°-À	Ñ2JÔKØ&×-Ñ-Ð.>¸yÑ.IÔJä#×M×MÜ(¨×3Ñ3Ü6VØ )Ø %Ø %Ø (Ø 0Ø -ó7Ñ3˜I y°!ð 6?À	Ð5I˜K¨	Ñ2Ü8¸×CÑCØ)¨X°iÑ-@Ñ@˜Mä(+Ø)¨<¸	Ñ+BÀ1Ñ+Eó)Ð%ð —L’L AÑ%•LØ % iÑ 0�IÚð(Ø(1×(:Ñ(:Ó(<Ð'=¸VÐ[d×[pÑ[pÔ[rÓDsÒ[rÐVWÀQÇZÁZÆ\Ñ[rÑDsÐCtð u/Ø/>Ð.?ðAð ð
 ,/�DÔ(Ùä×E×EÐEä0°×;Ñ;Ø (¨Ñ 3�Ià  1“}¬¨[Ó)9¸AÓ)=ä),¨Q°·±ÀÇÁÑ0OÓ)P˜ä(+Ø˜tŸ~™~°·±Ñ>ÀÑJó)˜ð )6¸Ñ(F˜Ø:E×:LÑ:LÖ:NÑ6˜L¨,ä03°A°|ÀlÑ7RÓ0SÐ-ä/2Ø ! <°,Ñ#>ÀÑ#Jó0Ð,ð *Ð-=Ð@QÑ-QÑQšMñ ;Oð )¨1Ó,à"8¸¸ð DNØN[È_ð!^ð !Ô0ñ "ð "-×!2Ñ!2Ö!4ñ! ñ %Ø ,Ø ,ð %1Ø$0°9Ñ$<ð3" ¨B£ñ "5øð % qÓ(Ü2RØ% u¨hÈ-ó3Ñ/˜	 9¨aô *-¨Q°	¸IÑ0EÓ)F˜ä(+¨A¨y¸9Ñ/DÀ}Ñ/TÓ(U˜Ø(5¸Ñ(F˜Ø(¨1Ó,à",¨Y×-?Ñ-?Ó-AÐ,Bð C2Ø2?°ð A2Ø2?°ÀÈiÈ[ÐXeÐfoÐepð!rð !Ô0ñ
 "ô ,IØ˜J¨ó,ˆCð 0@À	Ñ/JÐà#×.Ñ.Ð1D×1NÑ1NÑNð  ô  4Ø˜sÐ$9óð <ô 9ØØØØ%Ø'Ø'ØCØ ó	ñ /ˆNÐ.ð  Ñ,Ø¤× QÑ QÑQóRð ' ~Ð&6°iÀ¸}ÐMð Ô$ð Ø�JŠJ˜!‰O�JØ˜1ÑˆKä4Ø˜: z°5¸%ÀóˆEô 2RØ�e˜X¸ó2Ñ.ˆI�y ,ð 'ˆDŒNØ&ˆDŒNØ ,ˆDÔØ!*¨YÑ!6ˆDÔä6ØØØØ#Ø#Ø?Ø"ØØ%Ø ôö 0õ Ká,MØØÜ  Ó%Ü1°%¸¸uÓEØ.Ø!ØØ Ø$ØBØCó-Ð)ö -ØØ˜jÑ)ˆIðC Ô#ðD ˆðK Ñ
˜u T™{Ô6ôN ×4×4Ü2°5¸$ÀÓFˆ
Ø˜5Ð Ð ä1ØØØØØØ"Øó€Jð �uÐÐùòo	0ùòAùò>ùòp Ets   Â%"Z:Ã*Z?Ã='[Î$[	
c                ó‚  ^^^^^^^^^^^^• 0 n0 m0 0 0 smmm[        U 5       H|  u  pVUR                  5        H  nXdU'   M	     UR                  5        H  nUTU'   M
     UTUR                  5       '   UR                  5       n	[        R
                  TU	'   STU	'   UTU	'   M~     Sn
U  Hš  nU(       ab  [        U5      (       aR  U
TUR                  5       '   UR                   H(  nTU   R                  5       n[        TU   U
5      TU'   M*     U
S-  n
Ml  U(       d  Mu  [        U5      (       d  M‡  STUR                  5       '   Mœ      " UUUU4S jS5      mU  Vs0 s H   nU[        S UR                   5       5      _M"     snm/ m[        [        5      mU  Vs0 s H  of[        U5      _M     snmTR                  5        HN  u  pm[        U5      S:X  a  [         R"                  " TT" U5      5        U H  nTU   R%                  U5        M     MP     / mUUUUU4S jmU4S jmUUUU4S jnT(       aQ  [         R&                  " T5      R(                  nU(       a  [        U5      (       a	  U" U5        OT" U5        T(       a  MQ  TR+                  5        H  n[        U5      S:X  a  M   S	T 35       e   T$ s  snf s  snf )
aŽ  
Schedule `snodes` for various comm optimization objectives.

Args:
    snodes: the nodes to be scheduled.
    raise_comms: whether to greedily schedule collectives as early as possible
    sink_wait: whether to greedily schedule waits as late as possible
    reorder_compute_for_overlap: whether to reorder compute nodes to
        optimize for compute/communication overlapping.

Returns:
    The new schedule order.

Some notes on the synergy between different options:
    - `raise_comms` provides more overlapping oppurtunies for `reorder_compute_for_overlap`.
    - When both `raise_comms` and `sink_waits` is `True`, `raise_comms` is prioritized.
r   r   c                  ó2   >• \ rS rSrSU UUU4S jjrS rSrg)Ú$_schedule_for_comm.<locals>.Runnablei  c                ó¢   >• Xl         [        [        UR                  5       5      5      nTU   R	                  5       nTU   TU   TU   4U l        g rh   )r:   ÚnextÚiterÚget_operation_namesr”   Úscore)rk   r:   rA  Ú
fused_nameÚname_to_fused_nodeÚscores_0Úscores_1Úscores_2s       €€€€rB   Ú__init__Ú-_schedule_for_comm.<locals>.Runnable.__init__  sT   ø€ ØŒJÜœ˜U×6Ñ6Ó8Ó9Ó:ˆDØ+¨DÑ1×:Ñ:Ó<ˆJà˜Ñ$Ø˜Ñ$Ø˜Ñ$ðˆD�JrL   c                ó4   • U R                   UR                   :  $ rh   ©r™  )rk   Úothers     rB   Ú__lt__Ú+_schedule_for_comm.<locals>.Runnable.__lt__  s   € Ø—:‘: §¡Ñ+Ð+rL   )r™  r:   N)rí   rX   )rp   rq   rr   rs   rŸ  r¤  rw   )r›  rœ  r�  rž  s   €€€€rB   ÚRunnabler”    s   ø† ÷	ò 	õ	,rL   r¦  c              3  ó8   #   • U  H  oR                   v •  M     g 7frh   )rA  )r‡   Údeps     rB   r‰   Ú%_schedule_for_comm.<locals>.<genexpr>  s   é € ÐGÒ.F sŸ(ž(Ò.Fùr‹   c                óø   >• TR                  U 5        U R                  5        HT  nTU    HH  n TU    R                  U5        [        TU    5      S:X  d  M+  [        R
                  " TT" U 5      5        MJ     MV     g)zE
Schedules `snode` and put all unblocked nodes onto the ready queue.
r   N)rÓ   r•   Úremover³   ÚheapqÚheappush)r:   Úbuf_namer¦  Úbuffer_usersÚreadyÚ	scheduledrß   s     €€€€€rB   ÚscheduleÚ$_schedule_for_comm.<locals>.schedule#  sl   ø€ ð 	×Ñ˜ÔØ×.Ñ.Ö0ˆHØ% hÔ/�Ø˜5Ñ!×(Ñ(¨Ô2Ü�z %Ñ(Ó)¨QÕ.Ü—N’N 5©(°5«/Ö:ó 0ò 1rL   c                 óØ   >• T V s/ s H=  n [        U R                  5      (       a  M  [        U R                  5      (       a  M;  U PM?     nn [        U5      S:X  a  g[	        US S9$ s  sn f )zP
Return the next node in the ready queue that's neither a collective or
a wait.
r   Nc                ó   • U R                   $ rh   r¢  ©rˆ   s    rB   rC  ÚG_schedule_for_comm.<locals>.get_overlapping_candidate.<locals>.<lambda>:  s   € ¨Q¯WªWrL   ©Úkey)r   r:   r   r³   Úmin)rˆ   Ú
candidatesr°  s     €rB   Úget_overlapping_candidateÚ5_schedule_for_comm.<locals>.get_overlapping_candidate.  sf   ø€ ñ ó
â�Ü& q§w¡w×/ó ä8EÀaÇgÁg×8N÷ Ùð 	ð 
ô
 ˆz‹?˜aÓØÜ�:Ñ#4Ñ5Ð5ùò
s   †A'¨A'ÁA'c                ó  >• [        U 5      (       d   eT" U 5        TU    nUS:”  aQ  T" 5       =nbG  TR                  U5        T" UR                  5        UTUR                     -  nUS:”  a  T" 5       =nb  MG  [        R                  " T5        g)z¨
Schedules collective node `snode`, along with one or more compute nodes
to overlap with it. The strategy is described in the comment of
`reorder_compute_for_overlap`.
r   N)r   r«  r:   r¬  Úheapify)r:   Úcollective_costrü   r¼  r°  r²  Úsnode_to_costs      €€€€rB   Úschedule_collective_for_overlapÚ;_schedule_for_comm.<locals>.schedule_collective_for_overlap<  sŽ   ø€ ô # 5×)Ñ)Ð)Ð)Ù�Œà'¨Ñ.ˆà˜aÓÙ7Ó9Ð9�ÑFà�L‰L˜Ô#á�Y—_‘_Ô%à˜}¨Y¯_©_Ñ=Ñ=ˆOð ˜aÓÙ7Ó9Ð9�ÓFô 	�Š�eÕrL   z;Detected unscheduled nodes. Nodes with unmet dependencies: )r4   r•   r˜  r”   ÚsysÚmaxsizer   Ú	ancestorsrº  r   r   ro  r   rm  rJ  r³   r¬  r­  r¼   Úheappopr:   r/   )r7   rF   rG   rH   Úbuf_name_to_snoderA   r:   r®  Úop_nameÚ	node_nameÚcomm_idxÚancestorÚanc_fused_nameÚdepsr¨  rÂ  r¦  r¯  r¼  r›  r°  r²  r±  rœ  r�  rž  rÁ  rß   s                   @@@@@@@@@@@@rB   rJ   rJ   Ã  s¤  ÿû€ ðL ÐØÐØ#% r¨2Ð €Hˆh˜Ü Ö'‰
ˆØ×.Ñ.Ö0ˆHØ*/˜hÓ'ñ 1ð ×0Ñ0Ö2ˆGØ*/Ð˜wÓ'ñ 3à/4Ð˜5Ÿ>™>Ó+Ñ,à—N‘NÓ$ˆ	Ü!Ÿk™kˆ�ÑØˆ�ÑØ!ˆ�Óñ (ð €HÛˆÞÔ.¨u×5Ñ5Ø)1ˆH�U—^‘^Ó%Ñ&Ø!ŸOœO�Ø!3°HÑ!=×!FÑ!FÓ!H�Ü+.¨x¸Ñ/GÈÓ+R�˜Ó(ñ ,ð ˜‰MŠHßˆZœM¨%×0Ó0Ø)*ˆH�U—^‘^Ó%Ó&ñ ÷,÷ ,ñ  ó<âˆEð 	ŒzÑG¨e×.FÒ.FÓGÓGÒGÙñ<€Jð
 €EÜ=HÌÓ=T€LÙDJÓKÂF¸5Ô/°Ó6Ò6ÁFÑK€Mà!×'Ñ'Ö)‰ˆÜˆt‹9˜‹>Ü�NŠN˜5¡(¨5£/Ô2ÛˆCØ˜Ñ×!Ñ! %Ö(ó ñ *ð €I÷	;ñ 	;õ6÷ð ö* Ü—’˜eÓ$×*Ñ*ˆÞÔ#6°u×#=Ñ#=Ù+¨EÕ2á�UŒO÷ ˆ%ð ×!Ñ!Ö#ˆÜ�4‹y˜A�~ð 	
ØIÈ*ÈÐVó	
ˆ~ñ $ð ÐùòU<ùò Ls   Å'J7ÆJ<c           
     ó�  • [         R                  R                  5       (       d  U $ U  Vs/ s H  n[        U5      (       d  M  UPM     nn[	        S[        U5      5       H^  n[        [        XE   R                  5       5      5      nXES-
     R                  5        H  nXE   R                  [        XvSS95        M      M`     U $ s  snf )z¼
Decide global ordering of comms, by just enforcing the ordering that's in the input graph
(might not be the same ordering as the eager mode program).
TODO: Come up with a better approach
r   T©Úmutating_bufr›   )r0   r)   Úis_availabler   r,   r³   r–  r—  r•   Úadd_fake_depr   )ÚnodesÚname_to_bufr›  r˜   Ú
comm_nodesr¶   rÑ  r¾   s           rB   Údecide_global_ordering_of_commsr×  _  s©   € ô ×Ñ×)Ñ)×+Ñ+Øˆá"Ó=šU˜Ô&9¸!×&<—!™U€JÐ=ä�1”c˜*“oÖ&ˆäœD ¡×!?Ñ!?Ó!AÓBÓCˆØ !™eÑ$×5Ñ5Ö7ˆCØ‰M×&Ñ&Ü˜ÀÑEöó 8ñ 'ð €Lùò >s   ªCÁCc                  ó²   • \ rS rSr% SrS\S'   SrS\S'   SrS\S'   SrS\S	'   S
r	S\S'   Sr
S\S'   SrS\S'   SrS\S'   SrS\S'   S
rS\S'   \S 5       rSrg)ÚSinkWaitInfoiw  r   r[   r]   r^   rY   r_   r\   Ú
moves_inforX   rZ   r`   ra   rb   rc   rd   re   rf   c                ó4   • U R                   U R                  -
  $ rh   ri   rj   s    rB   rl   ÚSinkWaitInfo.improvement„  rn   rL   ro   N)rp   rq   rr   rs   r]   ru   r_   r\   rÚ  rZ   rb   rc   rd   re   rf   rv   rl   rw   ro   rL   rB   rÙ  rÙ  w  sw   ‡ à€GˆSÓØ€L�#ÓØ€Eˆ3ƒNØ€J�ÓØ!€O�SÓ!Ø€IˆuÓØ€IˆuÓØ!€O�UÓ!Ø€M�5ÓØ€L�#Óàñ9ó ó9rL   rÙ  c                óV  • [        U 5      (       a  SSU R                  5        34$ [        U 5      (       a  SSU R                  5        34$ [        R                  (       dJ  [        U 5      (       a  SSU R                  5        34$ [        U 5      (       a  SSU R                  5        34$ g)a0  
Check if a candidate node can be grouped during sink_waits pass.

Sink Waits traverses waits right to left, so we don't group with
processed waits on the right or with async collectives.

Args:
    candidate: Node to check for groupability

Returns:
    Tuple of (is_groupable, reason_if_not_groupable)
Fzcandidate contains wait ú$candidate contains_async_collective zcandidate contains collective zcandidate contains gemm_like r*  )r   r”   rÑ   r   Ú&sink_iterative_use_runtime_estimationsr   r†   r-  s    rB   Ú!_is_node_groupable_for_sink_waitsrà  ‰  sÄ   € ô" �Y×ÑØÐ0°×1CÑ1CÓ1EÐ0FÐGÐGÐGÜ  ×+Ñ+àØ2°9×3EÑ3EÓ3GÐ2HÐIð
ð 	
ô
 ×>×>ô
 ˜y×)Ñ)àØ0°×1CÑ1CÓ1EÐ0FÐGðð ô ˜i×(Ñ(àØ/°	×0BÑ0BÓ0DÐ/EÐFðð ð rL   c	                ó`  • US   n	Xy   S   X‰   R                   -
  n
U(       d@  X£R                   -   nUX³R                  -
  4Xp'   U H  nX|   nUS   U-   US   U-   4X|'   M     gU /UQ HC  nX^   nXŽ   =R                  UR                  US5      -  sl        UXøU   R                  -
  4X~'   ME     g)aâ  
Update memory tracking structures after swap (sink_waits version).

Updates curr_memory and snodes_allocfree dictionaries to reflect the new
memory state after swapping candidate with group.

Args:
    candidate: Node that was moved
    gns: Group nodes
    candidate_delta_mem: Net memory change from candidate (alloc - free)
    candidate_allocfree: Candidate's allocation/free info
    group_n_to_bufs_after_swap_dealloc_instead_of_candidate: Buffers whose deallocation moves from candidate to group
    post_alloc_update: Cached post-allocation memory values
    size_free_delta_update: Cached size-free delta values
    curr_memory: Current memory state dict (mutated)
    snodes_allocfree: Node allocation/free info dict (mutated)
r   r   N)r  r  r  )rü   r¡   r  r	  Ú7group_n_to_bufs_after_swap_dealloc_instead_of_candidater  Úsize_free_delta_updater  r­   rý   Úpre_group_memÚcandidate_post_allocr¢   r  r˜   Ú
post_allocs                   rB   Ú-_update_memory_tracking_after_swap_sink_waitsrç  ´  sè   € ð8 �Q‘€JØÑ+¨AÑ.Ð1AÑ1M×1XÑ1XÑX€MÞBØ,×/MÑ/MÑMÐà Ø ×#@Ñ#@Ñ@ð"
ˆÑó ˆBØ‘ˆBà�1‘Ð+Ñ+Ø�1‘Ð+Ñ+ðˆK‹Oñ ð 	àÐ˜#ÓˆØ&Ñ)ˆ
ØÑ×%Ò%Ð)?×)CÑ)CÀAÀqÓ)IÑIÕ%àØ¨!Ñ,×6Ñ6Ñ6ð
ˆ‹ò rL   c	                óü  • Xr   S   X‚   R                   -
  n	0 n
0 nSnU(       d  [        X4-   X•R                   -   5      nXÊU4$ X•R                   -   nXÚU '   Un[        S [        R                  R                  UR                  5       5       5       5      nU* X°'   XN-   nU HX  nUU   S   U-   nUU
U'   [        UU5      nSnUU;   a,  UU   nU H  nUUR                  R                  -  nM     UUU'   UU-  nMZ     XÊU4$ )aO  
Calculate potential peak memory after swapping candidate with group (sink_waits version).

Computes new memory levels for all affected nodes and returns the potential
peak memory along with cached post-allocation and size-free delta values.

Args:
    candidate: Node being moved
    gns: Group nodes
    group_head: First node of group
    group_peak_memory: Current peak memory within the group
    candidate_delta_mem: Net memory change from candidate (alloc - free)
    candidate_allocfree: Candidate's allocation/free info
    group_n_to_bufs_after_swap_dealloc_instead_of_candidate: Buffers whose deallocation moves from candidate to group
    curr_memory: Current memory state dict
    snodes_allocfree: Allocation/free info for all nodes

Returns:
    Tuple of (potential_peak_memory, post_alloc_update_dict, size_free_delta_update_dict)
r   c              3  óN   #   • U  H  nUR                   R                  v •  M     g 7frh   r  r  s     rB   r‰   Ú>_calculate_potential_peak_memory_sink_waits.<locals>.<genexpr>  s%   é € ð &ò
ˆCð 	�‰× Ö ò
ùr  )	r  r  r  Ú	itertoolsÚchainÚfrom_iterabler/   rº   r  )rü   r¡   rý   r  r  r	  râ  r  r­   rä  r  Ú_size_free_delta_updater  rå  Úcandidate_size_free_to_moveÚ	delta_memr¢   Úgn_post_allocÚgn_size_free_to_addr  r¾   s                        rB   Ú+_calculate_potential_peak_memory_sink_waitsró  é  sT  € ð>  Ñ+¨AÑ.Ð1AÑ1M×1XÑ1XÑX€Mà79ÐØ<>Ðà€NÞBäØÑ3Ø×:Ñ:Ñ:ó
ˆð Ð3JÐJÐJà(×+IÑ+IÑIÐØ$8�yÑ!Ø)€NÜ"%ñ &ä—?‘?×0Ñ0ØC×JÑJÓLô
ó&ó #Ðð +FÐ)EÐÑ&Ø#ÑA€IÛˆØ# B™¨Ñ*¨YÑ6ˆØ!.Ð˜2ÑÜ˜^¨]Ó;ˆØÐØÐHÓHØJÈ2ÑNˆDÛ�Ø# s§~¡~×'?Ñ'?Ñ?Ò#ñ à*=Ð# BÑ'ØÐ(Ñ(Š	ñ ð Ð/FÐFÐFrL   c                óp   • X1   nU(       a  XU'   XcU '   X@   nU(       a  X#U'   XtU'   XU'   XU '   X:X  a  U $ U$ )a…  
Swap positions of candidate and group in doubly-linked list (sink_waits version).

Transforms (moves candidate to the left):
group_head_prev -> group_head...group_tail -> candidate -> candidate_next
Into:
group_head_prev -> candidate -> group_head...group_tail -> candidate_next

Args:
    candidate: Node to swap with group
    group_head: First node of group
    group_tail: Last node of group
    prev_dict: Dictionary mapping nodes to their previous nodes
    next_dict: Dictionary mapping nodes to their next nodes
    head: Current head of the linked list

Returns:
    New head of the linked list (may change if group_head was the head)
ro   )rü   rý   rþ   r÷   rÖ   rÔ   Úgroup_head_prevÚcandidate_nexts           rB   Ú+_perform_double_linked_list_swap_sink_waitsr÷  /  sa   € ð8  Ñ+€OÞØ%.�/Ñ"Ø*ˆiÑð Ñ)€NÞØ$.�.Ñ!Ø*ˆjÑð &ˆjÑØ%ˆiÑð ÓØÐØ€KrL   c                ó.  ^• / SQnU R                  5        VV	s/ s H™  u  p‰[        U5      U	R                  S-  U	R                  S-  U	R                  S-  U	R
                  S-  U	R                  S-  U	R                  U	R                  U	R                  U	R                  U	R                  U	R                  /PM›     n
nn	Sm[        R                  R                  S5      (       a  SSKJn  TU" U
US9-  mO8TS-  mT[#        U5      S	-   -  mTS	R%                  ['        ["        U
5      5      -  m[(        R+                  T5        [-        US
U5      n[/        U5      U:X  d   e[1        XÅU5      u  n    nTSU 3-  mTSU 3-  m[3        SS U4S jS9  U$ s  sn	nf )a�  
Format sink_waits statistics, log them, and return final node list.

Computes improvement metrics, creates a formatted table (using tabulate if
available), validates the reordered node count, recalculates peak memory,
and logs all information.

Args:
    stats: Per-node sink_waits statistics
    head: Head of the reordered linked list
    next_dict: Linked list next pointers
    original_snodes_num: Original number of nodes (for validation)
    peak_memory: Initial peak memory before reordering
    name_to_freeable_input_buf: Buffer memory tracking info
    graph_outputs: Graph output names

Returns:
    Final reordered list of scheduler nodes
)z	Wait noder0  r1  r2  r3  r4  r5  r]   r_   r\   rÚ  rf   r6  r^   r7  r   r8  r9  r;  r<  Nz*
 sink_waits_iterative peak_memory_before:z)
 sink_waits_iterative peak_memory_after:r=  c                 ó   • SSS.$ )NÚsink_waits_iterative_infor?  r@  ro   ro   rL   rB   rC  Ú2_format_and_log_sink_waits_stats.<locals>.<lambda>±  s   € Ø/Ø ò
rL   c                 ó   >• T $ rh   ro   )Úlog_strs   €rB   rC  rû  µ  s   ø€ ™7rL   rG  )rJ  rK  rb   rc   rd   re   rl   rZ   r]   r_   r\   rÚ  rf   rL  rM  rN  r7  rY   r    rO  rP  rQ  r×   r³   r   r
   )rR  rÔ   rÖ   rS  r«   rª   r©   r:  r:   rQ  rW  r7  rX  rY  r>   rý  s                  @rB   Ú _format_and_log_sink_waits_statsrþ  `  s´  ø€ ò8€Gð: !Ÿ;™;œ=ôò )‰KˆEô ˜ÓØ�N‰N˜SÑ Ø�N‰N˜SÑ Ø× Ñ  3Ñ&Ø×Ñ Ñ$Ø×Ñ˜sÑ"Ø× Ñ Ø�L‰LØ×ÑØ�J‰JØ�O‰OØ×Ñó	
ñ )ð 	ñ ð" €GÜ‡~�~×Ñ 
×+Ñ+Ý%à‘8ØØñ
ñ 	
‰ð
 	ÐTÑTˆØ”3�w“< $Ñ&Ñ&ˆØ�4—9‘9œS¤ d›^Ó,Ñ,ˆÜ×Ñ�WÔÜ.¨t°T¸9ÓE€JÜˆz‹?Ð1Ó1Ð1Ð1Ü=Ø°ó Ñ€O�Q˜˜1ð Ð<¸[¸MÐJÑJ€GØÐ;¸OÐ;LÐMÑM€GÜØñ
ô #òð Ðùó[s   ™B Fc                ó  • [        [        5      nUR                  U [        5       5      nU HP  nX&   nXp:w  a  M  UR                  R
                  nSn	U H  n
X¨;   d  M
  U
n	M     U	c  M=  XI   R                  U5        MR     U$ )a}  
Find buffers whose last use will change after swapping in sink_waits pass.

When we swap [group] candidate to candidate [group], some buffers that
were last used by candidate will now be last used by a group node instead.
This is the opposite direction from the reorder version.

Args:
    candidate: The node being moved (currently last use)
    gns: Group nodes being swapped with candidate
    buf_to_snode_last_use: Mapping of buffers to their current last-use nodes
    candidate_buffer_map: Pre-computed map of node -> buffers using that node

Returns:
    Dict mapping group nodes to buffers that will change their last-use node
N)r   r.   r  r   rº   r»   rÓ   )rü   r¡   r®   r°   râ  r%  r¾   r'  r»   Úlast_succ_gnr¢   s              rB   Ú._find_buffers_with_changed_last_use_sink_waitsr  º  s˜   € ô0 	”DÓð <ð *×-Ñ-¨i¼»ÓF€NãˆØ.Ñ3ˆØÓ&Ùð —^‘^×.Ñ.ˆ
ØˆÛˆBØÕØ!’ñ ð ÑÙð 	@ÑM×TÑTØö	
ñ% ð, CÐBrL   c                ó  • [        U 5      nUS:X  a  U 0 4$ [        [        R                  R                  R                  5       5      n[        [        R                  R                  5       5      n[        XU5      u  nnnnnn	[        U 5      u  p«n0 nU  Vs0 s H  nU[        U5      [        U5      -  _M     nnU  Vs0 s H#  oî[        S UR                  5        5       5      _M%     nnU  Vs0 s H   nU[        S UR                   5       5      _M"     nnU S   n[        5       n[        R                  n[        R                   nSnUGby  U
U   Gbr  U
U   nU(       a  GOdUb  [        U5      U:¼  a  GOP[#        U5      (       a  UU;  d  UnMG  UR%                  U5        ['        5       =nUU'   [)        UXÊUUU5      u  nnnUU-
  =Ul        Ul        UUl        UUl        UUl        UU   nUnUn0 nSn UU   S   n![        UU   5      n"[5        U5      n#UGb�  [        R6                  (       a5  UR,                  [        R8                  * UR.                  -  :  a	  SUl        GOSU"(       d  Sn$OUU   n%[=        U%U"-  5      n$[        R>                  (       d*  [A        U5      (       a  SURC                  5        3Ul        GO÷U#=(       a    [5        U5      n&U$(       d  U&(       Ga  [E        U5      u  n'n(U'(       a¯  UnU"RG                  UU   5        U#=(       d    [5        U5      n#[        R6                  (       aA  [5        U5      (       a1  [I        UX¿UU5      u  nnn)UU4UU'   [A        U5      (       d  U UU   -  n [K        U!UU   S   5      n!U=RL                  S	-  sl&        UU   nGM‘  U$(       d7  [        RN                  (       d!  U&(       a  S
URC                  5        3Ul        GOÓOSURC                  5        SU( 3Ul        GOµ[        R6                  (       GaS  [Q        URR                  5      (       aJ  [)        UUU
UUU5      u  nnn)[K        SUU-
  5      n*[K        SUU-
  U -   5      n+U+U*:”  a  SU* SU+ 3Ul        GO;[A        U5      (       dß  UU   n,U,S:”  aÔ  [        U5      S:”  aÅ  [K        SUR.                  UR0                  -
  5      n-[K        SUR.                  UR0                  -
  U,-
  5      *   URU                  5        H+  u  n.n/U-[K        SU.U/-
  5      [K        SU.U/-
  U,-   5      -
  -  n-M-     U-S:”  a  SU, SU- 3Ul        GOsURW                  5        H  u  n0u  n.n/U.U/U,-
  4UU0'   M     [Y        UUU5      n1UU   n2U2RZ                  U2R\                  -
  n3[_        UU1Xy5      n4[a        UU1UU!U3U2U4UU5	      u  n5n6n7U5U-
  U[        Rb                  -  :”  a  SU5 SU 3Ul        OÕU=Rd                  S	-  sl2        U=Rf                  SURC                  5        3-  sl3        [i        UUUX«U5      n[)        UXÊUUU5      u  nnnUUl        UUl        UU-
  Ul        UUl        [k        UU1U3U2U4U6U7UU5	        U(       a4  S	SK6J7n8  U8" UU1[q        U15      [Y        US U5      UUUUUSU45      nU(       a  OUU   nUb  GM�  UnUb	  U
U   b  GMr  [        Rr                  (       d  [Y        US U5      n9U9U4$ [u        UUUUUUU5      n9U9U4$ s  snf s  snf s  snf )Nr   c              3  ó@   #   • U  H  oR                  5       v •  M     g 7frh   rÂ   rÃ   s     rB   r‰   Ú1_sink_waits_iterative_internal.<locals>.<genexpr>  r^  rÆ   c              3  ó^   #   • U  H#  n[        U5      (       a  M  UR                  v •  M%     g 7frh   r`  ra  s     rB   r‰   r    rb  rc  éÿÿÿÿFrâ   rd  rÞ  r   z$collective ordering
 with candidate:re  z
 non_group_reason:z"candidate is wait, exposed_before:z vs exposed_after:rf  z2, group contains collectives, total_exposed_delta rg  rh  rê   ri  Úsink_waits_iterative);r³   r   r   rk  r¨   r5   rl  r±   r¸   rm  rÍ   rn  rÇ   ro  r   rq  Ú(sink_waits_iterative_debug_limit_to_sinkr   r¼   rÙ  rú   rd   re   rb   rc   rf   r   rß  Ú&sink_iterative_extra_comm_comp_overlaprZ   rÙ   Ú*sink_waits_iterative_swap_with_collectivesrÑ   r”   rà  rt  ró   r  r]   Ú/sink_waits_iterative_unsafe_collectives_reorderr   r€   r/   rJ  r×   r  r  r  ró  Ú!sink_iterative_peak_memory_budgetr\   rÚ  r÷  rç  rv  rj  r£   rw  rþ  ):r7   rS  r¨   r©   r«   r¯   r­   r®   rª   r°   r´   rµ   r·   rR  r:   ræ   rÜ   rÝ   r{  Úprocessed_waitsr|  Údebug_num_sink_waits_to_reorderr}  Ú
_prev_currrQ  rb   rc   rf   rü   rý   rþ   Úgroup_collsr€  r  r‚  Úgroup_contains_collectiver„  Úcandidate_dep_namesÚboth_contain_commsÚ_is_groupableÚgroupable_reasonr>   rŠ  r‹  r‰  rŒ  Úgc_comm_timeÚgc_comp_timeÚgcr¡   r	  r  râ  r  r  rî  rj  rX  s:                                                             rB   Ú_sink_waits_iterative_internalr  ñ  s‡  € ô ˜f›+ÐØ˜aÓØ�rˆzÐÜ$.¬q¯w©w×/CÑ/C×/HÑ/HÓ/JÓ$K€LÜ%/´·±×0HÑ0HÓ0JÓ%K€Mô 	$ F¸-ÓHñØØØØØ"Øô 9¸Ó@Ñ€E�%à35€Eñ ó0âˆEð 	Ô" 5Ó)Ô,EÀeÓ,LÑLÒLÙð ð 0ñ RXóAÚQWÈŒyÑC¨u×/@Ñ/@Ô/BÓCÓCÒCÑQWð ð Añ ó	>ò ˆEð 	Œyñ 
Ø!×4Ò4ó
ó 
ò 	
ñ ð	 ð >ð )/¨r©
€Dä “l€Oä×=Ñ=ð %ô 	×=Ñ=ð $ð !&ÐØ
Ò
˜u T™{Ò6Ø˜4‘[ˆ
Þ$Ùà+Ñ7Ü�OÓ$Ð(GÓGáä˜d×#Ñ#¨°OÓ(CØˆDÙà×Ñ˜DÔ!Ü)›^Ð+ˆˆu�T‰{Ü-MØ�% Ð*:¸Mó.
Ñ*ˆ	�9˜lð 5>À	Ñ4IÐIˆÔ˜tÔ1Ø"ˆŒØ"ˆŒØ(ˆÔà˜$‘Kˆ	Øˆ
Øˆ
ØˆØˆØ(¨Ñ.¨qÑ1Ðô (Ð(8¸Ñ(>Ó?ÐÜ$7¸Ó$=Ð!àÒ#Ü×B×BØ×"Ñ"Ü×FÑFÐFÈÏÉÑWóXð (J�Ô$Ùö &Ø ‘ð '4°IÑ&>Ð#ÜÐ 3Ð6HÑ HÓI�ô  ×J×JÜ,¨Y×7Ñ7à>¸y×?QÑ?QÓ?SÐ>TÐUð Ô(ñ ð ";÷ "Ô?RØó@Ðö ×-Ü2SØó3Ñ/�Ð/ö !Ø!*�Jð '×-Ñ-Ð.>¸yÑ.IÔJà1×SÔ5HÈÓ5Sð .ô
 %×K×KÜ/°	×:Ñ:ä2RØ% uÐ8HÈ-ó3Ñ/˜	 9¨að 3<¸YÐ1G˜ IÑ.Ü8¸×CÑCØ)¨X°iÑ-@Ñ@˜Mä(+Ø)¨<¸	Ñ+BÀ1Ñ+Eó)Ð%ð —L’L AÑ%•LØ % iÑ 0�IÚÞ!ä(×X×XÞ.ð1Ø1:×1CÑ1CÓ1EÐ0FðHð Ô,ñ øð(Ø(1×(:Ñ(:Ó(<Ð'=Ø.Ð/?Ð.@ðBð Ô(ñ
 ä×B×BÐBÜ˜9Ÿ>™>×*Ñ*ô /OØ!ØØØ Ø(Ø%ó/Ñ+�I˜y¨!ô &)¨¨I¸	Ñ,AÓ%B�Nä$'¨¨9°yÑ+@À=Ñ+PÓ$Q�Mð % ~Ó5ð/Ø/=Ð.>Ð>PÐQ^ÐP_ðað Ô,ñ ô 1°×;Ñ;ð !)¨Ñ 3�Ià  1“}¬¨[Ó)9¸AÓ)=ô ),ØØ ŸN™N¨T¯^©^Ñ;ó)˜ô
 ˜Q §¡°·±Ñ ?À)Ñ KÓLÑLØ:E×:LÑ:LÖ:NÑ6˜L¨,à)¬S°°LÀ<Ñ4OÓ-PÔSVØ ! <°,Ñ#>ÀÑ#JóTñ .ñ šMñ ;Oð
 )¨1Ó,à"8¸¸ð D8Ø8E°ð!Hð !Ô0ñ "ð "-×!2Ñ!2Ö!4ñ! ñ %Ø ,Ø ,ð %1Ø$0°9Ñ$<ð3" ¨B£ñ "5ô ,IØ˜J¨ó,ˆCð 0@À	Ñ/JÐà#×.Ñ.Ð1D×1NÑ1NÑNð  ô ?Ø˜sÐ$9óð Dô <ØØØØ%Ø'Ø'ØKØ Ø$ó
ñ HˆNÐ.Ð0Gð  Ñ,Ø¤× NÑ NÑNóOð ' ~Ð&6°iÀ¸}ÐMð Ô$ð à�JŠJ˜!‰O�JØ�OŠO  9×#5Ñ#5Ó#7Ð"8Ð9Ñ9�Oä?Ø˜: z°5ÀóˆEô 2RØ�e HÐ.>Àó2Ñ.ˆI�y ,ð 'ˆDŒNØ&ˆDŒNØ!*¨YÑ!6ˆDÔØ ,ˆDÔä9ØØØ#Ø#ØGØ"Ø'ØØ ô
ö 0ÝJá,MØØÜ  Ó%Ü1°%¸¸uÓEØ.Ø!ØØ Ø$Ø*ØKó-Ð)ö -Øà˜jÑ)ˆIðQ Ô#ðR ˆðY Ñ
˜u T™{Ô6ô\ ×4×4Ü2°5¸$ÀÓFˆ
Ø˜5Ð Ð ä1ØØØØØØ"Øó€Jð �uÐÐùòo	0ùòAùò>s   Â"[?Â=*\Ã-'\	c                ó   • [        U 5      S   $ )a_  
Similarly to reorder_communication_preserving_peak_memory this pass will try to iteratively
push Wait nodes later, recomputing estimated peak memory before each swap,
and preventing peak memory regressions.

Pass will be applied to every Wait node. If there are immediate dependencies with next node,
pass will try to group them together and on the next step to swap the group with next candidate.

If _inductor.config_comms.sink_iterative_use_runtime_estimations is set True,
pass will stop reordering of Wait once corresponding Collective is unexposed,
based on runtime estimations.

inductor.config_comms.sink_iterative_peak_memory_budget allows to tune how much pass
can regress initial peak memory.
E.g.:
sink_iterative_peak_memory_budget == 0.0 - No regression of initial peak memory is allowed
sink_iterative_peak_memory_budget == 0.2 - Pass can improve comm-compute overlap, sacrificing
20% of initial peak memory value.

inductor.config_comms.sink_iterative_extra_comm_comp_overlap config allows to more aggressively
sink waits, stopping only when overlap_compute >= (1 + extra_comm_comp_overlap) * comm_time
r   )r  rK   s    rB   r  r  @  s   € ô. *¨&Ó1°!Ñ4Ð4rL   c                ó¾   • [         R                  S:X  a  U R                  5       nU$ [        [         R                  5      (       d   e[         R                  " U 5      nU$ )z3
Returns estimated op runtime in milliseconds (ms)
r~   )r   rm  r'   Úcallable)r:   Úruntimes     rB   rm  rm  Z  sU   € ô ×!Ñ! YÓ.Ø×-Ñ-Ó/ˆð €Nô œ×2Ñ2×3Ñ3Ð3Ð3Ü×,Ò,¨UÓ3ˆØ€NrL   c           
     ó�  • U R                  5       n[        U5      S:X  Ga²  Sn[        U R                  [        R
                  [        R                  45      (       a‹  SU R                  5        Vs/ s H  o3R                  5       PM     sn 3nSU R                   Vs/ s H  oUR                  PM     sn 3nSU R                  5        SU R                  R                   SU SU S	3	nU R                  5        Vs/ s H  owR                  R                  5       PM     nnS
R                  U V	s/ s HA  n	[        U	[        R                  5      (       a  SU	R                   SU	R                    S	3OSPMC     sn	5      n
 U R                  R#                  5       nU R                  R&                  R(                   U U
 SU SU R+                  5       S S3$ / nU H  nUR-                  [/        U5      5        M     U R&                  R(                   SSR                  U5       3$ s  snf s  snf s  snf s  sn	f ! [$         a    Sn N­f = f)Nr   r^   zouts:zins:Ú z (z)
 Ú(Ú)Ú,z (size=z	, stride=z.0fz ns)ú: z, )Ú	get_nodesr³   rŒ   r€   r   ÚExternKernelOutÚ_CollectiveKernelrÇ   r”   ro  rA  ry   Úget_output_specr    ÚLayoutÚsizeÚstrideÚmaybe_get_nameÚAttributeErrorÚ	__class__rp   r'   rÓ   rK  )r:   r7   ÚdetailrÄ   Úouts_strrœ   Úins_strÚchildÚlayoutsÚlayoutÚout_tensor_inforÊ  Ú	summariesÚchild_snodes                 rB   rK  rK  f  s&  € Ø�_‰_Ó€FÜ
ˆ6ƒ{�aÔØˆÜ�e—j‘j¤2×#5Ñ#5´r×7KÑ7KÐ"L×MÑMØ°e×6GÑ6GÔ6IÓJÒ6I°§
¡
¦Ñ6IÑJÐKÐLˆHØ¨e×.FÒ.FÓGÒ.F¨ŸfœfÑ.FÑGÐHÐIˆGØ˜Ÿ™Ó)Ð*¨"¨U¯Z©Z×-JÑ-JÐ,KÈ4ÐPXÈzÐYZÐ[bÐZcÐcdÐeˆFØ=B¿_¹_Ô=NÓOÒ=N°E—:‘:×-Ñ-Ö/Ñ=NˆÐOØŸ(™(ñ
 &ó	ò &�Fô ˜f¤b§i¡i×0Ñ0ð ˜&Ÿ+™+˜ i°·±¨¸aÑ@àòñ &ñ	ó
ˆð	ØŸ
™
×1Ñ1Ó3ˆIð —*‘*×&Ñ&×/Ñ/Ð0°°¸Ð8IÈÈIÈ;ÐVXÐY^×YtÑYtÓYvÐwzÐX{Ð{ð  Að  	Að €IÛˆØ×Ñœ kÓ2Ö3ñ à�o‰o×&Ñ&Ð' r¨$¯)©)°IÓ*>Ð)?Ð@Ð@ùò/  KùÚGùâOùòøô ó 	àŠIð	ús+   Á/H"ÂH'Ã9#H,Ä-AH1Å=H6 È6IÉIc                óX  • SnS nS n[        U 5       Hö  u  pEUci  [        U5      (       a  U[        U5      -  nUR                  nO)[	        UR                  5      (       a  OU[        U5      -  nU" U[        U5       5        Mq  [        U5      (       a/  U[        U5      -  nUR                  nU" U[        U5       5        M°  [	        UR                  5      (       a  U" U[        U5       5        S nMá  U" US[        U5       35        Mø     [        R                  SUS-  S-   35        g )Nrâ   c                ó:   • [         R                  U S SU 35        g )Nz>6r#  )rP  Údebug)Ústeprˆ  s     rB   Ústep_logÚ#visualize_overlap.<locals>.step_logŒ  s   € Ü×Ñ˜T "˜I R¨ uÐ-Õ.rL   z| zEst. runtime (ms): iè  )r4   r   rm  r€   r   rK  rP  r9  )ÚorderÚtotal_est_runtimeÚcur_comm_noder;  r:  r:   s         rB   Úvisualize_overlapr@  …  s#  € ð  #ÐØ€Mò/ô ! Ö'‰ˆØÑ Ü" 5×)Ñ)Ø!Ô%8¸Ó%?Ñ?Ð!Ø %§
¡
‘Ü˜Ÿ™×$Ñ$ð à!Ô%8¸Ó%?Ñ?Ð!Ù�Tœl¨5Ó1Ð2Ö4ä" 5×)Ñ)Ø!Ô%8¸Ó%?Ñ?Ð!Ø %§
¡
�Ù˜¤,¨uÓ"5Ð!6Ö8Ü˜Ÿ™×$Ñ$Ù˜¤,¨uÓ"5Ð!6Ô8Ø $’á˜ ¤L°Ó$7Ð#8Ð9Ö:ñ- (ô. ×ÑØ
Ð/°$Ñ6¸Ñ=Ð>Ð?õrL   c                óÞ   • U n[         R                   HV  n[        U[        5      (       a  U[	        5       ;   a  [	        5       U   n[        U5      (       d   SU S35       eU" U5      nMX     U$ )Nz3Invalid reorder_compute_and_comm_for_overlap pass: z is not callable)r   Ú'reorder_for_compute_comm_overlap_passesrŒ   rY   Úglobalsr  )r7   r=  Úps      rB   Ú$reorder_compute_and_comm_for_overlaprE  «  sm   € ð €Eä×;Ô;ˆÜ�aœ×Ñ !¤w£y£.Ü“	˜!‘ˆAÜ˜�{‰{ð 	
ØAÀ!ÀÐDTÐUó	
ˆ{ñ �%“Šñ <ð €LrL   c           
     ó<	  ^^^^^^• [        U R                  5      m[        [         5      m[        [         5      m[        T5       HÚ  u  pUR                  S:X  d  M  UR
                  [        R                  R                  R                  R                  L d  MT  UR                  S   R                  S:X  d   SU SUR                  S    S35       eUR                  S   nUR                  S   nUS:”  a  TU   R                  U5        MÆ  TU   R                  U5        MÜ     UUU4S jn[        [         5      n[        T5       H¦  u  pUR                  S:X  d  M  UR
                  [        R                  R                  R                  R                  L d  MT  UnUR                  S   mTR                  S:X  d   S	T S
U  S35       eU" T5      (       d  M’  UT   R                  U5        M¨     S nS mT H¦  nUR                  S:X  d  M  [        UR
                  [        R                   R"                  5      (       d  MJ  UR
                  R$                  R&                  (       d  Mq  U" U5      (       a  M€  T" X&R)                  5       5      (       d  M�   SU S35       e   UR+                  5        GH3  u  mn	[        U	5       GH  u  p«TU   nUR                  S   TL d   eUR                  u  nmUS-   nU
[-        U	5      S-
  :  a  XšS-      O[-        T5      S-
  nTXÞ n[/        UU4S jU 5       5      (       a   ST SU SU  S35       eU HŒ  nUR                  S:X  d  M  TUR                  ;   d  M'  UR
                  [        R                  R                  R                  R                  :w  d  Me  [1        UU4S jUR                   5       5      nUUl        MŽ     GM     GM6     UR3                  5        H"  n	U	 H  nTU   nU R5                  U5        M     M$     T Hx  nUR                  S:X  d  M  UR
                  [        R                  R                  R                  R                  L d  MR  UR                  S   U;   d  Mg  U R5                  U5        Mz     g)ab  
This FX graph pass replaces uses of FSDP2 unsharded params with their corresponding
graph intermediates that were fsdp.copy_ into the unsharded params in the original graph.

NOTE: Can only apply this pass to any of the FSDP2 unsharded params that have this pattern
(or repetition of): `resize_(full) -> copy_ -> resize_(0)`. Because of this, for partial-graph case
where `resize_(full) -> copy_` is in one graph and `resize_(0)` is in another graph, we can't
remove these resize and copy ops and thus we will have worse performance there.

In other words, "do we try to remove all the resize_(full) -> copy_ -> resize_(0) nodes for this unsharded param"
is actually a per-unsharded-param decision, since for each unsharded param, we look at its resize sequence pattern
(in `check_resize_pattern()`) to determine if its set of resize and copy nodes can be removed.
Úcall_functionr   Úplaceholderz1Resize can only operate on graph inputs, but got z# which is resizing non-graph-input r<  r   c                ón  >• TR                  U / 5      nTR                  U / 5      n[        U5      [        U5      :w  a2  [        R                  SU  S[        U5       S[        U5       S35        g[	        X5       H7  u  p4X4:¼  d  M  [        R                  SU  STU    SU S	TU    SU S
35          g   g)NzH
Unequal number of resize-to-full and resize-to-0 nodes for graph input z:
z vs. zK.
Skipping `remove_fsdp2_unsharded_param_graph_input_usage` FX graph pass.
Fz
For graph input z: resize-to-full node z
 at index z 
happens after resize-to-0 node zd.
Skipping `remove_fsdp2_unsharded_param_graph_input_usage` FX graph pass for that unsharded param.
T)r  r³   ÚlogÚwarningr¦   )Úgraph_inputÚresized_to_full_idxesÚresized_to_0_idxesÚresize_to_full_idxÚresize_to_0_idxÚ&graph_input_to_resized_to_0_node_idxesÚ)graph_input_to_resized_to_full_node_idxesÚ	node_lists        €€€rB   Úcheck_resize_patternÚLremove_fsdp2_unsharded_param_graph_input_usage.<locals>.check_resize_patternÝ  s  ø€ ð !J× MÑ MØ˜ó!
Ðð D×GÑGÈÐUWÓXÐäÐ$Ó%¬Ð-?Ó)@Ó@Ü�K‰KðHØHSÀ}ð UÜÐÓÐ ˜E¤#Ð&8Ó"9Ð!:ð ;ðôð ô 47Ø!ö4
Ñ/Ðð "Õ4Ü—‘ðØ�Ð3°IÐ>PÑ4QÐ3RÐR\Ð]oÐ\pð q Ø )¨/Ñ :Ð;¸:ÀoÐEVð Wðôñ ñ4
ð rL   z\
Assumed all FSDP2 `unsharded_param`s to be graph input, but it's not true!
Offending node: z	. Graph: c                óø   • U R                   [        R                  R                  R                  R
                  L =(       d:    U R                   [        R                  R                  R                  R
                  L $ rh   )Útargetr0   r{   ÚfsdpÚcopy_r~   ÚinductorÚresize_storage_bytes_)r€   s    rB   Úis_allowed_mutationÚKremove_fsdp2_unsharded_param_graph_input_usage.<locals>.is_allowed_mutation	  sO   € à�K‰Kœ5Ÿ9™9Ÿ>™>×/Ñ/×7Ñ7Ð7÷ OØ�{‰{œeŸi™i×0Ñ0×FÑF×NÑNÐNð	
rL   c           	     óš  • [        U R                  [        R                  R                  5      (       aj  [        U R                  R                  R                  5       VVs/ s H3  u  p#UR                  c  M  UR                  R                  (       d  M1  UPM5     snnO/ n[        U Vs/ s H6  n[        U R                  U   R                  S   R                  5       5      PM8     sn5      n[        U Vs/ s H)  n[        UR                  S   R                  5       5      PM+     sn5      n[        XW-  5      S:„  $ s  snnf s  snf s  snf )NÚvalr   )rŒ   rW  r0   Ú_opsÚ
OpOverloadr4   Ú_schemaÚ	argumentsÚ
alias_infoÚis_writer   r   ÚargsÚmetaÚuntyped_storager³   )r€   Úunsharded_paramsr¶   rˆ   Úmutated_arg_idxesÚmutated_node_arg_storagesÚunsharded_paramÚstorages_of_unsharded_paramss           rB   Ú-is_node_mutating_unsharded_param_or_its_aliasÚeremove_fsdp2_unsharded_param_graph_input_usage.<locals>.is_node_mutating_unsharded_param_or_its_alias	  s)  € ô ˜$Ÿ+™+¤u§z¡z×'<Ñ'<×=Ñ=ô & d§k¡k×&9Ñ&9×&CÑ&CÔDôâD‘D�AØ—<‘<ó à01·±×0EÕ0E÷ ÙDóð ð 	ô %/ñ +óâ*�Aô ˜tŸy™y¨™|×0Ñ0°Ñ7×GÑGÓIÖJÙ*ñó%
Ð!ô (2ñ (8óâ'7�Oô ˜×3Ñ3°EÑ:×JÑJÓLÖMÙ'7ñó(
Ð$ô Ð,ÑKÓLÈqÑPÐPùó)ùòùòs   Á D=Á7D=ÂD=Â)=EÃ60EzdUser mutation on FSDP2 unsharded param is not allowed when Traceable FSDP2 is used. Violating node: c              3  ó8   >#   • U  H  nT" UT/5      v •  M     g 7frh   ro   )r‡   r€   rn  rl  s     €€rB   r‰   ÚAremove_fsdp2_unsharded_param_graph_input_usage.<locals>.<genexpr>Y	  s%   øé € ð â*�Dñ >¸dÀ_ÐDU×VÐVÚ*ùs   ƒz(Assumed no ops mutating unsharded param z in subgraph z, but it's not true!
Graph: c              3  ó6   >#   • U  H  nUTL a  TOUv •  M     g 7frh   ro   )r‡   ÚargÚreplacementrl  s     €€rB   r‰   rq  f	  s$   øé € ð %â#,˜Cð (+¨oÒ'=™À3ÔFÚ#,ùs   ƒN)r.   rÔ  r   r4   ÚoprW  r0   r{   rZ  r[  r~   rf  rÓ   rX  rY  rŒ   r`  ra  rb  Ú
is_mutabler5   rJ  r³   r�   Útupler/   Ú
erase_node)rk  rA   r€   rL  Únew_sizerT  Ú'unsharded_param_to_fsdp_copy_node_idxesÚfsdp_copy_noder\  Úfsdp_copy_node_idxesr¶   Úfsdp_copy_node_idxr>   Úsubgraph_start_idxÚsubgraph_end_idxÚsubgraph_nodesÚnew_argsrQ  rR  rn  rS  rt  rl  s                    @@@@@@rB   Ú.remove_fsdp2_unsharded_param_graph_input_usager‚  »  sS  ý€ ô �U—[‘[Ó!€Iô 1<¼DÓ0AÐ-Ü-8¼Ó->Ð*Ü˜yÖ)‰	ˆà�G‰G�Õ&Ø—‘œuŸy™y×1Ñ1×GÑG×OÑOÔOà—9‘9˜Q‘<—?‘? mÓ3ð ð :2Ø26°Ð7ZÐ[_×[dÑ[dÐefÑ[gÐZhð ið6ó Ð3ð Ÿ)™) A™,ˆKØ—y‘y ‘|ˆHØ˜!‹|Ø9¸+ÑF×MÑMÈcÖRà6°{ÑC×JÑJÈ3ÖOñ *÷"ôJ /:¼$Ó.?Ð+Ü˜yÖ)‰	ˆØ�7‰7�oÕ%¨$¯+©+¼¿¹¿¹×9MÑ9M×9UÑ9UÔ*UØ!ˆNØ"Ÿi™i¨™lˆOØ"×%Ñ%¨Ó6ð ð =à Ð! ¨5¨'ð 2ð9ó Ð6ñ $ O×4Ó4Ø7¸ÑH×OÑOÐPSÖTñ *ò
òQó4 ˆà�G‰G�Õ&Ü˜4Ÿ;™;¬¯
©
×(=Ñ(=×>Ó>Ø—‘×#Ñ#×.×.Ñ.Ù'¨×-Ó-áDØ×BÑBÓD÷ó ð ðeØeiÐdjð kðóð ñ ð: 
1×	6Ñ	6×	8ñ	ØØä%.Ð/C×%DÑ!ˆAØ&Ð'9Ñ:ˆNØ!×&Ñ& qÑ)¨_Ò<Ð<Ð<Ø+×0Ñ0‰NˆAˆ{à!3°aÑ!7Ðð ”sÐ/Ó0°1Ñ4Ó4ð %¨¡UÒ+ä˜“^ aÑ'ð ð
 'Ð'9ÐKˆNÜõ á*ó÷ ñ ð ð)Ø)8Ð(9¸À~ÐFVð WØ€wð ðóð ó '�à—G‘G˜Õ.Ø'¨4¯9©9Õ4ØŸ™¤u§y¡y×'9Ñ'9×'OÑ'O×'WÑ'WÕWä$õ %à#'§9¢9ó%ó  �Hð !)�D–Iô 'ô) &Eñ 
9ðD !H× NÑ NÖ PÐÛ"6ÐØ&Ð'9Ñ:ˆNØ×Ñ˜^Ö,ó #7ñ !Qó ˆà�G‰G�Õ&Ø—‘œuŸy™y×1Ñ1×GÑG×OÑOÔOØ—	‘	˜!‘Ð GÕGà×Ñ˜TÖ"ò rL   c                ó  ^	•  SS K m	T	R                  R                  5       (       d   eT	R                  R                  R
                  (       a%  T	R                  R                  R                  (       d   e SSK
JnJnJnJnJn   U	4S jnU" 5       nU" U" T	R                  R                  R
                  R                   U" ["        R$                  U" T	R                  R&                  R(                  R                   U" S5      U" S5      U" S5      U" S5      U" S	5      5      U" S
5      5      U" S5      U" S5      5      US S9SU	4S jj5       nU" U 5        UR+                  U 5        g ! [        [        [        4 a     g f = f)Nr   r   )ÚCallFunctionÚ
KeywordArgÚMatchÚPatternMatcherPassÚregister_graph_patternc                óX  >• [        U R                  5      nU HŽ  nUR                  [        R                  L d  M"  UR
                  S   R                  TR                  R                  R                  R                  L d  Mh  UR
                  S   S:X  d  M}  U R                  U5        M�     g )Nr   r   )r.   rÔ  rW  ÚoperatorÚgetitemrf  r{   rX  Úall_gather_copy_inr~   rx  )ÚgrS  r˜   r0   s      €rB   Úremove_unused_getitemÚ8reinplace_fsdp_all_gather.<locals>.remove_unused_getitem¡	  sp   ø€ ä˜Ÿ™“Mˆ	ÛˆAà—‘œH×,Ñ,Ô,Ø—F‘F˜1‘I×$Ñ$¨¯	©	¯©×(IÑ(I×(QÑ(QÔQØ—F‘F˜1‘I •Nà—‘˜Q–ò rL   Úall_gather_inputsÚall_gather_outputÚinp_split_sizesÚall_gather_input_numelÚrankÚitem_idxÚ
group_sizeÚ
group_namec                ó&   • U R                   S   S:H  $ )Nr•  r   )Úkwargs)Úmatchs    rB   rC  Ú+reinplace_fsdp_all_gather.<locals>.<lambda>Â	  s   €  %§,¡,¨zÑ":¸aÒ"?rL   )Ú	pass_dictÚextra_checkc                ón   >• U4S jnU R                  UUS   US   US   US   US   US   US   /5        g )	Nc                 óð   >• U S S nU S   nU S   nTR                   R                  R                  R                  " U6 nUS   nUS   nTR                   R                  R
                  R                  XRX6S9nU$ )Néþÿÿÿr  r   r   )Úout)r{   rX  rŒ  r~   Ú_c10d_functionalÚall_gather_into_tensor_out)	rf  Úcopy_in_argsr–  r—  rŒ  r‹  Ú	getitem_1Úall_gather_into_tensorr0   s	           €rB   ÚreplÚEreinplace_fsdp_all_gather.<locals>.reinplace_all_gather.<locals>.replÅ	  s�   ø€ ð    ˜9ˆLØ˜b™ˆJØ˜b™ˆJØ!&§¡§¡×!BÑ!B×!JÒ!JØð"Ðð )¨Ñ+ˆGØ*¨1Ñ-ˆIà—	‘	×*Ñ*×EÑE×MÑMØ¨ð Nð ð #ð
 *Ð)rL   r�  r‘  r’  r“  r”  r–  r—  )Úreplace_by_example)rš  rf  r™  r§  r0   s       €rB   Úreinplace_all_gatherÚ7reinplace_fsdp_all_gather.<locals>.reinplace_all_gather®	  s[   ø€ õ.	*ð$ 	× Ñ ààÐ*Ñ+ØÐ*Ñ+ØÐ(Ñ)ØÐ/Ñ0Ø�v‘Ø�|Ñ$Ø�|Ñ$ðõ	
rL   )rš  r†  )Ú5torch.distributed.fsdp._fully_shard._fsdp_collectivesr)   rÒ  r{   r¢  r¦  r£  ÚImportErrorr,  ÚAssertionErrorÚpattern_matcherr„  r…  r†  r‡  rˆ  r~   rŠ  r‹  rX  rŒ  Úapply)
rk  r„  r…  r†  r‡  rˆ  rŽ  Ú
graph_passrª  r0   s
            @rB   Úreinplace_fsdp_all_gatherr²  |	  sg  ø€ ð
ÛDà× Ñ ×-Ñ-×/Ñ/Ð/Ð/ð �I‰I×&Ñ&×=×=Ø—	‘	×*Ñ*×E×Eð	
ðFØE÷
õ ðõ 	 ñ $Ó%€JáÙØ�I‰I×&Ñ&×=Ñ=×EÑEÙÜ× Ñ ÙØ—I‘I—N‘N×5Ñ5×=Ñ=ÙÐ2Ó3ÙÐ2Ó3ÙÐ0Ó1ÙÐ7Ó8Ù˜vÓ&óñ ˜:Ó&óñ �|Ó$Ù�|Ó$ó	
ð$ Ù?ñ)ö,
ó-ð,
ñB ˜%Ô Ø×Ñ�UÕøôA œ¬Ð8ó Ùðús   ƒA1E) Å)FÆ Fc                óì   • [        U [        R                  R                  R                  [        R                  R                  R
                  45      (       a   e[        U R                  5       SS  5      $ )Né   )rŒ   r0   Ú	_inductorÚ	schedulerÚFusedSchedulerNoder„   r[   r”   rÌ   s    rB   Ú
get_op_idxr¸  é	  sb   € ÜØä�O‰O×%Ñ%×8Ñ8Ü�O‰O×%Ñ%×:Ñ:ð	
÷ñ ð ð ô ˆu�~‰~Ó  Ð#Ó$Ð$rL   c           
     óò	  ^^^ ^!• SSK Jm   / n[        [           " 5       nSnSn0 n0 n0 m!U U!4S jn	U  GH"  n
[	        U
R
                  [        R                  R                  R                  R                  S9(       Gañ  [        U4S jU
R                   5       5      (       GaÌ  SnU
n[        5       n[        UUUT5        [        [        R                  R                  R                  R                  [        R                  R                  R                  R                  [        R                  R                  R                   R                  /5      m[#        UUUTUU 4S jS	9  [%        US
 S9n['        U5      nSn[)        ['        U5      5       H^  nUU   n[+        UR
                  [        R                  R                  R                   R                  5      (       a  US-  nUS:”  d  M\  Un  O   US U nS n[)        ['        U5      S-
  5       H9  n[-        UUS-      R
                  [.        R0                  5      (       d  M4  US-   n  O   Uc   eU	" US U 5      nU	" UUS  5      nUUU'   GM;  [+        U
R
                  [        R                  R                  R2                  R                  5      (       d  GM…  SnU
n[        5       n[#        UUUT5        [%        US S9nS n[)        ['        U5      S-
  5       H9  n[-        UUS-      R
                  [.        R0                  5      (       d  M4  US-   n  O   Uc   eU	" US U 5      nU	" UUS  5      nUUU'   GM%     ['        T!5      S:”  d   eU(       a  ['        U5      S:”  d   eU(       a  ['        U5      S:”  d   eU  HS  n
U
R5                  5       T!;   a  T!U
R5                  5          n
X¤;   a  M1  UR7                  U
5        UR9                  U
5        MU     S nUR;                  5        Hl  u  nnUba  [=        [?        URA                  5       5      5      nURC                  5        H+  nURE                  [G        UR5                  5       USS95        M-     UnMn     S nUR;                  5        Hl  u  nnUba  [=        [?        URA                  5       5      5      nURC                  5        H+  nURE                  [G        UR5                  5       USS95        M-     UnMn     U$ )Nr   )r¶  Fc                óœ   >• TR                   R                  U 5      nU  H  nUTUR                  5       '   M     UTUR                  5       '   U$ rh   )r„   Úcreater”   )Úsnodes_to_groupÚ
group_noder:   r¶  Úsnode_name_to_final_snodes      €€rB   Ú_create_group_nodeÚ:enforce_comm_ordering_for_fsdp.<locals>._create_group_node
  sO   ø€ Ø×3Ñ3×:Ñ:¸?ÓKˆ
Û$ˆEØ:DÐ% e§n¡nÓ&6Ó7ñ %à;EÐ! *×"5Ñ"5Ó"7Ñ8ØÐrL   )ru  c              3  ó®   >#   • U  HJ  n[        TU   R                  [        R                  R                  R
                  R                  5      v •  ML     g 7frh   )r   r€   r0   r{   rX  rŒ  r~   )r‡   rˆ   r›  s     €rB   r‰   Ú1enforce_comm_ordering_for_fsdp.<locals>.<genexpr>
  sJ   øé € ð 
ò %�ô Ø" 1Ñ%×*Ñ*¬E¯I©I¯N©N×,MÑ,M×,UÑ,U÷ð ò %ùs   ƒAATc                ó´   >• [        U TR                  5      =(       d6    [        U TR                  5      =(       a    U R                  R                  T;   (       + $ rh   )rŒ   ÚNopKernelSchedulerNodeÚExternKernelSchedulerNoder€   Úop_overload)rˆ   Úallowed_opsr¶  s    €€rB   rC  Ú0enforce_comm_ordering_for_fsdp.<locals>.<lambda>.
  sD   ø€ Ü˜q )×"BÑ"BÓC÷ ä" 1 i×&IÑ&IÓJ÷ >ØŸF™F×.Ñ.°+Ñ=õ	'rL   )Úcriteria_cbc                ó   • [        U 5      $ rh   ©r¸  r¶  s    rB   rC  rÈ  9
  ó   € ´J¸q´MrL   r¸  r   c                ó   • [        U 5      $ rh   rË  r¶  s    rB   rC  rÈ  j
  rÌ  rL   rÐ  )$r^   r¶  r   r   r   r€   r0   r{   r¢  r£  r~   r�   rÆ  r   Úwait_tensorrX  Úsplit_with_sizes_copyr   Úsortedr³   r,   r   rŒ   r   Ú_WaitKernelÚ	chunk_catr”   rÓ   r¼   rJ  r–  r—  r•   rÇ   rÓ  r   )"r7   rÕ  r›  Ú	new_orderr±  Ú	ag_existsÚ	rs_existsÚ$ag_grouped_node_to_wait_grouped_nodeÚ$rs_grouped_node_to_wait_grouped_noder¿  r:   Úag_snodeÚag_related_snode_setÚag_related_snodesÚend_idx_of_current_ag_blockÚcopy_out_countr¶   Ú	cur_snodeÚwait_node_idxÚag_group_nodeÚag_wait_group_nodeÚrs_snodeÚrs_related_snode_setÚrs_related_snodesÚrs_group_nodeÚrs_wait_group_nodeÚprev_ag_waitÚwait_group_noderÑ  rÄ   Úprev_rs_waitrÇ  r¶  r¾  s"     `                            @@@rB   Úenforce_comm_ordering_for_fsdpré  ô	  sÜ  û€ õ
 à)+€IÜœ3’Ó!€IØ€IØ€IØ+-Ð(Ø+-Ð(Ø "Ðöô ˆäØ�J‰Jœ5Ÿ9™9×5Ñ5×PÑP×XÑX÷
ð 
äô 
ð —_’_ó	
÷ 
ò 
ð ˆIØˆHÜLVËLÐ ô (ØØ$ØØ"ô	ô %ä—I‘I×.Ñ.×IÑI×QÑQÜ—I‘I×.Ñ.×:Ñ:×BÑBÜ—I‘I—N‘N×8Ñ8×@Ñ@ðóˆKô )ØØ$ØØ"õòô !'Ø$Ñ*Añ!Ðô +.Ð.?Ó*@Ð'ØˆNÜœ3Ð0Ó1Ö2�Ø-¨aÑ0�	Ü!Ø—N‘N¤E§I¡I§N¡N×$HÑ$H×$PÑ$P÷ñ ð # aÑ'�NØ! AÕ%Ø23Ð/Ùñ 3ð !2Ð2NÐ3NÐ OÐð !ˆMÜœ3Ð0Ó1°AÑ5Ö6�ÜÐ/°°A±Ñ6×;Ñ;¼R¿^¹^×LÓLØ$%¨¡E�MÙñ 7ð !Ñ,Ð,Ð,Ù.Ð/@ÀÀ-Ð/PÓQˆMñ "4Ð4EÀmÀnÐ4UÓ!VÐàBTÐ0°Ô?ô ˜EŸJ™J¬¯	©	¯©×(@Ñ(@×(HÑ(H×IÔIØˆIØˆHô MWËLÐ Ü(ØØ$ØØ"ô	ô !'Ø$Ñ*Añ!Ðð
 !ˆMÜœ3Ð0Ó1°AÑ5Ö6�ÜÐ/°°A±Ñ6×;Ñ;¼R¿^¹^×LÓLØ$%¨¡E�MÙñ 7ð !Ñ,Ð,Ð,Ù.Ð/@ÀÀ-Ð/PÓQˆMñ "4Ð4EÀmÀnÐ4UÓ!VÐàBTÐ0°Ô?ñ] ô` Ð(Ó)¨AÓ-Ð-Ð-ÞÜÐ7Ó8¸1Ó<Ð<Ð<ÞÜÐ7Ó8¸1Ó<Ð<Ð<ó ˆØ�>‰>ÓÐ8Ó8Ø-¨e¯n©nÓ.>Ñ?ˆEØÓÙØ×Ñ˜ÔØ�‰�eÖñ ð €LØ*N×*TÑ*TÖ*VÑ&ˆ�ØÑ#Ü¤ ]×%CÑ%CÓ%EÓ FÓGˆLØ!×-Ñ-Ö/�Ø×*Ñ*Ü˜AŸJ™J›L°|ÈTÑRöñ 0ð 'Šñ +Wð €LØ*N×*TÑ*TÖ*VÑ&ˆ�ØÑ#Ü¤ ]×%CÑ%CÓ%EÓ FÓGˆLØ!×-Ñ-Ö/�Ø×*Ñ*Ü˜AŸJ™J›L°|ÈTÑRöñ 0ð 'Šñ +Wð ÐrL   )r7   úlist[BaseSchedulerNode])r7   rê  rí   rê  )r€   z"Optional[Union[IRNode, Operation]]rí   rÙ   )r:   r!   rí   rÙ   )r:   r!   )F)rí   rY   )r¡   rê  rí   rY   )r7   rê  rí   z„tuple[dict[BaseSchedulerNode, Optional[BaseSchedulerNode]], dict[BaseSchedulerNode, Optional[BaseSchedulerNode]], BaseSchedulerNode])r®   r¥   rí   ú#dict[BaseSchedulerNode, OrderedSet])r7   rê  rí   z(dict[BaseSchedulerNode, OrderedSet[str]])rÔ   úOptional[BaseSchedulerNode]rÕ   rì  rÖ   ú4dict[BaseSchedulerNode, Optional[BaseSchedulerNode]]rí   rê  )
rÚ   r!   rÛ   r!   rÜ   ú'dict[BaseSchedulerNode, frozenset[str]]rÝ   rî  rí   rÙ   )rÚ   r!   rÖ   rí  ræ   údict[BaseSchedulerNode, float]rÜ   rî  rÝ   rî  rí   útuple[float, float, str])rÛ   r!   rÔ   r!   r÷   rí  ræ   rï  rÜ   rî  rÝ   rî  rí   rð  )rü   r!   rý   r!   rþ   r!   r÷   rí  rÖ   rí  rÔ   r!   rí   r!   )rü   r!   r¡   rê  rþ   r!   r  r[   r  r[   r	  r   r
  r¥   r  r¥   rí   z(tuple[int, dict[BaseSchedulerNode, int]])rü   r!   r¡   rê  rþ   r!   r  r[   r	  r   r
  r¥   r  údict[BaseSchedulerNode, int]r  r¥   r®   r¥   r­   r¥   rí   rX   )
rü   r!   r¡   rê  r®   r¥   r°   rë  rí   z>dict[BaseSchedulerNode, list[Union[FreeableInputBuffer, Any]]])rü   r!   rí   ztuple[bool, Optional[str]])rR  z$dict[BaseSchedulerNode, ReorderInfo]rÔ   r!   rÖ   rí  rS  r[   r«   r[   rª   r¥   r©   úOrderedSet[str]rí   rê  )r7   rê  rí   zDtuple[list[BaseSchedulerNode], dict[BaseSchedulerNode, ReorderInfo]])
r7   rê  rF   rÙ   rG   rÙ   rH   rÙ   rí   rê  )rÔ  rê  rí   rê  )rü   r!   r¡   rê  r  r[   r	  r   râ  r¥   r  rñ  rã  rñ  r  r¥   r­   r¥   rí   rX   )rü   r!   r¡   rê  rý   r!   r  r[   r  r[   r	  r   râ  r¥   r  r¥   r­   r¥   rí   zFtuple[int, dict[BaseSchedulerNode, int], dict[BaseSchedulerNode, int]])rR  z%dict[BaseSchedulerNode, SinkWaitInfo]rÔ   r!   rÖ   rí  rS  r[   r«   r[   rª   r¥   r©   rò  rí   rê  )r7   rê  rí   zEtuple[list[BaseSchedulerNode], dict[BaseSchedulerNode, SinkWaitInfo]])r:   r!   rí   ra   )rk  útorch.fx.Graph)rk  ró  rí   rX   )r7   ú1list[torch._inductor.scheduler.BaseSchedulerNode]rÕ  z4dict[str, torch._inductor.scheduler.SchedulerBuffer]r›  zdict[str, BaseSchedulerNode]rí   rô  )hÚ
__future__r   r¬  rL  rë  ÚloggingrŠ  rÄ  Úcollectionsr   Údataclassesr   Útypingr   r   r   r	   r0   Útorch._loggingr
   Ú torch.multiprocessing.reductionsr   Útorch.utils._ordered_setr   r^   r   r   r   Údependenciesr   r   r   Úmemoryr   r   r   r   Úutilsr   r   r   r   r   r   r   Úvirtualizedr   Ú	getLoggerrp   rJ  Ú_loggingÚgetArtifactLoggerrP  r&   r!   rC   rG   rF   rO   rT   rV   r�   r†   r’   r™   r�   r£   r±   r¸   r§   rÈ   rÍ   rÏ   rÑ   r×   rà   ró   rú   r  r  r#  r(  r.  rZ  rQ   rJ   r×  rÙ  rà  rç  ró  r÷  rþ  r  r  r  rm  rK  r@  rE  r‚  r²  r¸  ré  ro   rL   rB   Ú<module>r     sû  ðõ #ã Û Û Û Û Û 
Ý #Ý !ß 6Ó 6ã Ý +Ý ;Ý /ç &Ñ &Ý !ö ß%÷ó ÷÷ ñ õ ð ×Ò˜Ó!€Ø�n‰n×.Ñ.¨x¸ÓC€æÝ;ð#FØ#ô#FôLôðØ#ðàôð&#Ø#ð#àô#ðL ÷9ð 9ó ð9ô(ô"(ôöò0ô3òð2Ø#ððôð"(Øð(à(ô(ð0Ø#ðà-ôò"Gò
ò;ðØ
%ðà
%ðð Dðð ô	ð6.Ø'ð.à!ð.ð >ð.ð ;ð	.ð
 
ô.ð9.Ø'ð9.àCð9.ð -ð9.ð >ð	9.ð
 ;ð9.ð ô9.ðx9.Ø!ð9.à
ð9.ð Dð9.ð -ð	9.ð
 >ð9.ð ;ð9.ð ô9.ðx.Ø ð.à!ð.ð "ð.ð Dð	.ð
 Dð.ð ð.ð ô.ðb@.Ø ð@.à	 ð@.ð "ð@.ð ð	@.ð
 ð@.ð %ð@.ð 6:ð@.ð ð@.ð .ô@.ðFJØ ðJà	 ðJð "ðJð ð	Jð
 %ðJð 6:ðJð 4ðJð ðJð  ðJð ðJð 
ôJðZ$;Ø ð$;à	 ð$;ð  ð$;ð >ð	$;ð
 Dô$;ðNØ ðàôð<bØ/ðbà
ðbð Dðbð ð	bð
 ðbð !%ðbð #ðbð ôbðJUØ#ðUàIôUðp
YØ#ðYàðYð ðYð ð	Yð
 ôYðxØ"ðàôð0 ÷9ð 9ó ð9ð"(Ø ð(àô(ðV2
Ø ð2
à	 ð2
ð ð2
ð %ð	2
ð
 >Bð2
ð 4ð2
ð 9ð2
ð ð2
ð ð2
ð 
ô2
ðjCGØ ðCGà	 ðCGð "ðCGð ð	CGð
 ðCGð %ðCGð >BðCGð ðCGð ðCGð LôCGðL.Ø ð.à!ð.ð "ð.ð Dð	.ð
 Dð.ð ð.ð ô.ðbWØ0ðWà
ðWð DðWð ð	Wð
 ðWð !%ðWð #ðWð ôWðt4CØ ð4Cà	 ð4Cð  ð4Cð >ð	4Cð
 Dô4CðnLØ#ðLàJôLô^
5ô4	òAò>#ðLØ#ðàôô ~#ôBjòZ%ðnØ=ðnàEðnð 5ðnð 7õ	nrL   