Ë
    g^(h¬`  ã                  ó&  — d dl mZ d dlZd dlZd dlZd dlZd dlmZmZm	Z	m
Z
 d dlmZ d dlmZ ddlmZmZ ddlmZ dd	lmZ erdd
lmZ ddlmZmZ  ej6                  e«      Zej<                   G d„ d«      «       Zej<                   G d„ d«      «       Z ej<                   G d„ d«      «       Z!	 	 	 	 	 	 dd„Z"	 	 	 	 dd„Z#	 	 	 	 	 	 dd„Z$	 	 	 	 	 	 	 	 	 	 dd„Z%	 	 	 	 	 	 	 	 dd„Z&	 	 	 	 	 	 	 	 	 	 d d„Z'd!d„Z(d!d„Z)e'e(e)gf	 	 	 	 	 	 	 	 	 	 	 	 	 d"d„Z*y)#é    )ÚannotationsN)ÚCallableÚTYPE_CHECKINGÚ	TypedDictÚUnion)Úsignpost_event)Ú
OrderedSeté   )ÚMultiOutputLayoutÚ
NoneLayout)Úget_dtype_size)ÚV)ÚDep)ÚBaseSchedulerNodeÚSchedulerBufferc                  óZ   — e Zd ZU dZded<   dZded<    ej                  e¬«      Z	ded<   y)	ÚMemoryPlanningInfoForBufferr   ÚintÚ
size_allocÚ	size_free©Údefault_factoryúOrderedSet[BaseSchedulerNode]Ú
succ_nodesN)
Ú__name__Ú
__module__Ú__qualname__r   Ú__annotations__r   ÚdataclassesÚfieldr	   r   © ó    úT/var/www/skyplay_api_hub/venv/lib/python3.12/site-packages/torch/_inductor/memory.pyr   r      s3   … à€J�ÓØ€IˆsÓØ0A°×0AÑ0AØ"ô1€JÐ-ô r"   r   c                  óº   — e Zd ZU dZded<   dZded<    ej                  e¬«      Z	ded<    ej                  e¬«      Z
ded	<    ej                  e¬«      Zded
<   y)ÚMemoryPlanningInfoForNoder   r   ÚindexÚsizer   z7OrderedSet[Union[SchedulerBuffer, FreeableInputBuffer]]Úpred_buffersr   Ú
pred_nodesr   N)r   r   r   r&   r   r'   r   r    r	   r(   r)   r   r!   r"   r#   r%   r%   "   sq   … à€Eˆ3ƒNØ€Dˆ#ƒMàˆ×Ñ¨*Ô5ð ÐIó ð 1B°×0AÑ0AØ"ô1€JÐ-ó ð 1B°×0AÑ0AØ"ô1€JÐ-ô r"   r%   c                  óX   — e Zd ZU ded<    ej
                  e¬«      Zded<   d	d„Zd
d„Z	y)ÚFreeableInputBufferÚstrÚnamer   r   Ú
mpi_bufferc                ó   — | j                   S ©N)r-   ©Úselfs    r#   Úget_namezFreeableInputBuffer.get_name8   s   € Ø�y‰yÐr"   c                ó,   — t        | j                  «      S r0   )Úhashr-   r1   s    r#   Ú__hash__zFreeableInputBuffer.__hash__;   s   € Ü�D—I‘I‹Ðr"   N)Úreturnr,   )r7   r   )
r   r   r   r   r   r    r   r.   r3   r6   r!   r"   r#   r+   r+   1   s.   … à
ƒIØ.?¨k×.?Ñ.?Ø3ô/€JÐ+ó óôr"   r+   c                óÒ  — dd„}t        j                  t        «      }t        «       }| D ]{  }|j                  j
                  D ]`  }|j                  |v sŒ|j                  j                  d«      rŒ.||j                     j                  |«        ||«      ||j                  <   Œb Œ} t        «       }|j                  «       D ]"  \  }}	t        |t        ||   |	¬«      «      ||<   Œ$ |S )z¸
    Create and keep track of all input buffers that can be freed during the program

    Returns:
        A dictionary containing all freeble input buffers, keyed by their names.
    c                ól   — d}	 | j                  «       s| j                  «       }|S # t        $ r Y |S w xY w)Nr   )Úhas_unbacked_symbolsÚnumbytes_hintÚKeyError)ÚdepÚress     r#   Ú_dep_size_hintz.get_freeable_input_buf.<locals>._dep_size_hintL   sH   € Øˆð	Ø×+Ñ+Ô-Ø×'Ñ'Ó)�ð ˆ
