ó
    ‡Ž¡j0\  ã                   ó˜   • S SK r S SKJrJr  S SKJr  SSKJr  SSKJ	r	J
r
JrJr   " S S\5      r " S	 S
\5      r " S S\5      r\\S.rg)é    N)ÚABCÚabstractmethod)Údequeé   )ÚPagedAttentionCache)ÚFutureRequestStateÚRequestStateÚRequestStatusÚloggerc                   óº  • \ rS rSrSrS\S\S\4S jrS!S	 jr	S
\
4S jr\S\S\S\\\   S-  \\\4   4S j5       rS\4S jrS\SS4S jrS\S\\   4S jrS\4S jrS\\
   4S jrS\S\4S jrS
\
S\S\4S jrS
\
S\\   S\\   4S jrS
\
S\\   S\S\\   SS4
S jrS\\
   S\S\S\\   S\\\   \\\\4   4
S jrS\\
   4S jrS\\   SS4S jrS r g)"Ú	Scheduleré   a1  
Abstract base class for scheduling requests in the continuous batch processor. Schedulers manage the lifecycle of
requests from when they are added to the waiting queue to when they are scheduled for processing. Different
schedulers implement different strategies for prioritizing and batching requests.
ÚcacheÚsafety_marginÚmax_requests_per_batchc                 óÈ  • Xl         X l        X0l        [        R                  " 5       U l        US:  d  US:”  a  [        SU< S35      eUS:  a  [        SU< S35      eU R                   R                  (       a  SOU R                   R                  R                  U l
        U R                   R                  U R                   R                  -  U l        U R                  5         g)a}  Initializes the scheduler. The safety margin is the percentage of free blocks under which we stop
scheduling new prefill requests, so safety_margin = 0.1 means that when there is less than 10% of free blocks,
or equivalently when more than 90% of blocks are already allocated, we stop scheduling new prefill requests.
Setting safety_margin to 0.0 means no safety margin is applied.r   r   zGot safety_margin = z but expected a value in [0, 1]zGot max_requests_per_batch = z but expected a value >= 1N)r   r   r   Ú	threadingÚLockÚ_cancellation_lockÚ
ValueErrorÚnum_full_attention_groupsÚconfigÚsliding_windowÚread_cache_limitÚmax_blocks_per_requestÚ
block_sizeÚmax_decode_fast_path_lengthÚreset)Úselfr   r   r   s       ÚÃC:\Users\johnn\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\transformers/generation/continuous_batching/scheduler.pyÚ__init__ÚScheduler.__init__   s½   € ð
 Œ
