
    i                      d dl mZ d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dl	m
Z
 d dlmZ d dlmZmZmZmZ d dlZd dlmZ d dlmZ d dlmZ d	d
lmZmZmZ d	dlmZ erd	dlmZm Z  d	dl!m"Z"m#Z#m$Z$m%Z%m&Z& d	dl'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z. d	dl/m0Z0  ejb                  e2      Z3ejh                  jk                  e2d      Z6erd dl7m8Z8 	 	 dCdZ9dDdZ:dDdZ;	 	 	 	 dDdZ<	 	 	 	 dDdZ=e G d d             Z>dEdZ?dFdZ@dGdZA	 	 	 	 	 	 dHdZB	 	 	 	 	 	 dIdZCdJdKdZDd ZEdLd ZFd! ZG	 	 	 	 dMd"ZH	 	 	 	 	 	 dNd#ZId$ ZJd% ZKd& ZL	 	 	 	 	 	 	 	 dOd'ZM	 	 	 	 	 	 	 	 	 	 	 	 	 	 dPd(ZN	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dQd)ZO	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dRd*ZP	 	 	 	 	 	 	 	 dSd+ZQ	 	 	 	 dTd,ZR	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dUd-ZS	 	 	 	 dVd.ZT	 	 	 	 	 	 	 	 	 	 dWd/ZU	 	 	 	 dXd0ZVe G d1 d2             ZW	 	 	 	 dTd3ZX	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dYd4ZY	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dZd5ZZ	 	 	 	 	 	 	 	 	 	 	 	 	 	 dPd6Z[	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d[d7Z\	 	 	 	 	 	 	 	 dSd8Z]	 	 	 	 d\d9Z^dDd:Z_d]d;Z`d< Zad= Zb	 	 	 	 dDd>Zcd^d?Zdd_d@ZedA Zf	 	 	 	 	 	 	 	 d`dBZgy)a    )annotationsN)defaultdict)	dataclass)AnyOptionalTYPE_CHECKINGUnion)trace_structured)StorageWeakRef)
OrderedSet   )configconfig_commsir)WeakDep)IRNode	Operation)estimate_peak_memory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                   i }| D ]  }|j                         ||<    dd lm} ddlm} |j                         } |       }t        |      D cg c]  }g  }}|j                  |t        |j                               |       t        j                  t        j                  |      d      j                  j                         }	t        t        |             D ]  }
|	|
   | |
   _         y c c}w )Nr   )_get_default_group)dim)get_estimated_runtimetorch.distributeddistributed"torch.distributed.distributed_c10dr$   get_world_sizerangeall_gather_objectlistvaluestorchmediantensortolistlenoverride_estimated_runtime)snodesruntime_estimationssnodedistr$   
world_sizepg_gathered_runtime_estimationsmedian_runtime_estimationsis              O/var/www/html/engine/venv/lib/python3.12/site-packages/torch/_inductor/comms.py6align_runtime_estimations_across_all_distributed_ranksr@   6   s      C%*%@%@%BE"C$E$$&J		BCHCT6Uar6U 6U$d+>+E+E+G&H" "'12"fVVX  3v; M/I!/Lq	,M 7Vs   	C+c                     t        | ddd      S )z7
    Greedily schedules waits as late as possible.
    FTraise_comms
sink_waitsreorder_for_overlap_schedule_for_commr5   s    r?   rD   rD   L   s     Ed     c                     t        | ddd      S )z8
    Greedily schedules comms as early as possible.
    TFrB   rF   rH   s    r?   rC   rC   U   s     DU rI   c                     t        | ddd      S )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.
    TrB   rF   rH   s    r?   reorder_compute_for_overlaprL   ^   s     DTt rI   c                "    t        |       \  }}|S )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)r5   reordered_snodes
node_statss      r?   ,reorder_communication_preserving_peak_memoryrQ   q   s    @ 	?vF !j rI   c                      e Zd ZU dZdZded<   dZded<   dZded<   d	Zded
<   dZ	ded<   dZ
ded<   dZded<   dZded<   dZded<   ed        Zy)ReorderInfozE
    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    | j                   | j                  z
  S Nr`   ra   selfs    r?   improvementzReorderInfo.improvement       ##d&8&888rI   N)__name__
__module____qualname____doc__rV   __annotations__rX   rY   r[   r^   r_   r`   ra   rb   propertyrh    rI   r?   rS   rS      st     "OS!E3NGSL#IuIu!OU!M5L#9 9rI   rS   c                    | yt        | t        j                  j                  j                  j
                        ryt        | dd       x}rd|v ryy)NFTpython_kernel_nameextern_kernels)r   r/   opsaten#_scaled_dot_product_flash_attentiondefaultgetattr)noderr   s     r?   is_gemm_likerz      sX    |		::BB  &d,@$GGG
0
0rI   c                    ddl m} t        | |      rt        d | j                  D              S t        | j                        S )Nr   GroupedSchedulerNodec              3  2   K   | ]  }t        |        y wrd   )contains_gemm_like).0xs     r?   	<genexpr>z%contains_gemm_like.<locals>.<genexpr>   s     ?Q%a(?s   )torch._inductor.schedulerr}   
isinstanceanyr5   rz   ry   )r7   r}   s     r?   r   r      s4    >%-.?%,,???EJJ''rI   c                    ddl m} t        | |      r&| j                  r| j                  D ]
  } ||        y  ||        y )Nr   r|   )r   r}   r   temp_groupingr5   )r7   fnr}   _snodes       r?   _temp_group_visit_leavesr      s;    >%-.53F3Fll 	FvJ	 	5	rI   c                   | d   }t        |j                        sJ t        |       dkD  sJ t        |       dz
  }d}dd}g }t        |dd      D ]  }| |   }t	        |      r|j                  |       t        |      rNt        ||      r|   }|d|j                          dz  } nZt        |      sdg|D ]  }	t        ||	      sd }
dfd}t        ||       }|d	|j                          d
||
z
   dz  } ||fS )a  
    Calculate exposed communication time for a wait operation by finding its corresponding
    collective and accumulating overlapping compute time between them.

    The Wait node must be the last in snodes_to_wait.
    Compute time between corresponding Collective and Wait is accumulated.
    If there is another pair of Collective and Wait inside,
    Only compute before first such Wait' is considered as overlapping.

    Multiple process groups are not modeled so far.
    r              rZ   z->C[]c                    |    z  y rd   rp   r   r_   runtimess    r?   accumulate_timez8wait_exposed_communication_time.<locals>.accumulate_time       &))IrI   +[r   r"   returnrT   )r   ry   r3   r+   r   appendr    is_corresponding_collective_waitget_namecontains_async_collectiver   )snodes_to_waitr   
wait_snodeidxr^   rb   waits_foundr>   cwcomp_time_beforer   comp_time_afterr_   s    `           @r?   wait_exposed_communication_timer      sO     #J:??###~"""
n

!CIILK3B Q1q!q!/:>$QK	$qzz|nA 66,Q/	$ !A71= %(	 ! %	* 	!O4#!AJJL>?=M+M*NaPP?QB i--rI   c                   | d   }|   }dt        d |j                         D              }d}g }| dd D ]  }t        d |j                  D              }||z  r|d|j                          d	z  } nt	        |      rt        |      s np|j                  |       gt        |      rd
}	|D ]  }
t        ||      sd}	 n |	r n6}dfd}t        ||       }|d|j                          d||z
   d	z  } ||fS )a  
    Calculate exposed communication time for a collective operation by finding its corresponding
    wait and accumulating compute time that can overlap with communication.

    The Collective node must be the first in snodes.
    Compute time between corresponding Collective and Wait is accumulated.
    If there is another pair of Collective and Wait inside,
    Only compute before first such Wait' is considered as overlapping.

    Multiple process groups are not modeled so far.
    r   r   c              3  <   K   | ]  }|j                           y wrd   r   r   os     r?   r   z2coll_exposed_communication_time.<locals>.<genexpr>  s      2

2   rZ   r   Nc              3  L   K   | ]  }t        |      r|j                    y wrd   )_is_fake_depnamer   ds     r?   r   z2coll_exposed_communication_time.<locals>.<genexpr>$  s       
LOAFF 
s   $$z->W[r   FTc                    |    z  y rd   rp   r   s    r?   r   z8coll_exposed_communication_time.<locals>.accumulate_time>  r   rI   r   r   r   )
r   get_outputsunmet_dependenciesr   r   r   r   r   r   r   )r5   r   collective_snoder^   collective_outsrb   collectives_foundr7   
unmet_depshas_wait_for_collectives_found_collr   r   r   r_   s    `            @r?   coll_exposed_communication_timer   
  s]    ay)*II'1 2.::<2 (O L13 #U    