øô ò 	ð Øˆ
ð	ús   „ & ¦	3²3)Úprimals_Úarg)r   r   )r=   r   r7   r   )ÚcollectionsÚdefaultdictr	   ÚdictÚread_writesÚreadsr-   Ú
startswithÚaddÚitemsr+   r   )
ÚnodesÚgraph_inputsr?   Údep_name_to_succ_nodesÚdep_name_to_sizeÚnoder=   Úname_to_freeable_input_bufÚdep_namer   s
             r#   Úget_freeable_input_bufrQ   ?   s÷   € ó
ô 	×Ñ¤
Ó+ð ô (,£vÐØò AˆØ×#Ñ#×)Ñ)ò 	AˆCØ�x‰x˜<Ò'°·±×0CÑ0CØ#õ1ð ' s§x¡xÑ0×4Ñ4°TÔ:Ù-;¸CÓ-@Ð  §¡Ò*ñ	AðAô BFÃÐØ 6× <Ñ <Ó >ò 
Ñˆ�*Ü/BØÜ'Ø*¨8Ñ4Àôó0
Ð" 8Ò,ð
ð &Ð%r"   c                óº   ‡‡‡‡— ddl mŠ ddlmŠ t	        «       Š	 d	 	 	 	 	 dˆˆˆˆfd„Š| j                  «       D ]  }|j                  «       ‰vsŒ ‰|«       Œ ‰S )aË  
    Compute the size of each scheduler buffer, including (1) memory allocated when
    it is created and (2) memory deallocated when it is freed.

    We specially handle the case of MultiOutputLayout.
    Consider the following case:
        buf0 = some_ops_with_multi_outputs(...)
        buf1 = buf0[0] # assume 10 bytes
        buf2 = buf0[1] # assume 20 bytes
    In such cases,
        buf0: at creation, 30 bytes allocated, when deleted, 0 bytes freed
        buf1: at creation, 0 bytes allocated, when deleted, 10 bytes freed
        buf2: at creation, 0 bytes allocated, when deleted, 20 bytes freed

    Returns:
        A dictionary mapping a scheduler buffer to a tuple of (size_alloc, size_free).
    r
   )ÚMultiOutput)Ú
OutputNodec                óÎ  •— t        | j                  j                  t        «      rd‰	| j	                  «       <   yt        | j                  j                  t
        «      r‡d}| j                  D ][  }t        |j                  ‰«      rŒ|j                  j                  «       D ]%  }t        |j                  ‰«      sŒ| ‰|d«      z  }Œ' Œ] |rdn|df‰	| j	                  «       <   |S t        j                  j                  j                  | j                  j                  «       d¬«      t        | j                  j                  «       «      z  }|rdn||f‰	| j	                  «       <   |S )N)r   r   r   T)Úfallback)Ú
isinstancerN   Úlayoutr   r3   r   ÚusersÚget_outputsr   ÚgraphÚsizevarsÚ	size_hintÚ	get_numelr   Ú	get_dtype)
Ú	sched_bufÚuser_of_MultiOutputLayoutr   ÚuserÚbufÚbuf_sizerS   rT   Ú_compute_and_update_buf_sizeÚsched_buf_to_sizes
         €€€€r#   re   zGcompute_size_for_scheduler_buffer.<locals>._compute_and_update_buf_size‹   sL  ø€ ô �i—n‘n×+Ñ+¬ZÔ8Ø6<Ð˜i×0Ñ0Ó2Ñ3ØÜ˜	Ÿ™×-Ñ-Ô/@ÔAØˆJØ!Ÿ™ò N�Ü˜dŸi™i¨Ô4ØØŸ9™9×0Ñ0Ó2ò N�CÜ! #§(¡(¨KÕ8Ø"Ñ&BÀ3ÈÓ&MÑM™
ñNðNñ /‘°JØð7Ð˜i×0Ñ0Ó2Ñ3ð Ðä—w‘w×'Ñ'×1Ñ1Ø—‘×(Ñ(Ó*°Qð 2ó ä˜yŸ~™~×7Ñ7Ó9Ó:ñ;ˆHñ /‘°HØð7Ð˜i×0Ñ0Ó2Ñ3ð ˆOr"   )F)r`   r   ra   Úboolr7   r   )ÚirrS   Ú	schedulerrT   rD   Úvaluesr3   )Úname_to_bufr`   rS   rT   re   rf   s     @@@@r#   Ú!compute_size_for_scheduler_bufferrl   r   sz   û€ õ(  Ý%ä48³FÐð GLðØ"ðØ?Cðà	÷ð ð: !×'Ñ'Ó)ò 4ˆ	ð ×ÑÓÐ'8Ò8Ù(¨Õ3ð	4ð Ðr"   c                ó,  — t        |«      }t        j                  t        «      }| D ]1  }|j                  D ]   }||j
                     j                  |«       Œ" Œ3 |j                  «       D ]'  }t        ||   d   ||   d   ||   ¬«      ||   _	        Œ) y)z“
    For each SchedulerBuffer, assign its size info and successor nodes.
    A buffer's successor nodes determines when a buffer can be freed.
    r   r
   )r   r   r   N)