Ø*ÔØ&<Ô#Ü"+§.¢.Ó"2ˆÔà˜1Ó °Ó 1ÜÐ4 MÑ#5Ð5TÐUÓVÐVØ! AÓ%ÜÐ=Ð$:Ñ#>Ð>XÐYÓZÐZà(,¯
©
×(L×(L¡ÐRV×R\ÑR\×RcÑRc×RrÑRrˆÔØ+/¯:©:×+LÑ+LÈtÏzÉz×OdÑOdÑ+dˆÔ(à�
‰
�ó    ÚreturnNc                 ó†   • 0 U l         0 U l        [        5       U l        [	        5       U l        / U l        SU l        / U l        g)z0Reset scheduler state for a new generation loop.FN)	Úactive_requestsÚwaiting_requestsr   Úwaiting_requests_orderÚsetÚ_requests_to_cancelÚ_requests_to_forkÚblock_new_requestsÚstarved_requests©r   s    r    r   ÚScheduler.reset1   sB   € à8:ˆÔØ9;ˆÔÜ27³'ˆÔ#Ü-0«UˆÔ Ø57ˆÔØ"'ˆÔð ACˆÕr#   Ústatec                 ó~   • XR                   UR                  '   U R                  R                  UR                  5        g)z#Adds a request to the waiting list.N)r'   Ú
request_idr(   Úappend)r   r0   s     r    Úadd_waiting_requestÚScheduler.add_waiting_request=   s0   € à27×Ñ˜e×.Ñ.Ñ/Ø×#Ñ#×*Ñ*¨5×+;Ñ+;Õ<r#   Útoken_budgetÚcache_budgetc                 ó   • g)a_  Schedules requests for the next batch based on available token and cache budgets. This method selects which
requests should be processed in the current batch, considering the budgets and the scheduler's prioritization
rules. The token_budget is the maximum number of tokens that can be processed in a batch, and the cache_budget
is the maximum number of KV cache entries that can be read in a batch.
Returns the list of scheduled requests in their "FutureRequestState" form, a boolean indicating if the decode
fast path can be used, the total number of query tokens and the maximum number of kv tokens read.N© )r   r6   r7   s      r    Úschedule_batchÚScheduler.schedule_batchB   s   � r#   c                 óv   • [        [        U R                  5      =(       d    [        U R                  5      5      $ )z3Checks if there are requests ready to be processed.)ÚboolÚlenr&   r'   r.   s    r    Úhas_pending_requestsÚScheduler.has_pending_requestsM   s(   € ä”C˜×,Ñ,Ó-×K´°T×5JÑ5JÓ1KÓLÐLr#   r2   c                 ór   • U R                   R                  U5        U R                  R                  US5        g)zžCompletes processing of a request and frees its allocated cache blocks. This method is called
when a request has finished generation or encountered an error.
N)r   Úfree_blocksr&   Úpop©r   r2   s     r    Úfinish_requestÚScheduler.finish_requestQ   s,   € ð 	�
‰
×Ñ˜zÔ*Ø×Ñ× Ñ  ¨TÕ2r#   c                 óV   • XR                   ;   a  U R                   U   R                  $ / $ )z,Gets generated tokens for an active request.)r&   Úgenerated_tokensrD   s     r    Ú!get_active_request_static_outputsÚ+Scheduler.get_active_request_static_outputsX   s*   € à×-Ñ-Ó-Ø×'Ñ'¨
Ñ3×DÑDÐDØˆ	r#   c                 ó†   • U R                      U R                  R                  U5        SSS5        g! , (       d  f       g= f)z!Marks a request for cancellation.N)r   r*   ÚaddrD   s     r    Úset_request_cancellationÚ"Scheduler.set_request_cancellation^   s+   € à×$Ó$Ø×$Ñ$×(Ñ(¨Ô4÷ %×$Ö$ús	   �2²
A c                 óÔ  • / nU R                      U R                   HŸ  nU R                  R                  US5      nU R                  R                  US5      nU=(       d    UnUb  UR                  U5        X R                  ;   a  U R                  R                  U5        U R                  R                  U5        M¡     [        5       U l        SSS5        U$ ! , (       d  f       U$ = f)z=Remove all cancelled requests from active and waiting queues.N)r   r*   r&   rC   r'   r3   r(   Úremover   rB   r)   )r   Úcancelled_statesr2   Ústate_aÚstate_wr0   s         r    Úclear_cancelled_requestsÚ"Scheduler.clear_cancelled_requestsc   sË   € àÐØ×$Ó$Ø"×6Ô6�
Ø×.Ñ.×2Ñ2°:¸tÓD�Ø×/Ñ/×3Ñ3°JÀÓE�à×* 7�ØÑ$Ø$×+Ñ+¨EÔ2Ø×!<Ñ!<Ó<Ø×/Ñ/×6Ñ6°zÔBØ—
‘
×&Ñ& zÖ2ñ 7ô (+£uˆDÔ$÷ %ð  Ð÷ %Ô$ð  Ðús   �B?CÃ
C'c                 ór   • XR                   ;   =(       d#    XR                  ;  =(       a    XR                  ;  $ )z2Checks if a request has been cancelled or removed.)r*   r&   r'   rD   s     r    Úrequest_is_cancelledÚScheduler.request_is_cancelledt   s2   € à×5Ñ5Ñ5÷ 
Ø×2Ñ2Ñ2×^°z×I^ÑI^Ñ7^ð	
r#   Úlen_next_tokensc                 ó$  • UR                  5       nUR                  U R                  R                  -  U-
  nXB:  d  UR                  S:X  aÅ  X$-
  S-   U R                  R                  -  S-   nU R                  R	                  XQR
                  UR                  5      nUc\  UR
                  U R                  ;   aA  U R                  R                  XQR                  5      nU R                  R                  X45        gU=R                  U-  sl        g)a‡  Allocate additional cache blocks for a request if the currently allocated blocks are insufficient to
accommodate the next tokens. It calculates how many blocks are needed based on the request's current
cache occupancy and the number of tokens to be processed. The allocation itself is done by the CacheAllocator
objects. Returns a boolean indicating if the allocation was successful or not.
r   r   FT)
Úcurrent_lenÚallocated_blocksr   r   Úallocate_blocksr2   r&   Úblocks_neededr-   r3   )r   r0   rY   r[   Ú	occupancyr^   Ú	allocatedÚphysical_blockss           r    Ú_allocate_blocks_if_neededÚ$Scheduler._allocate_blocks_if_neededz   sí   € ð ×'Ñ'Ó)ˆØ×*Ñ*¨T¯Z©Z×-BÑ-BÑBÀ[ÑPˆ	ØÓ&¨%×*@Ñ*@ÀAÓ*EØ-Ñ9¸AÑ=À$Ç*Á*×BWÑBWÑWÐ[\Ñ\ˆMØŸ
™
×2Ñ2°=×BRÑBRÐTY×TjÑTjÓkˆIØÑ ð ×#Ñ# t×';Ñ';Ó;Ø&*§j¡j×&>Ñ&>¸}×NdÑNdÓ&e�OØ×)Ñ)×0Ñ0°%Ð1IÔJØØ×"Ò" iÑ/Õ"Ør#   Ú"request_ids_to_remove_from_waitingc                 óö  • U R                   R                  (       Ga$  UR                  [        R                  :X  Ga  UR
                  (       dô  U R                   R                  UR                  UR                  5      nUS:”  a¾  XR                  UR                  '   UR                  UR                  5        [        R                  Ul        U=R                  X0R                   R                  -  -  sl        [        U[        UR                  5      S-
  5      nUR                  US Ul        U=R                   U-  sl        UR                  [        R"                  :X  a  UR$                  nU$ UR                  nU$ )z»Prepares a request for processing in the current batch. If prefix sharing is enabled, and the request was
pending, this is where we look for a prefix match and split the request if found.r   r   N)r   Úuse_prefix_sharingÚstatusr
   ÚPENDINGÚis_cpu_offloadedÚsearch_prefix_matchr2   Úremaining_prefill_tokensr&   rL   Ú
PREFILLINGr\   r   Úminr>   Úposition_offsetÚDECODINGÚtokens_to_process)r   r0   rd   Úprefill_lengthÚrequest_tokenss        r    Ú_infer_request_tokensÚScheduler._infer_request_tokens‘   s*  € ð �:‰:×(×(Ð(¨U¯\©\¼]×=RÑ=RÔ-RÐ[`×[q×[qØ!ŸZ™Z×;Ñ;¸E×<LÑ<LÈe×NlÑNlÓmˆNØ Ó!Ø9>×$Ñ$ U×%5Ñ%5Ñ6Ø2×6Ñ6°u×7GÑ7GÔHÜ,×7Ñ7�”à×&Ò&¨.¿J¹J×<QÑ<QÑ*QÑQÕ&ä!$ ^´S¸×9WÑ9WÓ5XÐ[\Ñ5\Ó!]�Ø16×1OÑ1OÐP^ÐP_Ð1`�Ô.Ø×%Ò%¨Ñ7Õ%ð �<‰<œ=×1Ñ1Ó1Ø"×4Ñ4ˆNð Ðð #×;Ñ;ˆNØÐr#   rr   c                 óæ  • UR                   S:”  a;  U[        U5      S-
  :¼  a)  [        U5      S-
  nU R                  R                  U5        [        U5      U::  až  UR                  [
        R                  :X  a3  XR                  UR                  '   UR                  UR                  5        UR                  [
        R                  ::  a.  UR                  Ul        / Ul        [
        R                  Ul        ggUR                  [
        R                  :X  aH  XR                  UR                  '   [
        R                  Ul        UR                  UR                  5        X#S Ul        USU Ul        g)a:  Schedules a request for the current batch, updating the request's status according to the token budget left.
After a request is scheduled, it is part of the next batch unless there is an error.
If the request has children (for parallel decoding), it ensures at least one token remains before the request is
forked.r   r   N)Únum_childrenr>   r+   r3   rg   r
   rh   r&   r2   rL   rl   rk   rp   ro   )r   r0   rr   r6   rd   s        r    Ú_schedule_requestÚScheduler._schedule_requestª   s0  € ð ×Ñ Ó! l´c¸.Ó6IÈAÑ6MÓ&MÜ˜~Ó.°Ñ2ˆLØ×"Ñ"×)Ñ)¨%Ô0ô ˆ~Ó ,Ó.Ø�|‰|œ}×4Ñ4Ó4Ø9>×$Ñ$ U×%5Ñ%5Ñ6Ø2×6Ñ6°u×7GÑ7GÔHØ�|‰|œ}×7Ñ7Ó7Ø*/×*HÑ*H�Ô'Ø13�Ô.ô  -×5Ñ5�•ð 8ð �|‰|œ}×4Ñ4Ó4Ø9>×$Ñ$ U×%5Ñ%5Ñ6Ü,×7Ñ7�”Ø2×6Ñ6°u×7GÑ7GÔHØ-;¸MÐ-JˆEÔ*Ø&4°]°lÐ&CˆEÕ#r#   Ú
candidatesc           	      ó@  • / nSn/ U l         U R                  R                  S:„  nU R                  U R                  R                  -  nX#p©U R
                  nU GHµ  nU R                  R                  5       nXØ:  nU(       aF  U(       a?  UR                  [        R                  :w  a!  [        R                  " SU< SU< 35          GOKU R                  XÄ5      n[        [        U5      U5      nUS:H  =(       a    UR                  U R                   :  nUR#                  5       nU R$                  b  [        UU R$                  5      nU(       a  U(       d	  UU:  a  GM  U R'                  UU5      nU(       dL  SnUS:X  aA  UR(                  U R*                  ;   a'  [        R,                  " SUR(                   S	35          GOTGMi  U R/                  XÏX$5        [        UR0                  5      nUUS:H  =(       a    UR                  U R                   :  -  nUU-  nUU-  nUS-  nU R                  R2                  (       aF  UR#                  5       U R                  R4                  -  nUU-   nUU R                  R4                  -  nOSnUR6                  (       + nUR9                  [;        UUUU5      5        UR(                  nU R*                  R=                  US5      SLnU(       a  UR?                  U5        US:X  d  US::  a  U(       a	  US::  d  GM¶    O   X’-
  nX£-
  nXVUUU4$ )
a  Schedules candidate requests for the current batch.

This method contains the common logic shared by all schedulers: it checks token and cache budgets, allocates
cache blocks if needed, updates request states, and tracks which waiting requests should be removed from the
waiting queue.
Fr   zJOutside safety margin, breaking out of scheduling loop. num_free_blocks = z safety_margins = r   NTzBreaking mid-loop for request z because the cache is full) r-   r   r   r   Ú
num_blocksr   Úget_num_free_blocksrg   r
   ro   r   Údebugrs   rm   r>   rn   r   r[   r   rb   r2   r'   Úinforw   rp   Úallow_block_sharingr   rk   r3   r   rC   rL   )r   ry   r6   r7   rd   Úscheduled_requestsÚone_allocation_failedÚdecode_fast_pathÚsafety_marginsÚoriginal_token_budgetÚoriginal_cache_budgetÚrequest_budgetr0   Únum_free_blocksÚoutside_safety_marginrr   Úrequest_lenÚis_decode_eligibleÚread_cache_neededÚallocation_successfulÚtokens_in_current_blockÚtokens_after_forwardÚcomplete_blocksÚhas_new_tokenÚreq_idÚwas_waitingÚnum_q_tokensÚmax_kv_reads                               r    Ú_process_candidatesÚScheduler._process_candidatesÐ   s  € ð  ÐØ %ÐØ "ˆÔØŸ:™:×<Ñ<¸qÑ@ÐØ×+Ñ+¨d¯j©j×.CÑ.CÑCˆØ7CÐ4Ø×4Ñ4ˆäˆEØ"Ÿj™j×<Ñ<Ó>ˆOà$3Ñ$DÐ!Þ$Ö);ÀÇÁÔP]×PfÑPfÓ@fÜ—’ØaÈÑNbÐbuÐdrÑcvÐwôò ð "×7Ñ7¸ÓbˆNäœc .Ó1°<Ó@ˆKð
 "-°Ñ!1×!n°e×6KÑ6KÈd×NnÑNnÑ6nÐØ %× 1Ñ 1Ó 3ÐØ×$Ñ$Ñ0Ü$'Ð(9¸4×;PÑ;PÓ$QÐ!æ$Ö);ÀÐPaÓAaÚð %)×$CÑ$CÀEÈ;Ó$WÐ!ö )Ø(,Ð%ð # aÓ'¨E×,<Ñ,<À×@UÑ@UÓ,UÜ—K’KÐ"@À×AQÑAQÐ@RÐRlÐ mÔnÚÚð ×"Ñ" 5¸,ÔkÜ˜e×5Ñ5Ó6ˆKð  ¨qÑ 0× m°U×5JÑ5JÈT×MmÑMmÑ5mÑmÐð ˜KÑ'ˆLØÐ-Ñ-ˆLØ˜aÑˆNð �z‰z×-×-Ø*/×*;Ñ*;Ó*=ÀÇ
Á
×@UÑ@UÑ*UÐ'Ø'>ÀÑ'LÐ$Ø"6¸$¿*¹*×:OÑ:OÑ"O‘à"#�ð !&× >Ñ >Ô>ˆMØ×%Ñ%Ô&8¸ÀÈÐ`kÓ&lÔmð ×%Ñ%ˆFØ×/Ñ/×3Ñ3°F¸DÓAÈÐMˆKÞØ2×6Ñ6°vÔ>ð ˜qÓ  \°QÓ%6Ö?OÐTbÐfgÖTgÙñO  ðR -Ñ;ˆØ+Ñ:ˆØ!Ð:JÈLÐZeÐeÐer#   c                 ó–  • [        5       n[        5       nU R                   H6  nU R                  U   nUR                  (       a  UOUR	                  U5        M8     / nU(       d  U(       a^  U(       a  UR	                  UR                  5       5        U(       a  UR	                  UR                  5       5        U(       a  MU  U(       a  M^  U$ )zëReturns waiting requests in priority order. Since CPU-offloaded requests are cheaper to restore than fresh
requests, they get priority, but we interleave them with fresh request to not saturate new batches with only
offloaded requests.)r   r(   r'   ri   r3   Úpopleft)r   Ú	offloadedÚfreshr‘   r0   Úordereds         r    Ú_get_waiting_candidatesÚ!Scheduler._get_waiting_candidates2  s•   € ô */«ˆ	Ü%*£WˆØ×1Ô1ˆFØ×)Ñ)¨&Ñ1ˆEØ×0×0‰Y°e×CÑCÀEÖJñ 2ð ')ˆÞž5ÞØ—‘˜y×0Ñ0Ó2Ô3ÞØ—‘˜uŸ}™}›Ô/÷	 ˆiŸ5˜5ð
 ˆr#   c                 ór   • [        U R                   Vs/ s H  o"U;  d  M
  UPM     sn5      U l        gs  snf )z8Removes processed requests from the waiting queue order.N)r   r(   )r   rd   r‘   s      r    Ú_cleanup_waiting_queueÚ Scheduler._cleanup_waiting_queueC  s2   € ä&+Ø"&×"=Ò"=ÓrÒ"=˜ÐOqÑAq�VÑ"=Ñró'
ˆÕ#ùÚrs   ”	4¡4)r   r*   r+   r&   r,   r   r   r   r   r   r-   r'   r(   )r$   N)!Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r   ÚfloatÚintr!   r   r	   r4   r   ÚtupleÚlistr   r=   r:   r?   ÚstrrE   rI   rM   rT   rW   rb   r)   rs   rw   r•   rœ   rŸ   Ú__static_attributes__r9   r#   r    r   r      sø  † ñðÐ1ð À%ð Ðadô ô(
Cð=¨ô =ð
 ðmØðmØ/2ðmà	ˆtÐ&Ñ'¨$Ñ.°°c¸3Ð>Ñ	?ómó ðmðM dô Mð3¨ð 3°ô 3ð¸Cð ÀDÈÁIô ð5°3ô 5ð
 ¨$¨|Ñ*<ô  ð"
¨sð 
°tô 
ð°ð Èsð ÐW[ô ð.¨<ð Ð]`ÐadÑ]eð ÐjnÐorÑjsô ð2$Dàð$Dð ˜S™	ð$Dð ð	$Dð
 -0°©Hð$Dð 
ô$DðL`fà˜Ñ&ð`fð ð`fð ð	`fð
 -0°©Hð`fð 
ˆtÐ&Ñ'¨¨t°S¸#Ð=Ñ	>ô`fðD¨¨lÑ);ô ð"
ÈÈSÉð 
ÐVZ÷ 
r#   r   c            
       ór   ^ • \ rS rSrSrS\S\S-  S\4U 4S jjrS\S	\S
\	\
\   S-  \\\4   4S jrSrU =r$ )ÚFIFOScheduleriK  z|This scheduler processes requests in the order they arrive, meaning decoding requests has priority over
prefilling requests.r   r   Nr   c                 ó0   >• Uc  Sn[         TU ]  XU5        g)z^Initializes the FIFO scheduler, with a default safety margin of 0.15 (ie. 15% of free blocks).Ng333333Ã?©Úsuperr!   ©r   r   r   r   Ú	__class__s       €r    r!   ÚFIFOScheduler.__init__O  s   ø€ àÑ Ø ˆMÜ‰Ñ˜Ð/EÕFr#   r6   r7   r$   c                 ó  • / n/ nU R                   R                  5        He  nUR                  [        R                  :X  a  UR                  U5        M4  UR                  [        R                  :X  d  MT  UR                  U5        Mg     U R                  (       d  UR                  U R                  5       5        X4-   n[        5       nU R                  UUUU5      u  p‰p«nU R                  U5        U(       d  U	(       a  S U
SS4$ XŠX¼4$ ©Nr   )r&   Úvaluesrg   r
   ro   r3   rl   r,   Úextendrœ   r)   r•   rŸ   ©r   r6   r7   Úpriority_statesÚsecond_priority_statesr0   ry   rd   r€   r�   r‚   r“   r”   s                r    r:   ÚFIFOScheduler.schedule_batchU  s÷   € ð /1ˆØ57Ðà×)Ñ)×0Ñ0Ö2ˆEØ�|‰|œ}×5Ñ5Ó5Ø×&Ñ& uÖ-Ø—‘¤×!9Ñ!9Õ9Ø&×-Ñ-¨eÖ4ñ	 3ð ×&×&Ø"×)Ñ)¨$×*FÑ*FÓ*HÔIà$Ñ=ˆ