!44 
 

 'd5>>#3"4A66Lu%,U3!((/-2** 34DeL592 .$	* 	!8#!ENN,-QAQ/Q.RRSTTG#UH i--rI   c                    d}| j                   D ]<  }|r|dz  }||j                         z  }|s |t        | j                                z  }> |S )NrZ   r;   )r5   r   r-   get_buffer_names)r7   	with_bufsretns       r?   _group_namer   H  s[    
C\\ 73JCqzz|d5113456C7 JrI   c                >    t        | t              xr | j                  S rd   )r   r   is_fake)r   s    r?   r   r   S  s    a!/aii/rI   c                f    dj                  | D cg c]  }|j                          c}      S c c}w )N~)joinr   )gnsgns     r?   _group_namesr   W  s%    88S1rR[[]1221s   .c                    t        | |      }t        | ||      \  }}}}t        t        | |            }d|d<   |||||fS )z*Initialize memory tracking data structures)r   r   N)r   r   dictzip)	r5   graph_inputsgraph_outputsname_to_freeable_input_bufpeak_memorysnodes_curr_memorysnodes_allocfreebuf_to_snode_last_use_curr_memorys	            r?   _initialize_memory_trackingr   [  sg    !7!M&.	
 MK#%57L
 F$678LL" rI   c                    i }i }t        |       D ]5  \  }}|dkD  r| |dz
     nd||<   |t        |       dz
  k  r| |dz      nd||<   7 | d   }|||fS )z/Create double-linked list structure from snodesr   r   N)	enumerater3   )r5   _prev_nextr>   r7   _heads         r?   _initialize_double_linked_listr   n  s{     EEf% F5()Ava!e}4e()CK!O(;va!e}eF 1IE%rI   c                    t        d | j                         D              }t        d |j                  D              }t        ||z        S )z
    Check if a wait node corresponds to a given collective node by verifying if the wait
    depends on outputs from the collective.
    c              3  <   K   | ]  }|j                           y wrd   r   r   s     r?   r   z3is_corresponding_collective_wait.<locals>.<genexpr>  s      V! Vr   c              3  4   K   | ]  }|j                     y wrd   r   r   s     r?   r   z3is_corresponding_collective_wait.<locals>.<genexpr>  s     JqAFFJ   )r   r   r   bool)r   r   r   r   s       r?   r   r     sD     ! V7G7S7S7U VVOJJ,I,IJJJ
_,--rI   c                X    t        |       rt        j                  S t        j                  S rd   )r   r   *reorder_sink_runtime_estimations_comm_mult.reorder_sink_runtime_estimations_non_comm_multr7   s    r?   _op_runtime_estimate_multr     s$     5!FFFFFFrI   c                @    t        | j                  dd      x}rd|v ryy)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.
    rr   Nz-torch.ops._dtensor.shard_dim_alltoall.defaultFT)rx   ry   )r7   rr   s     r?   is_async_collectiver     s-     %UZZ1EtLLL:>PPrI   c                "    t        | t              S rd   )r   r   r   s    r?   r   r     s    u&9::rI   c                N    g }| }	 ||j                  |       ||k(  r	 |S ||   }!)aA  
    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)
    )r   )headtail	next_dictr   r   s        r?   _group_nodes_from_linked_listr     s@      CA
=JJqM9J aL rI   c                l    ||    }|r|||<   |||<   ||   }|r| ||<   ||| <   ||| <   | ||<   || k(  r|S |S )a  
    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)
    rp   )	candidate
group_head
group_tail	prev_dictr   r   candidate_prevgroup_tail_nexts           r?    _perform_double_linked_list_swapr     ss    8 y)N$.	.!*Ij  
+O%.	/"*Ii &Ii%Ij yKrI   c                n   i }d}	|s)t        ||z
  ||   d   |z
  |j                  z         }	|	|fS | }
|D ]R  }||   d   |
z   }|||<   t        |	|      }	|j                  |      }|3|D ]  }|
|j                  j                  z  }
 T ||   d   |
z   |j                  z   }||| <   t        |	|      }	|	|fS )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get
mpi_buffer	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bufsbufcandidate_mem_post_allocs                   r?   (_calculate_potential_peak_memory_reorderr    s+   > 8:N: 33
#A&!"!,,-
 111 %8#7 	D'OA.1HH!22^->?>BB2F D'3>>+C+CC'D	D 	J"
!	"

(
(	) 
 %=y!)ABN---rI   c
                   |sK|D ]  }
||
   }|d   |z
  |d   |z
  f||
<    ||   d   |j                   z   }||j                  z
  }||f|| <   y|j                         D ]  }|D ]  }| ||<   	  d}|D ]R  }||   }t        d ||   D              }||z  }|	|   xj                  |z  c_        ||	|   j                  z
  }||f||<   T ||    }|	|    xj                  |z  c_        ||	|    j                  z
  }||f|| <   y)aN  
    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  H   K   | ]  }|j                   j                    y wrd   r   r   r   r  s     r?   r   z=_update_memory_tracking_after_swap_reorder.<locals>.<genexpr>m  s"      2
 NN$$2
    ")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                         r?   *_update_memory_tracking_after_swap_reorderr  4  s   < ; 	BRB1++1++KO	 
#A&)<)G)GG 	" &(;(E(EE 	! &$"
I 	 @FFH 3 	3C)2!#&	33 /0& 
@"3A"6.1 2
FqI2
 /
& 	+.LL*%%)GG% 25Ea5H5R5R R,.>?A
@ !2) <Y))-OO)!$4Y$?$I$II  	"K	rI   c                    t        t              }|j                         D ]I  \  }|j                  j                  }| |vr!t        fd|D              s6|   j                  |       K |S )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

    Returns:
        Dict mapping group nodes to buffers that will change their last-use node
    c              3  (   K   | ]	  }|k(    y wrd   rp   )r   r   snode_last_uses     r?   r   z6_find_buffers_with_changed_last_use.<locals>.<genexpr>  s     6B2'6s   )r   r-   itemsr   
succ_nodesr   r   )r   r   r   r   r  r  r  s         @r?   #_find_buffers_with_changed_last_user    s}    , 	D 4 
	$	$	&T 	^^..
J&6#667GNNsST ;:rI   c                    t         j                  s t        |       rdd| j                          fS t         j                  st        |       ryy)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    r?   _is_node_groupable_for_reorderr$    sO    $ @@$Y/01C1C1E0FG  AAi(.rI   c                   | }|D ci c]  }|||   j                    }	}t        |	D cg c]  }|	|   	 c}      }
t        |D cg c]  }||   j                   c}      }d|
 d| dg d}|j                         D cg c]  \  }}t	        |      |j
                  dz  |j                  dz  |j                  dz  |j                  dz  |j                   dz  |j                  |j                  |j                  |j                  |j                  g }}}t        j                  j                  d      rddlm}  |||	      z  n8d