rl   rB   rC   r	   Úunmet_dependenciesr-   rH   Úkeysr   r.   )rJ   rk   rf   rL   rN   r=   Úbuf_names          r#   Ú1assign_memory_planning_info_for_scheduler_buffersrq   ±   s¯   € ô :¸+ÓFÐô
 	×Ñ¤
Ó+ð ð ò 7ˆØ×*Ñ*ò 	7ˆCØ" 3§8¡8Ñ,×0Ñ0°Õ6ñ	7ð7ð  ×$Ñ$Ó&ò 
ˆÜ+FØ(¨Ñ2°1Ñ5Ø'¨Ñ1°!Ñ4Ø-¨hÑ7ô,
ˆ�HÑÕ(ñ
r"   c                óL  ‡‡— ddl mŠ t        | «      D �]  \  }}t        d„ |j	                  «       D «       «      }t        t        ‰t        f      «       }|j                  j                  D ]j  }|j                  |v r-||j                  v r|j                  ||j                     «       Œ>|j                  |v sŒM|j                  ||j                     «       Œl t        ˆˆfd„|D «       «      }	t        d„ |j	                  «       D «       «      }
t        ||||	|
¬«      |_        �Œ y)zL
    Assign to each scheduler node its predecessor and successor nodes.
    r
   )r   c              3  óH   K  — | ]  }|j                   j                  –— Œ y ­wr0   )r.   r   )Ú.0Úbuffers     r#   ú	<genexpr>zBassign_memory_planning_info_for_scheduler_nodes.<locals>.<genexpr>Û   s   è ø€ ÒW¸&˜×*Ñ*×5Õ5ÑWùó   ‚ "c              3  ó\   •K  — | ]#  }t        |‰«      r‰|j                  «          –— Œ% y ­wr0   )rW   Údefining_op_name)rt   Úpred_bufferr   Úname_to_fused_nodes     €€r#   rv   zBassign_memory_planning_info_for_scheduler_nodes.<locals>.<genexpr>â   s1   øè ø€ ò  
àÜ˜;¨Ô8ð ˜{×;Ñ;Ó=Õ>ñ 
ùs   ƒ),c              3  óV   K  — | ]!  }|j                   j                  D ]  }|–— Œ Œ# y ­wr0   )r.   r   )rt   ru   Ú	succ_nodes      r#   rv   zBassign_memory_planning_info_for_scheduler_nodes.<locals>.<genexpr>ç   s9   è ø€ ò  
àØ#×.Ñ.×9Ñ9ò 
ð ô ð 
Øñ 
ùs   ‚'))r&   r'   r(   r)   r   N)ri   r   Ú	enumerateÚsumrZ   r	   r   r+   rE   rF   r-   rn   rH   r%   Úmpi_node)rJ   r{   rk   rO   r&   rN   r   r(   r=   r)   r   r   s    `         @r#   Ú/assign_memory_planning_info_for_scheduler_nodesr�   Ï   s  ù€ õ +ä  Ó'ó 
‰ˆˆtÜÑWÀD×DTÑDTÓDVÔWÓWˆ
Ü!¤%¨Ô9LÐ(LÑ"MÑNÓPˆØ×#Ñ#×)Ñ)ò 	GˆCØ�x‰x˜;Ñ&¨3°$×2IÑ2IÑ+IØ× Ñ  ¨S¯X©XÑ!6Õ7Ø—‘Ð7Ò7Ø× Ñ Ð!;¸C¿H¹HÑ!EÕFð		Gô
  ô  
à+ô 
ó 
ˆ
ô
  ñ  
à×*Ñ*Ó,ô 
ó 
ˆ
ô
 2ØØØ%Ø!Ø!ô
ˆŽñ%
r"   c                ó´  ‡— t         j                   G d„ d«      «       }t        «       Št        | «      D ]
  \  }}|‰|<   Œ g }|j	                  «       D ]‚  \  }}||v rt        | «      dz
  n't        ˆfd„|j                  j                  D «       «      }	|j                   |||j                  j                  |j                  j                  d|	«      «       Œ„ t        | «      D ]¯  \  }}|j                  «       D ]—  }
|
j                  «       |v rt        | «      dz
  n1t        |
j                  j                  D �cg c]  }‰|   ‘Œ	 c}|¬«      }	|j                   ||
|
j                  j                  |
j                  j                  ||	«      «       Œ™ Œ± t        t        | «      dz   «      D �cg c]  }d‘Œ }}|D ]G  }||j                  xx   |j                  z  cc<   ||j                   dz   xx   |j                  z  cc<   ŒI d}d}g }t        t        | «      dz   «      D ]'  }|||   z  }|j                  |«       t        ||«      }Œ) ||fS c c}w c c}w )a  
    Given a list of nodes in their execution order, estimate the peak memory, by
    keeping track of the liveliness of SchedulerBuffers and FreeableInputBuffers.

    Returns:
        int: peak memory
        List[int]: memory usage at each node (or each step).
    c                  ó@   — e Zd ZU ded<   ded<   ded<   ded<   ded<   y)	ú(estimate_peak_memory.<locals>.BufferInfoz+Union[SchedulerBuffer, FreeableInputBuffer]ru   r   r   r   Ú
start_stepÚend_stepN©r   r   r   r   r!   r"   r#   Ú
BufferInfor„     s   … à;Ó;Ø‹Ø‹Ø‹ØŒr"   rˆ   r
   c              3  ó(   •K  — | ]	  }‰|   –— Œ y ­wr0   r!   )rt   r}   Únode_to_steps     €r#   rv   z'estimate_peak_memory.<locals>.<genexpr>  s   øè ø€ ò Ø,5�˜YÕ'ñùs   ƒr   )Údefault)r   Ú	dataclassrD   r~   rI   ÚlenÚmaxr.   r   Úappendr   rZ   r3   r   Úranger…   r†   )rJ   rO   Úgraph_outputsrˆ   ÚsteprN   Úbuf_info_listrp   Ú	input_bufr†   r`   r}   Ú_ÚmemoryÚbuf_infoÚ