Ü-0«UÐ*à×$Ñ$ØØØØ2ó	ñ 	_ÐÐ3CÐS^ð 	×#Ñ#Ð$FÔGö "Ö&;ØÐ)¨1¨aÐ/Ð/à!°\ÐNÐNr#   r9   ©r¡   r¢   r£   r¤   r¥   r   r¦   r§   r!   r¨   r©   r   r=   r:   r«   Ú__classcell__©r²   s   @r    r­   r­   K  sl   ø† ñðGÐ1ð GÀ%È$Á,ð GÐhk÷ Gð"OØð"OØ/2ð"Oà	ˆtÐ&Ñ'¨$Ñ.°°c¸3Ð>Ñ	?÷"Oò "Or#   r­   c            
       ór   ^ • \ rS rSrSrS\S\S-  S\4U 4S jjrS\S	\S
\	\
\   S-  \\\4   4S jrSrU =r$ )ÚPrefillFirstScheduleri|  zìScheduler that prioritizes split prefill requests over decoding requests. This scheduler ensures that split
prefill requests (which are continuations of partially processed prompts) are completed before processing new
decoding requests.r   r   Nr   c                 ó0   >• Uc  Sn[         TU ]  XU5        g)z`Initializes the prefill first scheduler, with a default safety margin of 0.0 (no safety margin).Ng        r¯   r±   s       €r    r!   ÚPrefillFirstScheduler.__init__�  s   ø€ àÑ ØˆMÜ‰Ñ˜Ð/EÕFr#   r6   r7   r$   c                 ó  • / n/ nU R                   R                  5        He  nUR                  [        R                  :X  a  UR                  U5        M4  UR                  [        R                  :X  d  MT  UR                  U5        Mg     U R                  (       d  UR                  U R                  5       5        X4-   n[        5       nU R                  UUUU5      u  p‰p«nU R                  U5        U(       d  U	(       a  S U
SS4$ XŠX¼4$ rµ   )r&   r¶   rg   r
   rl   r3   ro   r,   r·   rœ   r)   r•   rŸ   r¸   s                r    r:   Ú$PrefillFirstScheduler.schedule_batch‡  s÷   € ð /1ˆØ57Ðà×)Ñ)×0Ñ0Ö2ˆEà�|‰|œ}×7Ñ7Ó7Ø×&Ñ& uÖ-Ø—‘¤×!7Ñ!7Õ7Ø&×-Ñ-¨eÖ4ñ 3ð ×&×&Ø"×)Ñ)¨$×*FÑ*FÓ*HÔIà$Ñ=ˆ
Ü-0«UÐ*à×$Ñ$ØØØØ2ó	ñ 	_ÐÐ3CÐS^ð 	×#Ñ#Ð$FÔGö "Ö&;ØÐ)¨1¨aÐ/Ð/à!°\ÐNÐNr#   r9   r¼   r¾   s   @r    rÀ   rÀ   |  sl   ø† ñðGÐ1ð GÀ%È$Á,ð GÐhk÷ Gð#OØð#OØ/2ð#Oà	ˆtÐ&Ñ'¨$Ñ.°°c¸3Ð>Ñ	?÷#Oò #Or#   rÀ   )ÚfifoÚprefill_first)r   Úabcr   r   Úcollectionsr   r   r   Úrequestsr   r	   r
   r   r   r­   rÀ   ÚSCHEDULER_MAPPINGr9   r#   r    Ú<module>rË      sV   ðó ß #Ý å &ß MÓ Môq
�ô q
ôj	,O�Iô ,Oôb.O˜Iô .Oðd Ø*ñÑ r#   