z  t#        |      dz   z  dj%                  t'        t"        |            z  t)        |d|      }t+        |      |k(  sJ t-        |||      \  }}}}d| z  d| z  t.        j1                         t3        dd fd       |S c c}w c c}w c c}w c c}}w )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 factorrX   rY   r[   rb        @@tabulater   r-  headers>Please `pip install tabulate` to nicely render overlap stats.

Nz
 peak_memory_before:z
 peak_memory_after:artifactc                     dddS )NrQ   stringr   encodingrp   rp   rI   r?   <lambda>z2_format_and_log_reordering_stats.<locals>.<lambda>"  s    B 
 rI   c                      S rd   rp   )reorder_log_strs   r?   r8  z2_format_and_log_reordering_stats.<locals>.<lambda>&  s    ? rI   metadata_fn
payload_fn)rh   r  rX   r  node_summaryr^   r_   r`   ra   rV   rY   r[   rb   	importlibutil	find_specr-  rU   r   mapr   r3   r   overlap_loginfor
   )statsr   r   original_snodes_numr   r   r   rP   r7   rh   total_improvementtotal_movesr0  	node_inforowsr-  
new_snodesnew_peak_memoryr;   r:  s                      @r?    _format_and_log_reordering_statsrM    sF   8 JEOPE5*U+777PKP[IE[/IJJG5z%(..GHK LL]K^ _l	, G6 !+ 0 0 2 E9 #%#%%%+##c)!!C'%%OO""""	
D   ~~
+%8
 	

 	M	
 	3w<$..499Sd^44.tT9EJz?1111=. OQ1 /}==O..?@@O_%
 + M QIG&s   G,G1G6BG;c                n   d}| D ]  }t        |      sd} n |s| i fS ddlm} t        |       }t	        t
        j                  j                  j                               }t	        t
        j                  j                               }t        | ||      \  }}}	}
}| D ci c]  }|t        |      t        |      z   }}i }d}t        |       \  }}}t        j                  }d}|}t        j                   }d}|||   ||   }|rnt#        |      s|} |||k\  rn|dz  }t%               x}||<   t'        t)        |d|      |      \  }}}||_        ||_        ||z
  x|_        |_        ||_        ||   }|}|}i }d} ||   d   }!|~t        j4                  r4|j0                  t        j6                   |j*                  z  k  r	d|_        n:t        j:                  st        |      r	d	|_        nt)        |||      }" ||j<                  |"d
      }#|#j>                  D $ci c]  }$tA        |$      r|$jB                  |$ }%}$|jE                         }&d}'|&D ](  }(|%jG                  |(jI                         d      x}$s&|$}' n |'tK        |      \  })}*|)r|}t        j4                  r@tM        |      r"tO        t)        |||      |      \  }}}+||f||<   t#        |      s| ||   z  } tQ        |!||   d         }!|xjR                  dz  c_)        tU        |"      |_+        ||   }d|' dtY        |%j                                d|jI                          d|j[                         g dtU        |"       d|* },|,|_        nt        j4                  r_t#        |      s||   }-|-dkD  rIt        |      dkD  r:tQ        d|j*                  |j,                  z
        }.tQ        d|j*                  |j,                  z
  |-z
        }/|/|.z
  }0|j]                         D ].  \  }1}2tQ        d|1|2z
        }3tQ        d|1|2z
  |-z         }4|0|4|3z
  z  }00 |0dkD  rd|- d|0 |_        n|j_                         D ]  \  }5\  }1}2|1|2|-z
  f||5<    nq| dkD  rlt'        t)        |d|      |      \  }}}+tQ        d||z
        }.tQ        d||z
  | z         }/|/|.z
  }0|0dkD  r&d|jI                          d|  d|0 d| d| 
|_        n|	|   }6|6j`                  |6jb                  z
  }7te        ||"|
      }8tg        ||"||!|7|6|8|      \  }9}:|9|z
  |t        jh                  z  kD  rd|9 d| |_        n|xjj                  dz  c_5        |dz  }tm        ||||||      }t'        t)        |d|      |      \  }}}||_        ||_        ||_        ||z
  |_        to        ||"||7|6|8|:||