max_memoryÚ
cur_memoryÚmemories_at_nodesÚtrŠ   s                      @r#   Úestimate_peak_memoryrœ   õ   s˜  ø€ ô ×Ñ÷ð ó ðô 26³€LÜ Ó&ò "‰
ˆˆdØ!ˆ�TÒð"ð ')€Mà9×?Ñ?ÓAò 
Ñˆ�)ð ˜=Ñ(ô �‹J˜ŠNäó Ø9B×9MÑ9M×9XÑ9Xôó ð 	ð 	×ÑÙØØ×$Ñ$×.Ñ.Ø×$Ñ$×.Ñ.ØØóõ	
ð
ô&   Ó&ò ‰
ˆˆdØ×)Ñ)Ó+ò 	ˆIð ×%Ñ%Ó'¨=Ñ8ô �E“
˜Q’äð *3×)=Ñ)=×)HÑ)Höà%ð % YÓ/òð !ôð ð × Ñ ÙØØ×(Ñ(×3Ñ3Ø×(Ñ(×2Ñ2ØØóõñ	ðô6 œs 5›z¨A™~Ó.Ö/�AŠaÐ/€FÐ/ð "ò <ˆØˆx×"Ñ"Ó# x×':Ñ':Ñ:Ó#Øˆx× Ñ  1Ñ$Ó%¨×);Ñ);Ñ;Ô%ð<ð
 €JØ€JØÐÜ”3�u“: ‘>Ó"ò 1ˆØ�f˜Q‘iÑˆ
Ø× Ñ  Ô,Ü˜ ZÓ0‰
ð1ð
 Ð)Ð*Ð*ùòEùò$ 0s   Ä9IÆ.	Ic                ó  ‡‡‡—  G d„ dt         «      } G d„ dt         «      }t        «       Št        «       }t        «       }| D ]D  }t        |j                  j
                  «      ddœ‰|<   ‰|   d   dk(  sŒ4|j                  |«       ŒF t        |j                  «       «      t        |j                  «       «      z   D ]=  }	dt        |	j                  j                  «      |	j                  «       |v rd	ndz   i||	<   Œ? t        d
„ |j                  «       D «       «      Šd}
|D ]D  }||v r|
||   j                  j                  z  }
Œ$||v sŒ)|
||   j                  j                  z  }
ŒF t        ‰|
«      Š| D ]’  }|j                  j                  D ]2  }	||	   d   d	k(  sŒ‰|   dxx   |	j                  j                  z  cc<   Œ4 |j!                  «       D ]2  }	||	   d   dk(  sŒ‰|   dxx   |	j                  j                  z  cc<   Œ4 Œ” g }d}|t        | «      k  �rV|�rSt#        |ˆˆˆfd„¬«      }|j%                  |«       |j'                  |«       |d	z  }‰|j                  j(                  z  Št        ‰‰«      Š‰‰|   d   z  Š|j                  j                  D ]<  }‰|   d   dkD  sJ ‚‰|   dxx   d	z  cc<   ‰|   d   dk(  sŒ,|j                  |«       Œ> |j                  j                  D ]j  }	||	   d   dkD  sJ ‚||	   dxx   d	z  cc<   ||	   d   d	k(  sŒ,|	j                  j                  D ]&  }‰|   dxx   |	j                  j                  z  cc<   Œ( Œl |t        | «      k  r|r�ŒS|t        | «      kD  rt+        d«      ‚|S )að  
    A bfs-based greedy topological order. LPMF stands for "Least Peak Memory First".

    The idea is from this paper:
    Buffer memory optimization for video codec application modeled in Simulink
    https://www.cs.york.ac.uk/rts/docs/DAC-1964-2006/PAPERS/2006/DAC06/PDFFILES/P0689.PDF

    The algorithm maintain the max memory so far.
    At every iteration, for each scheduleable node, it computes:
        - how much memory needs to be allocated for the output buffers of this node;
        - how much memory can be freed as a result of executing this node.
    This gives us two values for each node:
        (1) mem1: memory during the execution of the node;
        (2) mem2: memory after executing the node, after some input buffers are freed.
    The greedy approach select as follows:
        (i) if there are nodes whose mem1 values are below the max memory so far,
            then pick the node with the lowest mem2 value;
        (ii) otherwise, pick the one with the lowest mem1 value.
    c                  ó"   — e Zd ZU ded<   ded<   y)ú'topological_sort_lpmf.<locals>.NodeInfor   ÚindegreeÚmemory_to_freeNr‡   r!   r"   r#   ÚNodeInforŸ   p  s   … Ø‹ØÔr"   r¢   c                  ó   — e Zd ZU ded<   y)ú)topological_sort_lpmf.<locals>.BufferInfor   Ú	outdegreeNr‡   r!   r"   r#   rˆ   r¤   t  s   … ØŒr"   rˆ   r   )r    r¡   r    r¥   r
   c              3  óH   K  — | ]  }|j                   j                  –— Œ y ­wr0   ©r.   r   )rt   r”   s     r#   rv   z(topological_sort_lpmf.<locals>.<genexpr>�  s$   è ø€ ò àð 	×Ñ×&Õ&ñùrw   r¡   c                ó²   •— t        ‰| j                  j                  z   ‰«      | j                  j                  ‰|    d   z
  | j                  j                  fS )Nr¡   )rŽ   r€   r'   r&   )rN   Úlive_memoryr˜   Ú	node_infos    €€€r#   ú<lambda>z'topological_sort_lpmf.<locals>.<lambda>¯  sL   ø€ Ü�K $§-¡-×"4Ñ"4Ñ4°jÓAØ—‘×"Ñ" Y¨t¡_Ð5EÑ%FÑFØ—‘×#Ñ#ð€ r"   ©Úkeyz4Failed to schedule, while loop ran too long for lpmf)r   rD   r	   r�   r€   r)   rH   Úlistrj   r.   r   r3   r   r   rŽ   r(   rZ   ÚminÚremover�   r'   ÚRuntimeError)rJ   rO   rk   r‘   r¢   rˆ   r—   Únodes_to_schedulerN   rc   Úoutput_memoryrp   ÚscheduleÚ	num_itersÚselected_noder}   r©   r˜   rª   s                   @@@r#   Útopological_sort_lpmfr·   V  så  ú€ ô4”9ô ô”Yô ô 48³6€IÜNRËf€Hô 8B³|ÐØò (ˆä˜DŸM™M×4Ñ4Ó5Øñ
ˆ	�$‰ð �T‰?˜:Ñ&¨!Ó+Ø×!Ñ! $Õ'ð(ô �K×&Ñ&Ó(Ó)¬DÐ1K×1RÑ1RÓ1TÓ,UÑUò 
ˆàœ˜SŸ^™^×6Ñ6Ó7Ø—L‘L“N mÑ3‰q¸ñ<ð
ˆ�Šð
ô ñ à3×:Ñ:Ó<ôó €Kð €MØ!ò WˆØ�{Ñ"Ø˜[¨Ñ2×=Ñ=×GÑGÑG‰MØÐ3Ò3ØÐ7¸ÑA×LÑL×VÑVÑV‰Mð	Wô
 �[ -Ó0€Jð ò Nˆà—=‘=×-Ñ-ò 	NˆCØ˜‰}˜[Ñ)¨QÓ.Ø˜$‘Ð 0Ó1°S·^±^×5MÑ5MÑMÔ1ð	Nð ×#Ñ#Ó%ò 	NˆCØ˜‰}˜[Ñ)¨QÓ.Ø˜$‘Ð 0Ó1°S·^±^×5MÑ5MÑMÔ1ñ	NðNð )+€HØ€IØ
”c˜%“jÓ
 Ò%6äØõô
ˆð 	× Ñ  Ô/Ø�‰˜Ô&Ø�Q‰ˆ	ð 	�}×-Ñ-×2Ñ2Ñ2ˆÜ˜ [Ó1ˆ
Ø�y Ñ/Ð0@ÑAÑAˆð '×/Ñ/×:Ñ:ò 	1ˆIØ˜YÑ'¨
Ñ3°aÒ7Ð7Ð7Ø�iÑ  Ó,°Ñ1Ó,Ø˜Ñ# JÑ/°1Ó4Ø!×%Ñ% iÕ0ð		1ð !×)Ñ)×6Ñ6ò 	WˆCØ˜C‘= Ñ-°Ò1Ð1Ð1Ø�S‰M˜+Ó&¨!Ñ+Ó&Ø˜‰}˜[Ñ)¨QÓ.Ø!$§¡×!:Ñ!:ò W�IØ˜iÑ(Ð)9Ó:¸c¿n¹n×>VÑ>VÑVÔ:ñWð		Wð7 ”c˜%“jÒ
 Ó%6ðD ”3�u“:ÒÜÐQÓRÐRà€Or"   c           	     ó  ‡
—  G d„ dt         «      }t        «       Š
t        j                   G d„ d«      «       }dˆ
fd„}g }| D ]V  }t	        |j
                  j                  «      ddœ‰