|	
       |r/ddl8m9};  |;||"tU        |"      t)        |d|      |||||	d|8      }|rn	||   }|~|}|||   tu        |||||||      }<|<|fS c c}w c c}$w )z
    Internal testing helper that also returns debug info.
    Returns:
        - reordered snodes list
        - dict {snode: ReorderInfo}
    FTr   r|   Nr   r    unexposed by runtime estimationszcollective orderingr   data dependency (dep_names:)
 candidate:z(outs:z)dep on 
 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_recomputerQ   );r   r   r}   r3   r   r    graphr   keysget_output_namesr   estimate_op_runtimer   r   r   (reorder_iterative_debug_limit_to_reorder(reorder_iterative_debug_memory_recomputer   rS   r   r   r^   r_   r`   ra   rb   r"  )reorder_iterative_extra_comm_comp_overlaprV   ,reorder_iterative_unsafe_collectives_reorder	schedulerr   r   r   r   r   r   r$  r   r   r   rY   r   r[   r-   r   r.   r  r   r   r  r  $reorder_iterative_peak_memory_budgetrX   r   r  comms_debugrY  rM  )=r5   has_collectivesr7   r}   rF  r   r   r   r   r   r   r   r   rE  rH  r   r   r    debug_num_collectives_to_reordernum_processed_collectivescurr debug_iterative_memory_recomputeiterative_recompute_error
_next_currrD  r^   r_   rb   r   r   r   group_waitsgroup_runtimer   r   groupr   	data_depscandidate_outsdata_depr   is_groupable_resultgrouping_reasonr;   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  rY  rK  s=                                                                r?   rN   rN   ,  s    O u%"O rz>f+$.qww/C/C/H/H/J$KL%/0H0H0J%KM 	$FL-H"
 0 	"5),Ee,LLL0H 0
 35EK8@E5% 	== % &'(-D== % !&

uT{64[
$(.D+7%)II!Q&!(]*uT{-L)$e<h.
*	9l #"4=	4IIt1($K	

(.q1#EE""III..!! (J$ !MM'	2'<$+HJ,C )"E $)#;#;<PQ?	I  '224NH# !ajjlD9919 H
 #7U84#_ '!*J#MM(36U =eYPU V (73Iy! 6?	5IK	28C)Xi-@@M(+)<	+B1+E)% LLA%L(4S(9D% %i 0I +8*KY^^EU@V?W X((1(:(:(<'=VYE_E_EaDbCc d"".s"3!4..?A  ,/D( EE0; ( 3I 1}[)9A)=),Q0O)P(+t~~>J) )6(F:E:L:L:N R6L,03A|l7R0S-/2 !<,#>#J0, *-=@Q-QQMR )1,"8 DNN[_!^ !0 " "-!2!2!4" ! % , , %1$09$<3"B	" %q(2Q9)T5Q$3/	9a
 *-Q	I0E)F(+Ay9/D}/T(U(5(F(1,",Y-?-?-A,B C22? A22?i[Xefoep!r !0
 "/?	/J#..1D1N1NN    4s$9 < 9%''C 	 /N. , Q QQR
 '~&6i}M $ JJ!OJ1K4:z5%E 2Q-dD%@(2.Iy, 'DN&DN ,D!*Y!6D6##?"%  0 K,M %1%uE.! $BC-) -j)II #J I 
uT{6L 2"J uM	0bs   X-'X28X2c                   i }i i i i ct        |       D ]y  \  }}|j                         D ]  }|||<   	 |j                         D ]  }||<   	 ||j                         <   |j                         }	t        j
                  |	<   d|	<   ||	<   { d}
| D ]  }|rZt        |      rO|
|j                         <   |j                  D ]'  }|   j                         }t        |   |
      |<   ) |
dz  }
_|sbt        |      snd|j                         <     G fdd      | D ci c]  }|t        d |j                  D              ! c}g t        t              | D ci c]  }|t        |       c}j                         D ]J  \  }}t        |      dk(  rt!        j"                   |             |D ]  }|   j%                  |        L g fdfdfd}r@t!        j&                        j(                  }|rt        |      r	 ||       n |       r@j+                         D ]  }t        |      dk(  rJ d	         S c c}w c c}w )
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                  &    e Zd Zd fdZd Zy)$_schedule_for_comm.<locals>.Runnablec                    || _         t        t        |j                                     }|   j	                         }|   |   |   f| _        y rd   )r7   nextiterget_operation_namesr   score)rg   r7   r   
fused_namename_to_fused_nodescores_0scores_1scores_2s       r?   __init__z-_schedule_for_comm.<locals>.Runnable.__init__  sV    DJU6689:D+D1::<J$$$DJrI   c                4    | j                   |j                   k  S rd   r  )rg   others     r?   __lt__z+_schedule_for_comm.<locals>.Runnable.__lt__  s    ::++rI   N)r   rT   )rj   rk   rl   r  r  )r  r  r  r  s   r?   Runnabler    s    	 		,rI   r  c              3  4   K   | ]  }|j                     y wrd   r   )r   deps     r?   r   z%_schedule_for_comm.<locals>.<genexpr>  s     Gs#((Gr   c                    j                  |        | j                         D ]N  }|   D ]D  } |    j                  |       t        |          dk(  s)t	        j
                   |              F P y)zU
        Schedules `snode` and put all unblocked nodes onto the ready queue.
        r   N)r   r   remover3   heapqheappush)r7   buf_namer  buffer_usersready	scheduledr   s     r?   schedulez$_schedule_for_comm.<locals>.schedule  sv     	..0 	;H%h/ ;5!((2z%()Q.NN5(5/:;	;rI   c                     D  cg c].  } t        | j                        st        | j                        s| 0 }} t        |      dk(  ryt	        |d       S c c} w )zh
        Return the next node in the ready queue that's neither a collective or
        a wait.
        r   Nc                    | j                   S rd   r  r   s    r?   r8  zG_schedule_for_comm.<locals>.get_overlapping_candidate.<locals>.<lambda>  s
    QWW rI   key)r   r7   r   r3   min)r   
candidatesr  s     r?   get_overlapping_candidatez5_schedule_for_comm.<locals>.get_overlapping_candidate  s]     
&qww/agg8N 

 

 z?a:#455
s   3Ac                   t        |       sJ  |        |    }|dkD  rM        x}Dj                  |        |j                         ||j                     z  }|dkD  r
        x}Dt        j                         y)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  r7   r  heapify)r7   collective_costr   r  r  r  snode_to_costs      r?   schedule_collective_for_overlapz;_schedule_for_comm.<locals>.schedule_collective_for_overlap  s     #5)))'.a799FLL#Y__%}Y__==O a799F 	erI   z;Detected unscheduled nodes. Nodes with unmet dependencies: )r   r   r  r   sysmaxsizer   	ancestorsr  r   r   r   r   r]  r  r3   r  r  addheappopr7   r.   )r5   rC   rD   rE   buf_name_to_snoder   r7   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                   @@@@@@@@@@@@r?   rG   rG   t  s   L #%r2 Hh' "
U..0 	0H*/h'	0 002 	0G*/w'	0/45>>+,NN$	!kk!" H +.u5)1HU^^%&!OO S!3H!=!F!F!H+.x/G+R(S MHM%0)*HU^^%&+, ,  < 	zGe.F.FGGG<J
 E=H=TLDJK5U/66KM!'') )tt9>NN5(5/2 	)C!!%(	)) I	; 	;6* e$**#6u#=+E2UO  !!# 
4yA~ 	
I*V	
~
 U< Ls   9$I15I6c           	     z   t         j                  j                         s| S | D cg c]  }t        |      s| }}t	        dt        |            D ]b  }t        t        ||   j                                     }||dz
     j                         D ]"  }||   j                  t        ||d             $ d | S c c}w )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   )r/   r(   is_availabler   r+   r3   r  r  r   add_fake_depr   )nodesname_to_bufr  r   
comm_nodesr>   r  r  s           r?   decide_global_ordering_of_commsr    s     ))+"=&9!&<!=J=1c*o& DA!?!?!ABCa!e$557 	CqM&&,E	 L >s
   B8B8c                      e Zd ZU dZded<   dZded<   dZded<   dZded<   d	Zded
<   dZ	ded<   dZ
ded<   dZded<   dZded<   d	Zded<   ed        Zy)SinkWaitInfor   rW   rY   rZ   rU   r[   rX   
moves_inforT   rV   r\   r]   r^   r_   r`   ra   rb   c                4    | j                   | j                  z
  S rd   re   rf   s    r?   rh   zSinkWaitInfo.improvement5  ri   rI   N)rj   rk   rl   rY   rn   r[   rX   r  rV   r^   r_   r`   ra   rb   ro   rh   rp   rI   r?   r  r  (  sw    GSL#E3NJ!OS!IuIu!OU!M5L#9 9rI   r  c                $   t        |       rdd| j                          fS t        |       rdd| j                          fS t        j                  s@t        |       rdd| j                          fS t        |       rdd| j                          fS y)aP  
    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    r?   !_is_node_groupable_for_sink_waitsr  :  s    " Y01C1C1E0FGGG +293E3E3G2HI
 	
 >>
 y)01C1C1E0FG  i(/	0B0B0D/EF  rI   c	                d   |d   }	||	   d   ||	   j                   z
  }
|sC|
|j                   z   }|||j                  z
  f|| <   |D ]  }||   }|d   |z   |d   |z   f||<    y| g|D ]F  }||   }||   xj                  |j                  |d      z  c_        ||||   j                  z
  f||<   H y)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                   r?   -_update_memory_tracking_after_swap_sink_waitsr  f  s   8 QJ
+A.1A*1M1X1XXMB,/B/M/MM  #6#@#@@"
I  	BRB1++1++KO	 	# 
&q)
%%)?)C)CAq)II%)!,666
A
rI   c	                   ||   d   ||   j                   z
  }	i }
i }d}|s!t        ||z   |	|j                   z         }||
|fS |	|j                   z   }||
| <   |}t        d t        j                  j                  |j                               D              }| || <   ||z   }|D ]S  }||   d   |z   }||
|<   t        ||      }d}||v r*||   }|D ]  }||j                  j                  z  } |||<   ||z  }U ||
|fS )a  
    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  H   K   | ]  }|j                   j                    y wrd   r  r  s     r?   r   z>_calculate_potential_peak_memory_sink_waits.<locals>.<genexpr>  s"      & 	  &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                        r?   +_calculate_potential_peak_memory_sink_waitsr    s{   >  
+A.1A*1M1X1XXM79<>NB 33/:::
 13JJJ(+>+I+II$8y!)N"% &??00CJJL
& # +F)EI&#&AAI 
)#B*Y6!.2^];HHJ2ND @#s~~'?'??#@*=#B'((	
) -/FFFrI   c                l    ||   }|r| ||<   ||| <   ||    }|r|||<   |||<   | ||<   ||| <   ||k(  r| S |S )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)
    rp   )r   r   r   r   r   r   group_head_prevcandidate_nexts           r?   +_perform_double_linked_list_swap_sink_waitsr    ss    8  
+O%.	/"*Ii y)N$.	.!*Ij &Ij%Ii TKrI   c                *   g d}| j                         D 	cg c]  \  }}	t        |      |	j                  dz  |	j                  dz  |	j                  dz  |	j
                  dz  |	j                  dz  |	j                  |	j                  |	j                  |	j                  |	j                  |	j                  g }
}}	dt        j                  j                  d      rddlm}  ||
|      z  n8dz  t#        |      d	z   z  d	j%                  t'        t"        |
            z  t(        j+                         t-        |d
|      }t/        |      |k(  sJ t1        |||      \  }}}}d| z  d| z  t3        dd fd       |S c c}	}w )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 noder&  r'  r(  r)  r*  r+  rY   r[   rX   r  rb   r,  rZ   r-  r   r.  r/  r1  r2  Nz*
 sink_waits_iterative peak_memory_before:z)
 sink_waits_iterative peak_memory_after:r3  c                     dddS )Nsink_waits_iterative_infor5  r6  rp   rp   rI   r?   r8  z2_format_and_log_sink_waits_stats.<locals>.<lambda>d  s    / 
 rI   c                      S rd   rp   )log_strs   r?   r8  z2_format_and_log_sink_waits_stats.<locals>.<lambda>h  s    7 rI   r;  )r  r>  r^   r_   r`   ra   rh   rV   rY   r[   rX   r  rb   r?  r@  rA  r-  rU   r   rB  rC  rD  r   r3   r   r
   )rE  r   r   rF  r   r   r   r0  r7   rD  rJ  r-  rK  rL  r;   r  s                  @r?    _format_and_log_sink_waits_statsr    s   8G: !;;= E4 NNS NNS   3&$s"  LLJJOO	
D " G~~
+%8
 	

 	TT3w<$&&499Sd^,,W.tT9EJz?1111=. OQ1 <[MJJG;O;LMMG
 # ]s   BFc                    t        t              }|j                         D ]H  \  }}|j                  j                  }|| k7  r"d}|D ]	  }||v s|} |5||   j                  |       J |S )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

    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  last_succ_gnr   s	            r?   ._find_buffers_with_changed_last_use_sink_waitsr  m  s    , 	D < 
	$	$	&
 	^^..
Y& 	"BZ!	"  	@MTT	
#
* CBrI   c                   ddl m} t        |       }|dk(  r| i fS t        t        j
                  j                  j                               }t        t        j
                  j                               }t        | ||      \  }}}}}	t        |       \  }
}}i }| D ci c]  }|t        |      t        |      z   }}| d   }t               }t        j                  }t        j                  }d}||
|   |
|   }|rn|t        |      |k\  rnt!        |      r||vs|}6|j#                  |       t%               x}||<   t'        t)        |||      |      \  }}}||z
  x|_        |_        ||_        ||_        ||_        ||   }|}|}|}i }d}||   d   } |t        j4                  r4|j,                  t        j6                   |j.                  z  k  r	d|_        nt)        |||      }! ||j:                  |!d      }"|j<                  D #ci c]  }#t?        |#      r|#j@                  |# }$}#|"jC                         }%d }&|%D ](  }'|$jE                  |'jG                         d       x}#s&|#}& n t        jH                  s%tK        |      rd	|jG                          |_        n|&tM        |"      xr tM        |      x}(rQtO        |      \  })}*|)r|}t        j4                  r@tM        |      r5tQ        t)        |d |      |      \  }}}+||f||<   tK        |      s|||   z  }tS        | ||   d         } |xjT                  d
z  c_*        tW        |!      |_,        ||   }|&8t        jZ                  s(rdtW        |!       d|jG                          |_        nd|& dt]        |$j                                d|jG                          d|j_                         g dtW        |!       d|%D 'cg c]  }'|'jG                          c}' d|* |_        nt        j4                  rHta        |jb                        rPt'        t)        |||      |      \  }}}+tS        d||z
        },tS        d||z
  |z         }-|-|,kD  rd|, d|- |_        ntK        |      s||   }.|.dkD  rt        |      dkD  rtS        d|j.                  |j0                  z
        }/tS        d|j.                  |j0                  z
  |.z
          |je                         D ]*  \  }0}1|/tS        d|0|1z
        tS        d|0|1z
  |.z         z
  z  }/, |/dkD  rd|. d|/ |_        n`|jg                         D ]  \  }2\  }0}1|0|1|.z
  f||2<    ||   }3|3jh                  |3jj                  z
  }4tm        ||!|      }5to        ||!|| |4|3|5||	      \  }6}7}8|6|z
  |t        jp                  z  kD  rd|6 d| |_        n|xjr                  d
z  c_9        |xjt                  d|jG                          z  c_:        tw        ||||
||      }t'        t)        |||      |      \  }}}||_        ||_        ||z
  |_        ||_        ty        ||!|4|3|5|7|8||	       |r/d
dl=m>}9  |9||!tW        |!      t)        |d |      |	||||d|5      }|rn	||   }||}||
|   t        ||||||	|      }:|:|fS c c}w c c}#w c c}'w )Nr   r|   r   Fr   rO  TrP  r  r   zcollective ordering z
 with candidate:rQ  rR  rS  z(os:z
)
 dep on z
 outs:rT  z"candidate is wait, exposed_before:z vs exposed_after:rU  z2, group contains collectives, total_exposed_delta rV  rW  r   rX  sink_waits_iterative)@r   r}   r3   r   r    rZ  r   r[  r\  r   r   r]  r   r   r_  (sink_waits_iterative_debug_limit_to_sinkr   r  r  r   r   r`   ra   r^   r_   rb   r  &sink_iterative_extra_comm_comp_overlaprV   rb  r   r   r   r   r   r   *sink_waits_iterative_swap_with_collectivesr   r   r  r   r   rY   r   r[   /sink_waits_iterative_unsafe_collectives_reorderr-   r   r   ry   r.   r  r   r   r  r  !sink_iterative_peak_memory_budgetrX   r  r  r  rd  rY  r  );r5   r}   rF  r   r   r   r   r   r   r   r   r   r   rE  r7   r   rh  processed_waitsri  debug_num_sink_waits_to_reorderrj  
_prev_currrD  r^   r_   rb   r   r   r   r   group_collsrm  r   r   rn  r   ro  
group_outsrq  r   both_contain_comms_is_groupablegroupable_reasonr;   rv  rw  ru  rx  gc_comm_timegc_comp_timegcr   r   r  r  r  r  rY  rK  s;                                                              r?   _sink_waits_iterative_internalr    s    ?f+arz$.qww/C/C/H/H/J$KL%/0H0H0J%KM 	$FL-H" 9@E5%35E 0 	"5),Ee,LLL0H 0
 )/r
D lO== % 	== $ !&