|<   ‰
|   d   d	k(  sŒ4t        j                  | | ||«      |«      «       ŒX g }d	}|t	        | «      k  rÀ|r¾t        j                  |«      j                  }t	        |«      ‰
|   d
<   |j                  |«       |dz  }|j
                  j                  D ]N  }	‰
|	   d   d	kD  sJ ‚‰
|	   dxx   dz  cc<   ‰
|	   d   d	k(  sŒ,t        j                  | | ||	«      |	«      «       ŒP |t	        | «      k  r|rŒ¾|t	        | «      kD  rt        d«      ‚|S )a÷  
    A BFS topological sort that selects nodes whose dependencies are executed the
    earliest. This follows a FIFO idea. Specifically, at every iteration, for each node
    that is schedulable, we gather the order in which its predecessor nodes are executed,
    and this sorted list of execution orders of predecessor nodes defines the priority.
    We select the node whose predecessors nodes are executed the earliest. The FIFO
    idea aims to reduce the liveness duration of buffers created.
    c                  ó"   — e Zd ZU ded<   ded<   y)ú&topological_sort_bfs.<locals>.NodeInfor   r    ÚorderNr‡   r!   r"   r#   r¢   rº   Ý  s   … Ø‹ØŒ
r"   r¢   c                  ó*   — e Zd ZU ded<   ded<   dd„Zy)ú.topological_sort_bfs.<locals>.NodeWithPriorityú	list[int]Úpriorityr   rN   c                óè   — | j                   |j                   k(  rA| j                  j                  j                  |j                  j                  j                  k  S | j                   |j                   k  S r0   )r¿   rN   r€   r&   )r2   Úothers     r#   Ú__lt__z5topological_sort_bfs.<locals>.NodeWithPriority.__lt__è  sP   € Ø�}‰} §¡Ò.Ø—y‘y×)Ñ)×/Ñ/°%·*±*×2EÑ2E×2KÑ2KÑKÐKØ—=‘= 5§>¡>Ñ1Ð1r"   N)rÁ   ÚNodeWithPriorityr7   rg   )r   r   r   r   rÂ   r!   r"   r#   rÃ   r½   ã  s   … àÓØÓô	2r"   rÃ   c                ó„   •— ‰|    d   dk(  sJ ‚t        t        ˆfd„| j                  j                  D «       «      «      }|S )Nr    r   c              3  ó.   •K  — | ]  }‰|   d    –— Œ y­w)r»   Nr!   )rt   Ú	pred_noderª   s     €r#   rv   z?topological_sort_bfs.<locals>._node_priority.<locals>.<genexpr>ñ  s    øè ø€ ò Ø2;�	˜)Ñ$ WÕ-ñùs   ƒ)Úsortedr	   r€   r)   )rN   Úexec_ordersrª   s     €r#   Ú_node_priorityz,topological_sort_bfs.<locals>._node_priorityí  sK   ø€ à˜‰˜zÑ*¨aÒ/Ð/Ð/ÜÜó Ø?C¿}¹}×?WÑ?Wôó ó
ˆð
 Ðr"   éÿÿÿÿ)r    r»   r    r   r»   r
   z3Failed to schedule, while loop ran too long for bfs)rN   r   r7   r¾   )r   rD   r   rŒ   r�   r€   r)   ÚheapqÚheappushÚheappoprN   r�   r   r±   )rJ   r¢   rÃ   rÉ   r²   rN   r´   rµ   r¶   r}   rª   s             @r#   Útopological_sort_bfsrÎ   Ó  sŸ  ø€ ô”9ô ô 48³6€Iä×Ñ÷2ð 2ó ð2õð 13ÐØò ˆÜ'*¨4¯=©=×+CÑ+CÓ'DÈrÑRˆ	�$‰Ø�T‰?˜:Ñ&¨!Ó+Ü�N‰NØ!Ñ#3±NÀ4Ó4HÈ$Ó#Oõðð )+€HØ€IØ