uT{64[
$+7O$(GG d#O(CDD!)^+uT{-L)%u=x.
*	9l 5>	4IIt1""($K	


(.q1#BB""FFFWX (J$+HJ,C )$$"E $-#?#?|TU	I  **,JH !ajjlD9919 H  JJ,Y7>y?Q?Q?S>TU (  #'.Q3Fy3Q"  3T3// !!*J %KK/	:2Q9)T5Q$3/	9a 3<Y1GI.8C)Xi-@@M(+)<	+B1+E)% LLA%L(4S(9D% %i 0I% )XX. 3<3D2E01C1C1E0FH ,  +8*KY^^EU@V?W X((1(:(:(<'=T9C]C]C_B`Aa b%%1#%6$7"*#EQAJJL#E"F./?.@	B (  BB9>>* /N5eYNPX/+Iy! &)I	,A%BN$'9y+@=+P$QM %~5//=.>>PQ^P_a ,  1; !) 3I 1}[)9A)= ), NNT^^;)
 Q ?) KLL:E:L:L:N 6L,)SL<4O-PSV !<,#>#JT . M )1,"8 D88E!H !0 " "-!2!2!4" ! % , , %1$09$<3"B	" 0@	/J#..1D1N1NN   ?s$9 D <%''K $
 HN.0G , N NNO
 '~&6i}M $ JJ!OJOO9#5#5#7"899O?:z5%E 2Q-eT5A82.Iy, 'DN&DN!*Y!6D ,D9##G"' 
 0J,M %1%uE.! $*K-) -j)I[ #\ _ 
uT{6b 2"J uW	0JJ $Fs   [
[#[0[c                    t        |       d   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  rH   s    r?   r  r    s    . *&1!44rI   c                    t         j                  dk(  r| j                         }|S t        t         j                        sJ t        j                  |       }|S )z;
    Returns estimated op runtime in milliseconds (ms)
    rw   )r   r]  r&   callable)r7   runtimes     r?   r]  r]    sR     !!Y.--/ N 22333,,U3NrI   c           
     b   | j                         }t        |      dk(  rd}t        | j                  t        j
                  t        j                  f      rd| j                         D cg c]  }|j                          c} }d| j                  D cg c]  }|j                   c} }d| j                          d| j                  j                   d| d| d		}| j                         D cg c]  }|j                  j                          }}d
j                  |D 	cg c];  }	t        |	t        j                        rd|	j                   d|	j                    d	nd= c}	      }
	 | j                  j#                         }| j                  j&                  j(                   | |
 d| d| j+                         ddS g }|D ]  }|j-                  t/        |              | j&                  j(                   ddj                  |       S c c}w c c}w c c}w c c}	w # t$        $ r d}Y w xY w)Nr   rZ   zouts:zins: z (z)
 (),z (size=z	, stride=z.0fz ns): z, )	get_nodesr3   r   ry   r   ExternKernelOut_CollectiveKernelr   r   r   r   rr   get_output_specr   Layoutsizestridemaybe_get_nameAttributeError	__class__rj   r&   r   r>  )r7   r5   detailr   outs_strr   ins_strchildlayoutslayoutout_tensor_infor  	summarieschild_snodes                 r?   r>  r>    s   __F
6{aejj2#5#5r7K7K"LMe6G6G6IJ

JKLHe.F.FGaffGHIG)*"UZZ-J-J,K4PXzYZ[bZccdeF=B__=NOE5::--/OO((
 &	  fbii0 &++ia@
	

113I **&&//08II;VXY^YtYtYvwzX{{  A  	A I 4k234oo&&'r$))I*>)?@@/  KGO  	I	s+   )HH/!H!A H)H   H.-H.c                &   d}d }d }t        |       D ]  \  }}|^t        |      r|t        |      z  }|j                  }n$t	        |j                        rn|t        |      z  } ||t        |              ft        |      r.|t        |      z  }|j                  } ||t        |              t	        |j                        r ||t        |              d } ||dt        |               t        j                  d|dz  dz          y )Nr   c                :    t         j                  | dd|        y )Nz>6r  )rC  debug)steprt  s     r?   step_logz#visualize_overlap.<locals>.step_log,  s    T"IRu-.rI   z| zEst. runtime (ms): i  )r   r   r]  ry   r   r>  rC  r  )ordertotal_est_runtimecur_comm_noder  r  r7   s         r?   visualize_overlapr  %  s     #M/ !' ;e "5)!%8%??! %

$ !%8%??!Tl5124"5)!%8%??! %

,u"5!68$,u"5!68 $L$7#89:-;. 
/$6=>?rI   c                (   | }t        t        j                  j                  j	                               }t        t        j                  j                               }t        j                  D ]I  }t        |t              r|t               v rt               |   }t        |      sJ d| d       t        | t        | |      |      \  }}t        j                  j!                         dk(  r(t"        j%                  d| d|d       	 t'        |       t+        j*                         } ||      }t+        j*                         |z
  }	t        j                  j!                         dk(  r(t"        j%                  d	| d
|	 d       	 t'        |       t        | t        | |      |      \  }}t-        d|       L |S # t(        $ r!}t"        j%                  d|       Y d }~d }~ww xY w# t(        $ r!}t"        j%                  d|       Y d }~d }~ww xY w)Nz3Invalid reorder_compute_and_comm_for_overlap pass: z is not callabler   z.==== Visualize overlap before reordering pass z, peak_memory=z ====rZ   )exc_infoz-==== Visualize overlap after reordering pass z	 (ran in z	 sec)====zfinal peak_memory=)r   r    rZ  r   r[  r\  r   'reorder_for_compute_comm_overlap_passesr   rU   globalsr  r   r   r/   r(   get_rankrC  r  r  	Exceptiontimeprint)
r5   r  r   r   pr   r;   et0ts
             r?   $reorder_compute_and_comm_for_overlapr*  K  s    E$.qww/C/C/H/H/J$KL%/0H0H0J%KM;; 'a!wy.	!A{ 	
A!DTU	
{ .*6<@-
Q %%'1,@?k^SXY2!%( YY[%IIK"%%'1,?s)A3iX2!%( .*6<@-
Q 	#{n%&?'B L%  2!!"q!112  2!!"q!112s0   F:G':	G$GG$'	H0HHc           
        t        | j                        t        t               t        t               t              D ]  \  }}|j                  dk(  s|j
                  t        j                  j                  j                  j                  u sQ|j                  d   j                  dk(  sJ d| d|j                  d    d       |j                  d   }|j                  d   }|dkD  r|   j                  |       |   j                  |        fd}t        t               }t              D ]  \  }}|j                  dk(  s|j
                  t        j                  j                  j                  j                  u sQ|}|j                  d   j                  dk(  sJ d	 d
|  d        |      s|   j                  |        d }d D ]  }|j                  dk(  st        |j
                  t        j                   j"                        sB|j
                  j$                  j&                  sc ||      rl ||j)                               sJ d| d        |j+                         D ]!  \  }	t        |	      D ]  \  }
}|   }|j                  d   u sJ |j                  \  }|dz   }|
t-        |	      dz
  k  r|	|
dz      nt-              dz
  }|| }t/        fd|D              rJ d d| d|  d       |D ]  }|j                  dk(  s|j                  v s"|j
                  t        j                  j                  j                  j                  k7  s^t1        fd|j                  D              }||_          $ |j3                         D ]  }	|	D ]  }|   }| j5                  |        ! D ]p  }|j                  dk(  s|j
                  t        j                  j                  j                  j                  u sN|j                  d   |v s`| j5                  |       r y)a  
    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 r2  r   c                l   j                  | g       }j                  | g       }t        |      t        |      k7  r2t        j                  d|  dt        |       dt        |       d       yt	        ||      D ]7  \  }}||k\  st        j                  d|  d|    d| d	|    d| d
        y y)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   r3   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        r?   check_resize_patternzLremove_fsdp2_unsharded_param_graph_input_usage.<locals>.check_resize_pattern  s    !J M M!
 DGGUWX$%-?)@@KKHHS} U E#&8"9!: ;  47!#54
 	/ "_43I>P4Q3RR\]o\p q  )/ :;:oEV W 	 rI   z\
Assumed all FSDP2 `unsharded_param`s to be graph input, but it's not true!
Offending node: z	. Graph: c                    | j                   t        j                  j                  j                  j
                  u xs: | j                   t        j                  j                  j                  j
                  u S rd   )targetr/   rt   fsdpcopy_rw   inductorresize_storage_bytes_)ry   s    r?   is_allowed_mutationzKremove_fsdp2_unsharded_param_graph_input_usage.<locals>.is_allowed_mutation  sO    KK599>>//777 O{{eii00FFNNN	
rI   c           	     n   t        | j                  t        j                  j                        r^t        | j                  j                  j                        D cg c])  \  }}|j                  |j                  j                  r|+ c}}ng }t        |D cg c]5  }t        | j                  |   j                  d   j                               7 c}      }t        |D cg c](  }t        |j                  d   j                               * c}      }t        ||z        dkD  S c c}}w c c}w c c}w )Nvalr   )r   r;  r/   _ops
OpOverloadr   _schema	arguments
alias_infois_writer   r   argsmetauntyped_storager3   )ry   unsharded_paramsr>   r   mutated_arg_idxesmutated_node_arg_storagesunsharded_paramstorages_of_unsharded_paramss           r?   -is_node_mutating_unsharded_param_or_its_aliaszeremove_fsdp2_unsharded_param_graph_input_usage.<locals>.is_node_mutating_unsharded_param_or_its_alias  s    $++uzz'<'<= &dkk&9&9&C&CDAq<<+0E0E   	 %/ + tyy|007GGIJ%
! (2 (8# 33E:JJLM(
$ ,/KKLqPP)s   .D':D-"-D2zdUser mutation on FSDP2 unsharded param is not allowed when Traceable FSDP2 is used. Violating node: c              3  2   K   | ]  } |g        y wrd   rp   )r   ry   rQ  rO  s     r?   r   zAremove_fsdp2_unsharded_param_graph_input_usage.<locals>.<genexpr>	  s#       >d_DUVs   z(Assumed no ops mutating unsharded param z in subgraph z, but it's not true!
Graph: c              3  .   K   | ]  }|u rn|  y wrd   rp   )r   argreplacementrO  s     r?   r   zAremove_fsdp2_unsharded_param_graph_input_usage.<locals>.<genexpr> 	  s%      % (+o'=3F%s   N)r-   r  r   r   opr;  r/   rt   r>  r?  rw   rI  r   r<  r=  r   rC  rD  rE  
is_mutabler[  r  r3   r   tupler.   
erase_node)rZ  r   ry   r1  new_sizer9  '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_argsr6  r7  rQ  r8  rU  rO  s                    @@@@@@r?   .remove_fsdp2_unsharded_param_graph_input_usagerc  u  s{    U[[!I 1<D0A--8->*y) P	TGG&uyy11GGOOO99Q<??m3  :2267Z[_[d[def[gZh i6 3 ))A,Kyy|H!|9+FMMcR6{CJJ3OP"J /:$.?+y) 	U	T77o%$++9M9M9U9U*U!N"iilO"%%6  = !5' 29 6 $O47HOOPST	U
Q4  GG&4;;

(=(=>##..'-D=BBD eeidj k : 
1	6	6	8") 	%./C%D 	)!A!&'9:N!&&q)_<<<+00NA{!3a!7 s/0144 %QU+^a' 
 ''9:JKN *  ))8(9~FV Ww   ' 
)GG.'4994uyy'9'9'O'O'W'WW$ %#'99%  H !)DI
))	)	")J !H N N P -"6 	-&'9:N^,	--  #GG&uyy11GGOOO		! GGT"#rI   c                  	 	 dd l 		j                  j                         sJ 	j                  j                  j
                  r 	j                  j                  j                  sJ 	 ddl
m}m}m}m}m} 	 	fd} |       } | |	j                  j                  j
                  j                    |t"        j$                   |	j                  j&                  j(                  j                    |d       |d       |d       |d       |d	             |d
             |d       |d            |d       d	fd       } ||        |j+                  |        y # t        t        t        f$ r Y y w xY w)Nr   r   )CallFunction
KeywordArgMatchPatternMatcherPassregister_graph_patternc                H   t        | j                        }|D ]  }|j                  t        j                  u s |j
                  d   j                  j                  j                  j                  j                  u sd|j
                  d   dk(  sw| j                  |        y )Nr   r   )r-   r  r;  operatorgetitemrI  rt   r<  all_gather_copy_inrw   rY  )gr8  r   r/   s      r?   remove_unused_getitemz8reinplace_fsdp_all_gather.<locals>.remove_unused_getitem[	  su    M	 	 AH,,,FF1I$$		(I(I(Q(QQFF1INQ	 rI   all_gather_inputsall_gather_outputinp_split_sizesall_gather_input_numelrankitem_idx
group_size
group_namec                &    | j                   d   dk(  S )Nru  r   )kwargs)matchs    r?   r8  z+reinplace_fsdp_all_gather.<locals>.<lambda>|	  s    %,,z":a"? rI   )	pass_dictextra_checkc                l    fd}| j                  ||d   |d   |d   |d   |d   |d   |d   g       y )	Nc                     | d d }| d   }| d   } j                   j                  j                  j                  | }|d   }|d   }j                   j                  j
                  j                  ||||      }|S )Nr   r   r   )out)rt   r<  rm  rw   _c10d_functionalall_gather_into_tensor_out)	rI  copy_in_argsrv  rw  rm  rl  	getitem_1all_gather_into_tensorr/   s	           r?   replzEreinplace_fsdp_all_gather.<locals>.reinplace_all_gather.<locals>.repl	  s      9LbJbJ!J!B!B!J!J" )+G*1-I		**EEMMZ N  #
 *)rI   rp  rq  rr  rs  rt  rv  rw  )replace_by_example)rz  rI  ry  r  r/   s       r?   reinplace_all_gatherz7reinplace_fsdp_all_gather.<locals>.reinplace_all_gatherh	  s[    .	*$ 	  *+*+()/0v|$|$	
rI   )rz  rg  )5torch.distributed.fsdp._fully_shard._fsdp_collectivesr(   r  rt   r  r  r  ImportErrorr
  AssertionErrorpattern_matcherre  rf  rg  rh  ri  rw   rk  rl  r<  rm  apply)
rZ  re  rf  rg  rh  ri  ro  
graph_passr  r/   s
            @r?   reinplace_fsdp_all_gatherr  6	  sd   
D  --/// II&&==		**EE	
FE
  	  $%JII&&==EE  IINN55==23230178v& :& |$|$	
$ ?),
-,
B % UA 8 s   A"E E10E1c                    t        | t        j                  j                  j                  t        j                  j                  j
                  f      rJ t        | j                         dd        S )Nr   )r   r/   	_inductorrb  FusedSchedulerNoder}   rW   r   r   s    r?   
get_op_idxr  	  s]    OO%%88OO%%::	
   u~~#$$rI   c           	     ~	   ! ddl m  g }t        t                  }d}d}i }i }i ! !fd}	| D ]  }
t	        |
j
                  t        j                  j                  j                  j                        rt        fd|
j                  D              rd}|
}t               }t        |||       t        t        j                  j                  j                  j                  t        j                  j                  j                  j                  t        j                  j                  j                   j                  g      t#        ||| fd	       t%        |d
       }t'        |      }d}t)        t'        |            D ]W  }||   }t+        |j
                  t        j                  j                  j                   j                        r|dz  }|dkD  sU|} n |d | }d }t)        t'        |      dz
        D ]3  }t-        ||dz      j
                  t.        j0                        s.|dz   } n |J  |	|d |       } |	||d        }|||<   't+        |
j
                  t        j                  j                  j2                  j                        skd}|
}t               }t#        |||       t%        |d       }d }t)        t'        |      dz
        D ]3  }t-        ||dz      j
                  t.        j0                        s.|dz   } n |J  |	|d |       } |	||d        }|||<    t'        !      dkD  sJ |rt'        |      dkD  sJ |rt'        |      dkD  sJ | D ]N  }
|
j5                         !v r!|
j5                            }
|
|v r-|j7                  |
       |j9                  |
       P d }|j;                         D ]k  \  }}|bt=        t?        |jA                                     }|jC                         D ]-  }|jE                  tG        |j5                         |d             / |}m d }|j;                         D ]k  \  }}|bt=        t?        |jA                                     }|jC                         D ]-  }|jE                  tG        |j5                         |d             / |}m |S )Nr   )rb  Fc                    j                   j                  |       }| D ]  }||j                         <    ||j                         <   |S rd   )r}   creater   )snodes_to_group
group_noder7   rb  snode_name_to_final_snodes      r?   _create_group_nodez:enforce_comm_ordering_for_fsdp.<locals>._create_group_node	  sV    33::?K
$ 	EE:D%enn&67	E;E!*"5"5"78rI   )rV  c              3     K   | ]I  }t        |   j                  t        j                  j                  j
                  j                         K y wrd   )r   ry   r/   rt   r<  rm  rw   )r   r   r  s     r?   r   z1enforce_comm_ordering_for_fsdp.<locals>.<genexpr>	  sD      
  "1%**EIINN,M,M,U,U
s   AATc                    t        | j                        xs0 t        | j                        xr | j                  j                  v  S rd   )r   NopKernelSchedulerNodeExternKernelSchedulerNodery   op_overload)r   allowed_opsrb  s    r?   r8  z0enforce_comm_ordering_for_fsdp.<locals>.<lambda>	  sF    q)"B"BC "1i&I&IJ >FF..+=	' rI   )criteria_cbc                    t        |       S rd   r  r  s    r?   r8  z0enforce_comm_ordering_for_fsdp.<locals>.<lambda>	  
    JqM rI   r  r   c                    t        |       S rd   r  r  s    r?   r8  z0enforce_comm_ordering_for_fsdp.<locals>.<lambda>$
  r  rI   r  )$rZ   rb  r   r   r   ry   r/   rt   r  r  rw   r   r  r   wait_tensorr<  split_with_sizes_copyr   sortedr3   r+   r   r   r   _WaitKernel	chunk_catr   r   r  r  r  r  r   r   r  r   )"r5   r  r  	new_orderr  	ag_exists	rs_exists$ag_grouped_node_to_wait_grouped_node$rs_grouped_node_to_wait_grouped_noder  r7   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  rb  r  s"     `                            @@@r?   enforce_comm_ordering_for_fsdpr  	  s   
 )+I3!III+-(+-( "  nUJJ59955PPXX
 
 __	
 
 IHLVL  ($"	 %II..IIQQII..::BBIINN88@@K )$" !'$*A! +..?*@'N3012 -a0	!NNEIINN$H$H$P$P #a'N!A%23/ !22N3N O !M301A56 /A6;;R^^L$%EM !,,,./@-/PQM "44Emn4U!VBT0? EJJ		(@(@(H(HIIH MWL ($"	 !'$*A!
 !M301A56 /A6;;R^^L$%EM !,,,./@-/PQM "44Emn4U!VBT0?]nU` ()A---781<<<781<<<  >>88-enn.>?EIe L*N*T*T*V '&#]%C%C%E FGL!--/ **AJJL|TR '' L*N*T*T*V '&#]%C%C%E FGL!--/ **AJJL|TR '' rI   )r5   list[BaseSchedulerNode])r5   r  r   r  )ry   z"Optional[Union[IRNode, Operation]]r   r   )r7   r"   r   r   )r7   r"   )r   r  r   dict[BaseSchedulerNode, float]r   tuple[float, float, str])r5   r  r   r  r   r  )F)r   rU   )r   r  r   rU   )r5   r  r   ztuple[dict[BaseSchedulerNode, Optional[BaseSchedulerNode]], dict[BaseSchedulerNode, Optional[BaseSchedulerNode]], BaseSchedulerNode])r   r"   r   r"   r   r   )r   Optional[BaseSchedulerNode]r   r  r   4dict[BaseSchedulerNode, Optional[BaseSchedulerNode]]r   r  )r   r"   r   r"   r   r"   r   r  r   r  r   r"   r   r"   )r   r"   r   r  r   r"   r   rW   r   rW   r   r   r   r   r   r   r   z(tuple[int, dict[BaseSchedulerNode, int]])r   r"   r   r  r   r"   r   rW   r   r   r   r   r  dict[BaseSchedulerNode, int]r   r   r   r   r   r   r   rT   )r   r"   r   r  r   r   r   z>dict[BaseSchedulerNode, list[Union[FreeableInputBuffer, Any]]])r   r"   r   ztuple[bool, Optional[str]])rE  z$dict[BaseSchedulerNode, ReorderInfo]r   r"   r   r  rF  rW   r   rW   r   r   r   OrderedSet[str]r   r  )r5   r  r   zDtuple[list[BaseSchedulerNode], dict[BaseSchedulerNode, ReorderInfo]])