”c˜%“jÒ
 Ñ%6äŸ™Ð&7Ó8×=Ñ=ˆÜ,/°«Mˆ	�-Ñ  Ñ)Ø�‰˜Ô&Ø�Q‰ˆ	ð '×/Ñ/×:Ñ:ò 	ˆIØ˜YÑ'¨
Ñ3°aÒ7Ð7Ð7Ø�iÑ  Ó,°Ñ1Ó,Ø˜Ñ# JÑ/°1Ó4Ü—‘Ø%Ù$¡^°IÓ%>À	ÓJõð		ð ”c˜%“jÒ
 Ò%6ð" ”3�u“:ÒÜÐPÓQÐQà€Or"   c                ón  ‡‡‡‡‡— t        «       Št        «       Šg Št        «       Šdˆˆˆˆˆfd„Š| D ]  }|j                  «       D ]  }|‰|<   Œ	 Œ | D ]B  }|j                  j                  t        d„ |j                  j                  D «       «      z   ‰|<   ŒD t        | ˆfd„¬«      D ]
  } ‰|«       Œ ‰S )aß  
    This is a DFS topological sort. The setup is similar to `topological_sort_schedule`
    in scheduler.py. The difference is the order nodes are visited in the outer loop.
    In `topological_sort_schedule`, nodes are visited in their original order.
    In this function, nodes are visited based on their priority -- for each node, we
    compute the total memory of all buffers it reads from or writes to, and we visit
    the nodes in ascending order of this priority.
    c                ó   •— | ‰vrt‰j                  | «       | j                  D �cg c]  }|j                  ‰v r‰|j                     ‘Œ! }}t        |ˆfd„¬«      D ]
  } ‰|«       Œ ‰j	                  | «       y y c c}w )Nc                ó:   •— ‰|    | j                   j                  fS r0   ©r€   r&   ©ÚnÚsize_with_readss    €r#   r«   z5topological_sort_dfs.<locals>.visit.<locals>.<lambda>2  s   ø€ ¨/¸!Ñ*<¸a¿j¹j×>NÑ>NÐ)O€ r"   r¬   )rH   rn   r-   rÇ   r�   )	rÔ   r=   Ú	dep_nodesrN   Úname_to_nodeÚresultÚseenrÕ   Úvisits	       €€€€€r#   rÚ   z#topological_sort_dfs.<locals>.visit)  sŒ   ø€ Ø�D‰=Ø�H‰H�QŒKð ×/Ñ/öàØ—8‘8˜|Ñ+ð ˜SŸX™XÓ&ðˆIð ô
 ØÓOôò �ñ �d•ðð �M‰M˜!Õð ùòs   ¥$A;c              3  óH   K  — | ]  }|j                   j                  –— Œ y ­wr0   r§   )rt   Úpred_bufs     r#   rv   z'topological_sort_dfs.<locals>.<genexpr><  s!   è ø€ ò 9
Ø.6ˆH×Ñ×)Õ)ñ9
ùrw   c                ó:   •— ‰|    | j                   j                  fS r0   rÒ   rÓ   s    €r#   r«   z&topological_sort_dfs.<locals>.<lambda>?  s   ø€ ¨_¸QÑ-?ÀÇÁ×AQÑAQÐ,R€ r"   r¬   )rÔ   r   r7   ÚNone)r	   rD   Úget_buffer_namesr€   r'   r   r(   rÇ   )rJ   rN   r-   r×   rØ   rÙ   rÕ   rÚ   s      @@@@@r#   Útopological_sort_dfsrà     sË   ü€ ô +5«,€DÜ15³€LØ&(€FÜ48³F€O÷ñ ð ò &ˆØ×)Ñ)Ó+ò 	&ˆDØ!%ˆL˜Òñ	&ð&ð ò 
ˆØ $§¡× 2Ñ 2´Sñ 9
Ø:>¿-¹-×:TÑ:Tô9
ó 6
ñ !
ˆ˜Òð
ô �uÓ"RÔSò ˆÙˆd�ðð €Mr"   c           
     ó€  — t         j                  dt        | «      «       t        j                   G d„ d«      «       }t        | |«      }t        | |«       t        | |||«       g }t        | ||«      \  }	}
|j                   || |	d«      «       t         j                  d|	«       |D ]�  }	 |t        k(  r || |||«      }n || «      }t        |«      t        | «      k(  sJ ‚t        |||«      \  }}
|j                   ||||j                  «      «       t         j                  d|j                  |«       Œ� t        d	d
d|D �ci c]  }|j                  |j                   “Œ c}i¬«       t#        |d„ ¬«      }|j$                  S # t        $ r,}t         j                  d|j                  |«       Y d}~�Œd}~ww xY wc c}w )zŸ
    Try a few heuristics based topological sort algorithms, and pick the one whose
    resulting topological order has the lowest peak memory estimation.
    z&Reordering for peak memory -- %d nodesc                  ó,   — e Zd ZU ded<   ded<   ded<   y)ú1reorder_for_peak_memory.<locals>.PeakMemoryResultúlist[BaseSchedulerNode]r»   r   Úpeak_memoryr,   ÚmethodNr‡   r!   r"   r#   ÚPeakMemoryResultrã   X  s   … à&Ó&ØÓØŒr"   rç   ÚbaselinezBaseline peak memory: %dz%s peak memory: %dzFailed to reorder for %s: %sNÚinductorr–   Úorm)Úcategoryr-   Ú
parametersc                ó   — | j                   S r0   )rå   )Úxs    r#   r«   z)reorder_for_peak_memory.<locals>.<lambda>‘  s
   € ¸a¿m¹m€ r"   r¬   )Ú	torch_logÚinfor�   r   rŒ   rQ   rq   r�   rœ   r�   r·   r   Ú	ExceptionÚerrorr   ræ   rå   r¯   r»   )rJ   rk   r{   rK   r‘   Úmethodsrç   rO   Úpeak_memory_diff_methodsÚestimated_peak_memoryr•   ræ   r»   rå   ÚeÚelemÚbest_results                    r#   Úreorder_for_peak_memoryrù   E  sß  € ô" ‡N�NÐ;¼SÀ»ZÔHä×Ñ÷ð ó ðô BXØˆ|óBÐô 6°e¸[ÔIÜ3ØÐ! ;Ð0Jôð
 8:Ðô  4ØÐ)¨=ó ÑÐ˜1ð ×#Ñ#Ù˜Ð 5°zÓBôô ‡N�NÐ-Ð/DÔEð ò Pˆð	PØÔ.Ò.ÙØÐ5°{ÀMó‘ñ ˜u›�Ü�u“:¤ U£Ò+Ð+Ð+Ü1ØÐ1°=ó‰NˆK˜ð %×+Ñ+Ù  ¨°V·_±_ÓEôô �N‰NÐ/°·±À+ÕNðPô& ØØàÐ>VÖW°d�D—K‘K ×!1Ñ!1Ñ1ÒWð
õô Ð.Ñ4KÔL€Kà×ÑÐøô ò 	PÜ�O‰OÐ:¸F¿O¹OÈQ×OÒOûð	Püò Xs   Â*B
FÅF;Æ	F8Æ!F3Æ3F8)rJ   rä   rK   úOrderedSet[str]r7   údict[str, FreeableInputBuffer])rk   údict[str, SchedulerBuffer]r7   zdict[str, tuple[int, int]])rJ   rä   rk   rü   r7   rÞ   )
rJ   rä   r{   údict[str, BaseSchedulerNode]rk   rü   rO   rû   r7   rÞ   )rJ   rä   rO   rû   r‘   rú   r7   ztuple[int, list[int]])
rJ   rä   rO   rû   rk   rü   r‘   rú   r7   rä   )rJ   rä   r7   rä   )rJ   rä   rk   rü   r{   rý   rK   rú   r‘   rú   ró   z,list[Callable[..., list[BaseSchedulerNode]]]r7   rä   )+Ú
__future__r   rB   r   rË   ÚloggingÚtypingr   r   r   r   Útorch._utils_internalr   Útorch.utils._ordered_setr	   rh   r   r   Úutilsr   Úvirtualizedr   Údependenciesr   ri   r   r   Ú	getLoggerr   rï   rŒ   r   r%   r+   rQ   rl   rq   r�   rœ   r·   rÎ   rà   rù   r!   r"   r#   ú<module>r     s  ðÝ "ã Û Û Û ß <Ó <å 0Ý /ç -Ý !Ý ñ Ý!ß=ð ˆG×Ñ˜hÓ'€	ð ×Ñ÷ð ó ðð ×Ñ÷ð ó ðð ×Ñ÷
ð 
ó ð
ð0&Ø"ð0&à!ð0&ð $ó0&ðf<Ø+ð<àó<ð~
Ø"ð
à+ð
ð 
ó
ð<#
Ø"ð#
à4ð#
ð ,ð#
ð !?ð	#
ð
 
ó#
ðL^+Ø"ð^+à >ð^+ð #ð^+ð ó	^+ðBzØ"ðzà >ðzð ,ðzð #ð	zð
 ózózEóP'ðb 	ØØð=ðNØ"ðNà+ðNð 5ðNð "ð	Nð
 #ðNð :ðNð ôNr"   