r5   r  rC   r   rD   r   rE   r   r   r  )r  r  r   r  )r   r"   r   r  r   rW   r   r   r  r   r  r  r  r  r   r   r   r   r   rT   )r   r"   r   r  r   r"   r   rW   r   rW   r   r   r  r   r   r   r   r   r   zFtuple[int, dict[BaseSchedulerNode, int], dict[BaseSchedulerNode, int]])rE  z%dict[BaseSchedulerNode, SinkWaitInfo]r   r"   r   r  rF  rW   r   rW   r   r   r   r  r   r  )r5   r  r   zEtuple[list[BaseSchedulerNode], dict[BaseSchedulerNode, SinkWaitInfo]])r7   r"   r   r]   )rZ  torch.fx.Graph)rZ  r  r   rT   )r5   1list[torch._inductor.scheduler.BaseSchedulerNode]r  z4dict[str, torch._inductor.scheduler.SchedulerBuffer]r  zdict[str, BaseSchedulerNode]r   r  )h
__future__r   r  r?  r  loggingrk  r  r$  collectionsr   dataclassesr   typingr   r   r   r	   r/   torch._loggingr
    torch.multiprocessing.reductionsr   torch.utils._ordered_setr   rZ   r   r   r   dependenciesr   r   r   memoryr   r   r   r   r   utilsr   r   r   r   r   r   r   virtualizedr    	getLoggerrj   r/  _logginggetArtifactLoggerrC  r   r"   r@   rD   rC   rL   rQ   rS   rz   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r$  rM  rN   rG   r  r  r  r  r  r  r  r  r  r  r]  r>  r  r*  rc  r  r  r  rp   rI   r?   <module>r     sb   #      
  # ! 6 6  + ; / & & ! %     g!nn..xC;M#M,#&####L 9 9 9("(7.+7.7U7.7.t;.#;.,;. ;.|03&#"	.'	.5F	.		.G
;
%
% D 	6. .!. ". D	.
 D. . .b@. @.	 @. "@. 	@.
 @. %@. 6:@. @. .@.FJ J	 J "J 	J
 %J 6:J 4J J  J J 
JZ$; $;	 $;  $; D	$;N <c/c
c Dc 	c
 c !%c #c cLE#EIEP
Y#YY Y 	Y
 Yx"0 9 9 9") ))X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X0X
X DX 	X
 X !%X #X Xv,C ,C	 ,C  ,C D	,C^A#AJAH
54	A>#L'#''T~#BjZ%n=nEn 5n 7	nrI   