+
    œ°³jº·  ã                   óî   € ^ RI t ^ RIHtHtHt ^ RIHt ^ RIt^RIH	t	 ^RI
Ht ^RIHt ^RIHtHtHtHt ^RIHt ^R	IHt ^R
IHtHtHtHt R R ltR R ltR R lt ! R R4      t ! R R4      t R# )é    N)ÚfloorÚgcdÚsqrt)ÚAny)ÚPreTrainedConfig)ÚContinuousBatchingConfig)Úis_flash_attention_requested)ÚBlockManagerÚCacheAllocatorÚFullAttentionCacheAllocatorÚSlidingAttentionCacheAllocator)ÚDistributedHelper)Úresolve_max_memory_percent)ÚRequestStateÚRequestStatusÚget_device_and_memory_breakdownÚloggerc                ó0   € V ^8„  d   QhR\         R\        /# ©é   ÚconfigÚreturn©r   Úint)Úformats   "Úr/home/luca/screen-checking/.venv/lib/python3.14/site-packages/transformers/generation/continuous_batching/cache.pyÚ__annotate__r      s   € ÷ 
pñ 
pÔ.ð 
p´3ñ 
pó    c                ój   € \        V RR4      pVe   V# \        V RR4      pVe   V# \        RV  24      h)z9Finds the number of key-value heads for the given config.Únum_key_value_headsNÚnum_attention_headszMnum_key_value_heads or num_attention_heads could not be found in the config:
©ÚgetattrÚ
ValueError)r   Úkv_headss   & r   Úfind_num_kv_headsr&      sM   € ô �vÐ4°dÓ;€HØÒØˆä�vÐ4°dÓ;€HØÒØˆÜ
ÐeÐflÐemÐnÓ
oÐor   c                ó0   € V ^8„  d   QhR\         R\        /# r   r   )r   s   "r   r   r   *   s   € ÷ wñ wÔ*ð w¬sñ wr   c                ó˜   € \        V RR4      pVe   V# \        V RR4      p\        V RR4      pVe   Ve	   W#,          # \        RV  24      h)z.Finds the head dimension for the given config.Úhead_dimNÚhidden_sizer!   zThead_dim or (hidden_size and num_attention_heads) could not be found in the config:
r"   )r   r)   r*   r!   s   &   r   Úfind_head_dimr+   *   se   € ô �v˜z¨4Ó0€HØÒØˆä˜& -°Ó6€KÜ! &Ð*?ÀÓFÐØÒÐ#6Ò#BØÕ1Ð1Ü
ÐlÐmsÐltÐuÓ
vÐvr   c                ó”   € V ^8„  d   QhR\         R\        \        \        \        ,          ,          \        \        ,          3,          /# r   )r   ÚtupleÚlistr   Ústr)r   s   "r   r   r   8   s4   € ÷ %ñ %Ô&6ð %¼5ÄÄdÌ3ÅiÅÔRVÔWZÕR[ÐA[Õ;\ñ %r   c                óV  € \        V RR4      pVf7   \        V RR4      e   RMRp\        V P                  4       Uu. uF  q2NK  	  pp/ p\        V4       F!  w  rVVP	                  V. 4      V.,           WF&   K#  	  \        VP                  4        Uu. uF  p\        V4      NK  	  up!  p. p	VP                  4        F;  w  rg\        ^ \        V4      V4       F  pV	P                  WuWX,            4       K  	  K=  	  V	 U
u. uF  q¡V
^ ,          ,          NK  	  pp
W›3# u upi u upi u up
i )a|  
Group layers depending on the attention mix, according to VLLM's hybrid allocator rules:
    - Layers in each group need to have the same type of attention
    - All groups have the same number of layers

For a model with the following layer types: ["sliding", "full", "full", "sliding", "full", "full", "full", "full"]
We would get four groups: [0, 3], [1, 2], [4,5] and [6,7].
Úlayer_typesNÚsliding_windowÚsliding_attentionÚfull_attention)
r#   ÚrangeÚnum_hidden_layersÚ	enumerateÚgetr   ÚvaluesÚlenÚitemsÚappend)r   r1   Ú	attn_typeÚ_Úlayer_countsÚiÚ
layer_typeÚindicesÚ
group_sizeÚlayer_groupsÚlgÚgroup_typess   &           r   Úgroup_layers_by_attn_typerG   8   s2  € ô ˜& -°Ó6€KØÒÜ+2°6Ð;KÈTÓ+RÒ+^Ñ'Ðdtˆ	Ü*/°×0HÑ0HÔ*IÓJÑ*I Q’yÑ*IˆÐJð €LÜ" ;Ö/‰ˆØ#/×#3Ñ#3°JÀÓ#CÀqÀcÕ#IˆÓ ñ 0ô °<×3FÑ3FÔ3HÓIÑ3H¨”s˜7–|Ñ3HÑIÑJ€Jð €LØ+×1Ñ1Ö3Ñˆ
Ü�qœ#˜g›,¨
Ö3ˆAØ×Ñ ¨A­NÐ ;Ö<ó 4ñ  4ñ 1=Ó=±¨"˜r !�u×%Ð%±€KÐ=ØÐ$Ð$ùò# Kùò Jùò >s   ¼
DÂD!Ã?D&c                   ó†  a € ] tR t^Yt o Rt^t]P                  3V 3R lR lltV 3R lR lt	V 3R lR lt
V 3R lR	 ltV 3R
 lR ltV 3R lR ltV 3R lR ltV 3R lR ltV 3R lR ltV 3R lR ltV 3R lR ltV 3R lR ltV 3R lR ltV 3R lR ltV 3R lR ltV 3R  lR! ltV 3R" lR# ltV 3R$ lR% ltR&tV tR'# )(ÚPagedAttentionCacheuú  
Manages the cache for a paged attention mechanism, inspired by VLLM's hybrid allocator. The cache relies on making
groups of layers to reduce the complexity of cache management and fragmentation.

The cache uses a three-level hierarchy:
- Pages: The smallest unit of cache, a page has a size of [num_heads, head_size], which is the space needed to
    store the key or value states for one token and one layer. For a model with only full-attention layers, to store
    the KV cache of one token, we need `2 * num_layers` pages: key and values each take `num_layers` pages.
    Pages are grouped into blocks:
- Blocks: A block is a collection of `block_size` pages, serving as the allocation unit to reduce management
    complexity and fragmentation. Cache is allocated and freed block by block, not page by page. One block is
    allocated to one layer group, which only has one attention type, like full-attention or sliding-attention.
    If all layers in the model have the same attention type, then all layers will be in the same group. There is
    more than one group if and only if the model has a mixed attention types, like layers with full-attention and
    layers with sliding-attention.
- Cache tensors: The physical supports for the cache. There are as many cache tensors as there are layer in a
    layer group, and the shape of the cache tensor is `[num_blocks * block_size, num_heads, head_size]`.

Grouping layers into groups is useful because when we allocate one block to a group N, the block allocated is the
    same for all layers in group N, equivalently it is allocated across all cache tensors. This allows us to
    efficiently allocate and free blocks, and to efficiently read and write key and value states.

For instance, imagine we have 8 blocks of cache and a model with two layer groups: a full-attention group with 3
layers and a sliding-attention group with 3 layers. At creation time, the physical cache tensors look like this:

cache_tensor_0: â–¡ â–¡ â–¡ â–¡ â–¡ â–¡ â–¡ â–¡
cache_tensor_1: â–¡ â–¡ â–¡ â–¡ â–¡ â–¡ â–¡ â–¡
cache_tensor_2: â–¡ â–¡ â–¡ â–¡ â–¡ â–¡ â–¡ â–¡

where â–¡ means the blocks is not allocated to any layer group yet. We have 3 cache tensors because there are
3 layers per group.
We allocate 1 block to each group, after allocation, the cache tensors look like this:

cache_tensor_0: âœ– â—‰ â–¡ â–¡ â–¡ â–¡ â–¡ â–¡
cache_tensor_1: âœ– â—‰ â–¡ â–¡ â–¡ â–¡ â–¡ â–¡
cache_tensor_2: âœ– â—‰ â–¡ â–¡ â–¡ â–¡ â–¡ â–¡

where âœ– means the block is allocated to the full-attention group, and â—‰ means the block is allocated to the
sliding-attention group.
Now, if we continue to generate, and the sliding window has been reached, we only need to allocate a new block
for the full-attention group, and the cache tensors look like this:

cache_tensor_0: âœ– â—‰ âœ– â–¡ â–¡ â–¡ â–¡ â–¡
cache_tensor_1: âœ– â—‰ âœ– â–¡ â–¡ â–¡ â–¡ â–¡
cache_tensor_2: âœ– â—‰ âœ– â–¡ â–¡ â–¡ â–¡ â–¡

And after further generation, when we need a new block allocated:

cache_tensor_0: âœ– â—‰ âœ– âœ– â–¡ â–¡ â–¡ â–¡
cache_tensor_1: âœ– â—‰ âœ– âœ– â–¡ â–¡ â–¡ â–¡
cache_tensor_2: âœ– â—‰ âœ– âœ– â–¡ â–¡ â–¡ â–¡

This would not have been possible if all layers were in the same group: we would have had to allocate a new block
for the sliding-attention group, although it is not needed.
c                ó�   <€ V ^8„  d   QhRS[ RS[RS[P                  S[,          RS[RS[S[S[3,          RS[P                  RR/# )	r   r   Úcontinuous_batching_configÚdeviceÚdistributed_helperÚtp_planÚdtyper   N)	r   r   ÚtorchrL   r/   r   Údictr   rO   )r   Ú__classdict__s   "€r   r   Ú PagedAttentionCache.__annotate__”   so   ø€ ÷ Z%ñ Z%á ðZ%ñ %=ðZ%ñ —‘™sÕ"ð	Z%ñ
 .ðZ%ñ ‘c™3�h•ðZ%ñ �{‰{ðZ%ð 
ñZ%r   c           	     óD  € Wn         W`n        W0n        \        V4      V n        \        V4      V n        VP                  V n        V P                  V P                  8  d&   \        RV P                   RV P                   24      h\        V4      w  rx\        V^ ,          4      p	\        V4      V n        / V n        / V n        \        V4       FR  w  r«WŠ,          R8X  d   VP                   M^p\        V4       F#  w  rÞW­3V P                  V&   WÀP                  V&   K%  	  KT  	  RpR F  pVV9   d   K  RV,           V9   d   K  Rp M	  VP"                  pV^8”  dV   V'       dN   V P                  V,          ^ 8w  d   \        RV P                   RV R	24      hV ;P                  V,          un        VP$                  f   \'        VRR7       \)        VVV P                  VV	R7      P+                  4       w  ppV^8”  d…   \,        P.                  ! VV.V P                  \,        P0                  R7      pVP3                  V4       \5        V^ ,          P7                  4       4      \5        V^,          P7                  4       4      ppVV n        VV n        V P:                  V P                  ,          V n        \>        P@                  ! RV P8                  : RV P:                  : RV P                  : 24       . V n!        . V n"        V^,           V P                  V P                  V P                  3pV^,           V P                  ,          V P                  V P                  3V n#        VV P                  ,          V n$        VV P                  ,          ^,           V n%        V^,           V P                  ,          V n&        \O        V	4       EF4  p\,        PP                  ! V PF                  V P                  V P                  R7      p\,        PP                  ! V PF                  V P                  V P                  R7      p\,        PR                  PU                  V4       \,        PR                  PU                  V4       V PB                  PW                  V4       V PD                  PW                  V4       VPY                  V4      V,          P[                  ^ 4       VPY                  V4      V,          P[                  ^ 4       EK7  	  \>        P@                  ! RV PF                  : RV PB                  ^ ,          P\                  : RV PB                  ^ ,          P_                  4       : 24       VP`                  V n0        . V n1        ^ V n2        ^ V n3        ^ V n4        \        V4       FÙ  w  p
pVR8X  d<   \k        W P                  V P`                  R7      pV ;Pd                  ^,          un2        MvVR8X  db   \m        W P                  VP                   V PJ                  V PL                  4      pV ;Pf                  ^,          un3        VPn                  V n4        M\        RV 24      hV Pb                  PW                  V4       KÛ  	  VPp                  pV Pf                  ^ 8”  d+   Ve   V^ 8”  d   \>        Pr                  ! R4       ^ Vn8        ^ pVf   VPt                  pVV n8        V P`                  ;'       d    VR.8H  V n;        \y        VV P                  V^8„  R7      V n=        ^ V n>        R
V n?        R
# )a  Initialize a paged attention cache for efficient memory usage. Also turns in prefix sharing if the model has
only full attention layers.

Args:
    config: Model configuration
    continuous_batching_config: Continuous batching configuration containing cache parameters
    device: Device for the cache tensors
    distributed_helper: TP-aware helper. Used to dispatch attention heads and ensure coherent cache size
    tp_plan: Tensor parallelism plan
    dtype: Data type of the activation and the cache (for now, these are the same)
zBlock size must be at least z
, but got r3   Tzmodel.FzNumber of key value heads z+ must be divisible by tensor parallel size Ú.N)Ú	cb_configÚhas_logit_processors)r   rK   rO   rF   rC   ©rL   rO   z1Paged cache initialized: self.max_batch_tokens = z, self.num_blocks = z, self.block_size = )rO   rL   zself.cache_shape = z self.key_cache[0].shape = z self.key_cache[0].numel() = r4   )Úallow_block_sharingzInvalid group type: zHSliding window attention groups detected: disabling block table support.)Útp_on)zlayers.*.self_attn.k_projzlayers.*.self_attn.v_proj)@r   rO   rL   r&   r    r+   r)   Ú
block_sizeÚ_min_block_sizer$   rG   r:   Ú
num_groupsÚsliding_windowsÚlayer_index_to_group_indicesr7   r2   Útp_sizeÚmax_memory_percentr   ÚPagedAttentionMemoryHandlerÚ%infer_max_batch_tokens_and_num_blocksrP   ÚtensorÚint64Útp_all_reduce_minr   ÚitemÚmax_batch_tokensÚ
num_blocksÚ	num_pagesr   ÚinfoÚ	key_cacheÚvalue_cacheÚcache_shapeÚread_trash_indexÚsentinel_indexÚwrite_trash_indexr5   ÚemptyÚ_dynamoÚmark_static_addressr<   ÚviewÚfill_ÚshapeÚnumelrY   Úgroup_cache_managersÚnum_full_attention_groupsÚnum_sliding_attention_groupsÚ%max_sliding_window_blocks_per_requestr   r   Ú_max_blocks_per_requestÚmax_blocks_per_requestÚwarningÚfallback_max_blocks_per_requestÚuse_prefix_sharingr
   Ú_block_managerÚ_total_prefix_lengthÚ_block_table_key)Úselfr   rK   rL   rM   rN   rO   rD   rF   rC   r@   Úgroupr2   ÚjÚlayerÚkv_is_tpÚkeyr`   rh   ri   ÚsyncÚblock_based_shaper>   Únew_layer_key_cacheÚnew_layer_value_cacheÚ
group_typeÚcmr~   s   &&&&&&&                     r   Ú__init__ÚPagedAttentionCache.__init__”   s  € ð( ŒØŒ
ØŒô ):¸&Ó(AˆÔ Ü*¨6Ó2ˆŒð 5×?Ñ?ˆŒØ�?‰?˜T×1Ñ1Ô1ÜÐ;¸D×<PÑ<PÐ;QÐQ[Ð\`×\kÑ\kÐ[lÐmÓnÐnô %>¸fÓ$EÑ!ˆÜ˜ a�Ó)ˆ
Ü˜lÓ+ˆŒà!ˆÔØ,.ˆÔ)Ü! ,Ö/‰HˆAØ6AµnÐH[Ô6[˜V×2Ò2ÐabˆNÜ% eÖ,‘�Ø<=¸6�×1Ñ1°%Ñ8Ø.<×$Ñ$ UÓ+ó -ñ 0ð ˆÛMˆCØ˜7–N h°¥n¸Ö&?Ø �Ùñ Nð %×,Ñ,ˆØ�QŒ;Ÿ8Ø×'Ñ'¨'Õ1°QÔ6Ü Ø0°×1IÑ1IÐ0JÐJuÐv}Ðu~Ð~ð  Aóð ð ×$Ò$¨Õ0Õ$ð &×8Ñ8Ò@Ü&Ð1KÐbfÕgä'BØØ'AØ—*‘*Ø#Ø!ô(
÷ 0Ñ
/Ó
1ñ 	%Ð˜*ð �QŒ;Ü—<’<Ð!1°:Ð >ÀtÇ{Á{ÔZ_×ZeÑZeÔfˆDØ×0Ñ0°Ô6Ü+.¨t°A­w¯|©|«~Ó+>ÄÀDÈÅGÇLÁLÃNÓ@S˜jÐð !1ˆÔØ$ˆŒØŸ™¨4¯?©?Õ:ˆŒÜ�ŠÐH°×0EÑ0EÑ/IÐI^ÈDÏOÉOÑK_Ð_tÐbf×bqÑbqÑauÐvÔwð .0ˆŒØ/1ˆÔð (¨!�^¨T¯_©_¸d×>VÑ>VÐX\×XeÑXeÐfÐà'¨!�^¨t¯©Õ>À×@XÑ@XÐZ^×ZgÑZgÐhˆÔØ *¨T¯_©_Õ <ˆÔØ(¨4¯?©?Õ:¸QÕ>ˆÔØ",¨q¥.°D·O±OÕ!CˆÔÜ�z×"ˆAÜ"'§+¢+¨d×.>Ñ.>ÀdÇjÁjÐY]×YdÑYdÔ"eÐÜ$)§K¢K°×0@Ñ0@ÈÏ
É
Ð[_×[fÑ[fÔ$gÐ!Ü�M‰M×-Ñ-Ð.AÔBÜ�M‰M×-Ñ-Ð.CÔDØ�N‰N×!Ñ!Ð"5Ô6Ø×Ñ×#Ñ#Ð$9Ô:à×$Ñ$Ð%6Ó7¸
ÕC×IÑIÈ!ÔLØ!×&Ñ&Ð'8Ó9¸*ÕE×KÑKÈA×Nñ #ô 	�ŠÐ*�t×'Ñ'Ñ+Ð+G¨T¯^©^¸AÕ->×-DÑ-DÑ,HÐHfÈ$Ï.É.ÐYZÕJ[×JaÑJaÓJcÑIgÐhÔið $>×#QÑ#QˆÔ Ø:<ˆÔ!Ø)*ˆÔ&Ø,-ˆÔ)Ø56ˆÔ2ä& {Ö3‰MˆAˆzØÐ-Ô-Ü0°·O±OÐY]×YqÑYqÔr�Ø×.Ò.°!Õ3Ö.ØÐ2Ô2Ü3Ø—‘¨×(=Ñ(=¸t×?RÑ?RÐTX×TjÑTjó�ð ×1Ò1°QÕ6Õ1Ø=?×=WÑ=W�Õ:ä Ð#7¸
°|Ð!DÓEÐEØ×%Ñ%×,Ñ,¨RÖ0ñ 4ð "<×!RÑ!RÐà×,Ñ,¨qÔ0à%Ò1Ð6LÈqÔ6PÜ—’ÐiÔjØ@AÐ&Ô=Ø%&Ð"à!Ò)Ø%?×%_Ñ%_Ð"Ø&<ˆÔ#ð #'×":Ñ":×"`Ð"`¸{ÐO_ÐN`Ñ?`ˆÔÜ*¨:°t·±ÈgÐXYÉkÔZˆÔØ)*ˆÔ!ð !%ˆÖr   c                ó,   <€ V ^8„  d   QhRS[ RS[ RS[ /# ©r   Únum_requested_blocksÚallocated_blocksr   ©r   )r   rR   s   "€r   r   rS   0  s#   ø€ ÷ ñ ±#ð Éð ÑQTñ r   c                óÎ   € WP                   ,          pV P                  '       dA   \        V P                  V,
          ^ 4      pV\	        WA4      V P                  ,          ,          pV# )a:  Returns the number of physical blocks needed to allocate (num_requested_blocks) blocks to a request that
already has (allocated_blocks) blocks. The number of newly allocated blocks needed is predicted by the
following rules:
- for full attention groups: since there is no sliding window for full attention layers, one requested block is
    always equivalent to one newly allocated block for EACH full attention group
- for sliding window groups: because of the sliding window, the number of blocks allocated to a request is
    capped. Using the number of already (allocated_blocks) we can compute the number of new blocks to actually
    allocate to the request, which can be lower than the number of requested blocks. That number is the same for
    all sliding window groups, as only one sliding window size is supported.
)rz   r{   Úmaxr|   Úmin)r…   r•   r–   Úneeded_blocksÚblocks_lefts   &&&  r   Úblocks_neededÚ!PagedAttentionCache.blocks_needed0  sW   € ð -×/MÑ/MÕMˆà×,×,Ð,Ü˜d×HÑHÐK[Õ[Ð]^Ó_ˆKØœS ÓCÀd×FgÑFgÕgÕgˆMØÐr   c                ó,   <€ V ^8„  d   QhRS[ RS[ RS[/# r”   )r   Úbool)r   rR   s   "€r   r   rS   C  s)   ø€ ÷ hñ hÁ#ð hÑY\ð hÑaeñ hr   c                óF   € V P                  W4      V P                  4       8*  # )zcReturns a boolean indicating if the allocation of (num_requested_blocks) blocks will be successful.)r�   Úget_num_free_blocks)r…   r•   r–   s   &&&r   Úwill_allocation_be_successfulÚ1PagedAttentionCache.will_allocation_be_successfulC  s"   € à×!Ñ!Ð"6ÓIÈT×MeÑMeÓMgÑgÐgr   c                ó&   <€ V ^8„  d   QhRS[ RS[/# )r   Ú
request_idr   ©r/   r   )r   rR   s   "€r   r   rS   G  s   ø€ ÷ `ñ `©ð `±ñ `r   c                óB   a€ \        V3R lV P                   4       4      # )zfReturns the total number of physical blocks currently referenced by a request across all layer groups.c              3   ón   <"  € T F*  p\        VP                  P                  SR4      4      x € K,  	  R # 5i)N© )r:   Úblock_tabler8   )Ú.0r�   r¦   s   & €r   Ú	<genexpr>Ú4PagedAttentionCache.blocks_in_use.<locals>.<genexpr>I  s,   øé € Ð_ÑE^¸r”3�r—~‘~×)Ñ)¨*°bÓ9×:Ð:ÓE^ùs   ƒ25)Úsumry   )r…   r¦   s   &fr   Úblocks_in_useÚ!PagedAttentionCache.blocks_in_useG  s   ø€ äÔ_ÀT×E^ÒE^Ó_Ó_Ð_r   c          	      ó@   <€ V ^8„  d   QhRS[ RS[RS[ RS[ R,          /# )r   Ún_blocksr¦   r–   r   N)r   r/   )r   rR   s   "€r   r   rS   K  s1   ø€ ÷ ñ ©ð ¹ð ÑPSð ÑX[Ð^bÕXbñ r   c                óÚ   € V P                  W4      '       g   R# ^ pV P                   F?  pVP                  WV P                  4      pVf   \	        RV RV 24      h\        WF4      pKA  	  V# )zÕAllocate cache blocks across all layer groups for a given request. Actual allocation is done by the cache
managers, and this method only returns the maximum number of blocks actually allocated across all managers.NzFailed to allocate z blocks for request )r£   ry   Úallocate_blocksr‚   r$   r™   )r…   r³   r¦   r–   Úmax_allocatedr�   Únum_allocated_blockss   &&&&   r   rµ   Ú#PagedAttentionCache.allocate_blocksK  sz   € ð ×1Ñ1°(×MÒMÙàˆØ×+Ô+ˆBØ#%×#5Ñ#5°hÈD×L_ÑL_Ó#`Ð Ø#Ò+Ü Ð#6°x°jÐ@TÐU_ÐT`Ð!aÓbÐbÜ ÓDŠMñ	 ,ð
 Ðr   c                ó$   <€ V ^8„  d   QhRS[ RR/# )r   r¦   r   N)r/   )r   rR   s   "€r   r   rS   Z  s   ø€ ÷ <ñ <¡cð <¨dñ <r   c                ób   € V P                    F  pVP                  WP                  4       K   	  R# )zFree all allocated cache blocks for a given request across all layer groups. Actual deallocation is done
by the cache managers.N)ry   Úfree_blocksr‚   )r…   r¦   r�   s   && r   r»   ÚPagedAttentionCache.free_blocksZ  s&   € ð ×+Ô+ˆBØ�N‰N˜:×':Ñ':Ö;ó ,r   c                ó    <€ V ^8„  d   QhRS[ /# ©r   r   r—   )r   rR   s   "€r   r   rS   `  s   ø€ ÷ 3ñ 3¡Sñ 3r   c                ó.   € V P                   P                  # )zHGet the current number of unallocated blocks available for new requests.)r‚   Únum_free_blocks)r…   s   &r   r¢   Ú'PagedAttentionCache.get_num_free_blocks`  s   € à×"Ñ"×2Ñ2Ð2r   c                óŠ   <€ V ^8„  d   QhRS[ RS[RS[RS[S[S[,          ,          R,          RS[S[S[,          ,          RR/# )r   r¦   Úpast_lengthÚquery_lengthÚ
read_indexNÚwrite_indexr   )r/   r   r.   )r   rR   s   "€r   r   rS   d  sd   ø€ ÷ `ñ `áð`ñ ð`ñ ð	`ñ
 ™™c�•O dÕ*ð`ñ ™$™s�)•_ð`ð 
ñ`r   c                ó  € \        V P                  V4       F&  w  rgVP                  VP                  WV4      4       K(  	  VeC   \        V P                  V4       F&  w  rhVP                  VP	                  WV4      4       K(  	  R# R# )a5  Retrieve physical cache indices for reading KV states in the cache across all layer groups. This method
coordinates with all cache managers to build the complete set of read indices needed for attention computation.
When read_index is None, the batch has no cache reads and we only compute the write indices.
N)Úzipry   ÚextendÚget_write_indicesÚget_read_indices)	r…   r¦   rÃ   rÄ   rÅ   rÆ   r�   Úwrite_indicesÚread_indicess	   &&&&&&   r   Úextend_read_and_write_indicesÚ1PagedAttentionCache.extend_read_and_write_indicesd  s~   € ô "% T×%>Ñ%>ÀÖ!LÑˆBØ× Ñ  ×!5Ñ!5°jÈ|Ó!\Ö]ñ "Mð Ò!Ü$'¨×(AÑ(AÀ:Ö$NÑ �Ø×#Ñ# B×$7Ñ$7¸
ÐQ]Ó$^Ö_ó %Oñ "r   c          
      óJ   <€ V ^8„  d   QhRS[ RS[RS[RS[P                  RR/# )r   r¦   rÃ   rÄ   r«   r   N)r/   r   rP   ÚTensor)r   rR   s   "€r   r   rS   x  sB   ø€ ÷ Wñ WÙðWÙ,/ðWÙ?BðWÙQV×Q]ÑQ]ðWà	ñWr   c                ót   € \        V P                  4       F  w  rVVP                  WW4V,          4       K   	  R # )N)r7   ry   Úfill_block_table)r…   r¦   rÃ   rÄ   r«   r@   r�   s   &&&&&  r   rÓ   Ú$PagedAttentionCache.fill_block_tablex  s0   € ô ˜t×8Ñ8Ö9‰EˆAØ×Ñ 
¸ÐSTÅ~ÖVó :r   c                óB   <€ V ^8„  d   QhRS[ RS[ RS[S[S[ 3,          /# )r   rÃ   rÄ   r   )r   rQ   r/   )r   rR   s   "€r   r   rS   ~  s*   ø€ ÷ 	ñ 	©ð 	¹Cð 	ÁDÉÉcÈÅNñ 	r   c                óÄ   € / pV P                   ^ 8”  d   W,           VR&   V P                  ^ 8”  d1   V\        WP                  P                  ^,
          4      ,           VR&   V# )z¢Retrieve the key sequence length for the given request_id across all layer types. Returns a dictionary of
layer types to their corresponding key sequence lengths.r4   r3   )rz   r{   rš   r   r2   )r…   rÃ   rÄ   Ú	seqlens_ks   &&& r   Úget_seqlens_kÚ!PagedAttentionCache.get_seqlens_k~  s^   € ð ˆ	Ø×)Ñ)¨AÔ-Ø*5Õ*DˆIÐ&Ñ'Ø×,Ñ,¨qÔ0Ø-9¼CÀÏ[É[×MgÑMgÐjkÕMkÓ<lÕ-lˆIÐ)Ñ*àÐr   c                óì   <€ V ^8„  d   QhRS[ P                  RS[ P                  RS[RS[S[ P                  ,          RS[S[ P                  ,          RS[S[ P                  S[ P                  3,          /# )r   Ú
key_statesÚvalue_statesÚ	layer_idxrÅ   rÆ   r   )rP   rÑ   r   r.   r-   )r   rR   s   "€r   r   rS   ‰  ss   ø€ ÷ ;>ñ ;>á—L‘Lð;>ñ —l‘lð;>ñ ð	;>ñ
 ™Ÿ™Õ&ð;>ñ ™%Ÿ,™,Õ'ð;>ñ 
‰u�|‰|™UŸ\™\Ð)Õ	*ñ;>r   c                óÀ  € V P                   V,          w  rgWF,          pWV,          p	V P                  V,          p
V P                  V,          pVP                  ^^4      P	                  ^ 4      pVP                  ^^4      P	                  ^ 4      pVP                  4       ^ 8X  d(   V
P                  ^ W‘4       VP                  ^ W’4       W3# V P                  V,          pV^8X  dX   V
P                  ^ W‘4       VP                  ^ W’4       \        P                  ! V
^ V4      p\        P                  ! V^ V4      pWÞ3# W€P                  8H  P                  R4      P                  R4      p\        P                  ! V
^ V4      pVP                  Wñ4       \        P                  ! V^ V4      pVP                  Wò4       V
P                  ^ W‘4       VP                  ^ W’4       WÞ3# )a  Update the cache with new key-value states for a specific layer, and retrieves the relevant KV states from
the cache for attention computation. The behavior differs based on the layer's attention type:

- Full attention: New KV states are written to cache, then complete sequence is read from cache
- Sliding window: Old KV is read from cache along with extra spaces for the new KV, then new KV is written to
    cache. This is because new KV might overwrite the old KV, so we need to read the old KV first.

When the layer's read index is empty, the batch has no cache reads (all requests are non-chunked prefills): we
only write to the cache and return the input KV states directly, skipping the index_select read-back.

Returns the complete KV states (cached + new) for attention computation.
éÿÿÿÿ)r_   rl   rm   Ú	transposeÚsqueezerx   Úindex_copy_r^   rP   Úindex_selectrp   Ú	unsqueezeÚmasked_scatter_)r…   rÛ   rÜ   rÝ   rÅ   rÆ   Ú	group_idxÚlayer_idx_in_groupÚlayer_read_indexÚlayer_write_indexÚk_cacheÚv_cacher2   Úkey_states_with_cacheÚvalue_states_with_cacheÚmasks   &&&&&&          r   ÚupdateÚPagedAttentionCache.update‰  sÐ  € ð* )-×(IÑ(IÈ)Õ(TÑ%ˆ	Ø%Õ0ÐØ'Õ2ÐØ—.‘.Ð!3Õ4ˆØ×"Ñ"Ð#5Õ6ˆà×)Ñ)¨!¨QÓ/×7Ñ7¸Ó:ˆ
Ø#×-Ñ-¨a°Ó3×;Ñ;¸AÓ>ˆð ×!Ñ!Ó# qÔ(Ø×Ñ Ð#4ÔAØ×Ñ Ð#4ÔCØÐ+Ð+ð ×-Ñ-¨iÕ8ˆØ˜QÔØ×Ñ Ð#4ÔAØ×Ñ Ð#4ÔCÜ$)×$6Ò$6°wÀÐCSÓ$TÐ!Ü&+×&8Ò&8¸À!ÐEUÓ&VÐ#ð" %Ð=Ð=ð %×(;Ñ(;Ñ;×FÑFÀrÓJ×TÑTÐUWÓXˆDÜ$)×$6Ò$6°wÀÐCSÓ$TÐ!Ø!×1Ñ1°$ÔCÜ&+×&8Ò&8¸À!ÐEUÓ&VÐ#Ø#×3Ñ3°DÔGà×Ñ Ð#4ÔAØ×Ñ Ð#4ÔCð %Ð=Ð=r   c                ó&   <€ V ^8„  d   QhRS[ RS[/# )r   Úflash_attn_with_kvcache_fnr   )r   r/   )r   rR   s   "€r   r   rS   Æ  s   ø€ ÷ %ñ %¹cð %Ácñ %r   c                ó>  € V P                   f…   \        P                  ! V4      P                  P	                  4       pRV9   d   RV n         V P                   # RV9   d   RV n         V P                   # \        R\        P                  ! V4       24      hV P                   # )zïA function to get the name of the block table key for the given flash_attn_with_kvcache_fn. The function's
signature is only inspected once. This is necessary because different version of flash have different names for
the block table key.r«   Ú
page_tablezOflash_attn_with_kvcache_fn does not have a block_table or page_table argument: )r„   ÚinspectÚ	signatureÚ
parametersÚkeysr$   )r…   rò   Úkwarg_namess   && r   Úget_block_table_keyÚ'PagedAttentionCache.get_block_table_keyÆ  s²   € ð × Ñ Ò(Ü!×+Ò+Ð,FÓG×RÑR×WÑWÓYˆKØ Ô+Ø(5�Ô%ð ×$Ñ$Ð$ð  Ô,Ø(4�Ô%ð
 ×$Ñ$Ð$ô !ØeÔfm×fwÒfwð  ySó  gTð  fUð  Vóð ð ×$Ñ$Ð$r   c                ó<   <€ V ^8„  d   QhRS[ RS[S[,          RS[/# )r   r¦   Ú
prompt_idsr   )r/   r.   r   )r   rR   s   "€r   r   rS   Ö  s&   ø€ ÷ ñ ©cð ¹tÁC½yð ÉSñ r   c                ó°  € Rp. p\        \        V4      V P                  ,          4       F¤  pW%V P                  ,          V^,           V P                  ,           pV P                  P	                  W6^ R7      pV P                  P
                  P                  V4      pVe/   VP                  V4       V P                  P                  V4       K¤   M	  V'       dH   \        P                  ! RV R\        V4       R24       V P                  ^ ,          pWHP                  V&   \        V4      V P                  ,          p	V ;P                  V	,          un        V	# )a  Searches for a prefix match in the cache for the given (prompts_ids). If one is found, we reference the
matching blocks in the (request_id), increase the reference count of the blocks and return the number of blocks
that match. If no prefix match is found, we return 0.N)Úgroup_idzFound prefix match for request z with z blocks)r5   r:   r[   r‚   Úcompute_hashÚ_hash_to_idr8   r<   Úincrease_ref_countr   Údebugry   r«   rƒ   )
r…   r¦   rý   Úcurrent_hashr–   ÚbÚtokensÚblock_idr�   Úprefix_lengths
   &&&       r   Úsearch_prefix_matchÚ'PagedAttentionCache.search_prefix_matchÖ  s  € ð ˆØÐÜ”s˜:“¨$¯/©/Õ9Ö:ˆAØ D§O¡OÕ 3°q¸1µuÀÇÁÕ6OÐPˆFà×.Ñ.×;Ñ;¸LÐ[\Ð;Ó]ˆLØ×*Ñ*×6Ñ6×:Ñ:¸<ÓHˆHØÒ#Ø ×'Ñ'¨Ô1Ø×#Ñ#×6Ñ6°xÖ@áñ ;÷ Ü�LŠLÐ:¸:¸,ÀfÌSÐQaÓMbÐLcÐcjÐkÔlØ×*Ñ*¨1Õ-ˆBØ)9�N‰N˜:Ñ&äÐ,Ó-°·±Õ?ˆØ×!Ò! ]Õ2Õ!ØÐr   c                ó*   <€ V ^8„  d   QhRS[ RS[RR/# )r   ÚstateÚnum_complete_blocksr   N)r   r   )r   rR   s   "€r   r   rS   ð  s$   ø€ ÷ ñ ±|ð ÑZ]ð Ðbfñ r   c                óL  € V^ 8X  g    VP                   \        P                  8X  d   R# V P                   Fk  pVP                  '       g   K  V P
                  P                  VVP                  VP                  ,          VP                  VP                  ,           R7       Km  	  R# )aƒ  Marks the blocks allocated to a request (state) as complete if they are shareable and they have been computed
in the forward pass. A complete block is a block where the KV cache has been fully computed: if the block has
enough space to hold the cache for N tokens, the block is marked as complete when the cache data is present for
the N tokens. If block sharing is off, this is a no-op.N)r  r–   rý   )Ústatusr   ÚFINISHEDry   Úuses_block_sharingr‚   Ú!mark_shareable_blocks_as_completer«   r¦   Úinitial_tokensÚgenerated_tokens)r…   r  r  r�   s   &&& r   r  Ú5PagedAttentionCache.mark_shareable_blocks_as_completeð  s   € ð  !Ô# u§|¡|´}×7MÑ7MÔ'MÙØ×+Ô+ˆBØ×$×$Ò$Ø×#Ñ#×EÑEØ(;Ø%'§^¡^°E×4DÑ4DÕ%EØ %× 4Ñ 4°u×7MÑ7MÕ Mð Fö ó ,r   c                óJ   <€ V ^8„  d   QhRS[ S[,          RS[ S[,          RR/# )r   Úlist_source_blocksÚlist_forked_blocksr   N)r.   r   )r   rR   s   "€r   r   rS     s1   ø€ ÷ Dñ D©T±#­Yð DÉDÑQTÍIð DÐZ^ñ Dr   c                ó  € \         P                  ! WP                  \         P                  R7      p\         P                  ! W P                  \         P                  R7      p\	        V P
                  V P                  4       F}  w  rVVP                  RV P                  V P                  V P                  4      pVP                  RV P                  V P                  V P                  4      pWS,          WT&   Wc,          Wd&   K  	  R# )z;Copy the cache from the source blocks to the forked blocks.rX   Nrß   )rP   rd   rL   Úint32rÈ   rl   rm   ru   r[   r    r)   )r…   r  r  Úsource_blocksÚforked_blocksrl   rm   s   &&&    r   Ú
copy_cacheÚPagedAttentionCache.copy_cache  s»   € äŸšÐ%7ÇÁÔSX×S^ÑS^Ô_ˆÜŸšÐ%7ÇÁÔSX×S^ÑS^Ô_ˆÜ&)¨$¯.©.¸$×:JÑ:JÖ&KÑ"ˆIØ!Ÿ™ r¨4¯?©?¸D×<TÑ<TÐVZ×VcÑVcÓdˆIØ%×*Ñ*¨2¨t¯©À×@XÑ@XÐZ^×ZgÑZgÓhˆKØ'0Õ'?ˆIÑ$Ø)4Õ)CˆKÓ&ó	 'Lr   c                ó&   <€ V ^8„  d   QhRS[ RS[/# )r   Úsource_request_idr   r§   )r   rR   s   "€r   r   rS     s   ø€ ÷ Dñ D±sð D¹sñ Dr   c                ón  € ^ pV P                    F„  pVP                  V,          p^ pVP                  '       dB   V F;  pV P                  P                  V,          P
                  '       g    MV^,          pK=  	  V\        V4      V,
          ,          pK†  	  V^ 8X  d   R# V P                  4       V,          # )z\Computes the maximum number of children requests that can be forked from the source request.l        )ry   r«   r  r‚   Ú_id_to_blockÚis_completer:   r¢   )r…   r   Úblocks_needed_per_forkr�   Ú	block_idsÚshareable_blocksr  s   &&     r   Úcompute_max_num_forksÚ)PagedAttentionCache.compute_max_num_forks  s«   € ð "#ÐØ×+Ô+ˆBØŸ™Ð'8Õ9ˆIØ ÐØ×$×$Ð$Û )�HØ×.Ñ.×;Ñ;¸HÕE×Q×QÐQÙØ$¨Õ)Ò$ñ !*ð #¤c¨)£nÐ7GÕ&GÕGÒ"ñ ,ð " QÔ&ØˆLØ×'Ñ'Ó)Ð-CÕCÐCr   c          	      ór   <€ V ^8„  d   QhRS[ RS[S[ ,          RS[S[S[,          S[S[,          3,          /# )r   r   Údestination_request_idsr   )r/   r.   r-   r   )r   rR   s   "€r   r   rS     s@   ø€ ÷ 	1ñ 	1©cð 	1ÉDÑQTÍIð 	1ÑZ_Ñ`dÑehÕ`iÑkoÑpsÕktÐ`tÕZuñ 	1r   c                ó´   € . . rCV P                    FC  pVP                  WV P                  4      w  rgVP                  V4       VP                  V4       KE  	  W43# )zhFork the cache of a request (state) into the one of a list of requests with the given (dst_request_ids).)ry   Úfork_blocksr‚   rÉ   )r…   r   r*  r  Údestination_blocksr�   Ú
src_blocksÚ
dst_blockss   &&&     r   Úfork_requestÚ PagedAttentionCache.fork_request  s^   € ð -/°Ð)à×+Ô+ˆBØ%'§^¡^Ð4EÐ`d×`sÑ`sÓ%tÑ"ˆJØ× Ñ  Ô,Ø×%Ñ% jÖ1ñ ,ð Ð0Ð0r   c                ó   <€ V ^8„  d   QhRR/# )r   r   Nrª   )r   rR   s   "€r   r   rS   *  s   ø€ ÷ )ñ ) 4ñ )r   c                óÆ   € \        4       pV P                   F,  pVP                  VP                  P	                  4       4       K.  	  V F  pV P                  V4       K  	  R# )zûFree all blocks allocated to requests across all cache managers. This preserves prefix hashes in the block
manager (blocks become initialized rather than uninitialized if they were complete), allowing prefix sharing
to work across generation sessions.N)Úsetry   rï   r«   rø   r»   )r…   Úall_request_idsr�   r¦   s   &   r   Úfree_all_requestsÚ%PagedAttentionCache.free_all_requests*  sN   € ô ›%ˆØ×+Ô+ˆBØ×"Ñ" 2§>¡>×#6Ñ#6Ó#8Ö9ñ ,ã)ˆJØ×Ñ˜ZÖ(ó *r   )r‚   r„   rƒ   rY   r[   rn   r   rL   rO   ry   r)   rl   r_   rh   r~   r|   ri   rz   r]   r    rj   r{   ro   rp   r^   r�   rm   rq   N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r\   rP   Úfloat16r‘   r�   r£   r°   rµ   r»   r¢   rÎ   rÓ   rØ   rï   rú   r	  r  r  r'  r0  r6  Ú__static_attributes__Ú__classdictcell__©rR   s   @r   rI   rI   Y   sß   ø‡ € ñ6ðp €Oð #Ÿ]™]÷Z%ò Z%÷xð ÷&hð h÷`ð `÷ð ÷<ð <÷3ð 3÷`ð `÷(Wð W÷	ð 	÷;>ð ;>÷z%ð %÷ ð ÷4ð ÷"Dð D÷Dð D÷$	1ð 	1÷)ö )r   rI   c                   óê   a € ] tR tRt o RtRtRtV 3R lR lt]V 3R lR l4       t	V 3R	 lR
 lt
V 3R lR ltV 3R lR ltV 3R lR ltV 3R lR ltV 3R lR ltV 3R lR ltV 3R lR ltRtV tR# )rb   i5  u’  Determines the optimal max batch tokens (M) and number of blocks (N) for the paged attention cache, given
available GPU memory. The relation between N and number of blocks is: num_blocks = N // block_size.

The memory footprint is a polynomial in M and N, where each term maps to a tensor allocated in
``ContinuousBatchingIOs._setup_static_tensors`` or ``PagedAttentionCache.__init__``:

    memory(M, N)  =  coeff_m Â· M  +  coeff_n Â· N  +  coeff_mn Â· MÂ·N  +  coeff_mm Â· MÂ²

See ``_equation_coefficients`` for the breakdown.  All three solving modes (auto, fixed-N, fixed-M) reduce to
solving this equation, which is at most quadratic in one variable.
é   i    c                ó`   <€ V ^8„  d   QhRS[ RS[RS[P                  RS[S[,          RS[RR/# )r   r   rK   rO   rF   rC   r   N)r   r   rP   rO   r.   r/   r   )r   rR   s   "€r   r   Ú(PagedAttentionMemoryHandler.__annotate__E  sO   ø€ ÷ %<ñ %<á ð%<ñ %=ð%<ñ �{‰{ð	%<ñ
 ™#•Yð%<ñ ð%<ð 
ñ%<r   c                ó   € Wn         W n        W0n        W0n        VP                  V n        \        V4      \        V4      ,          V n        \        V4      V n	        WPn
        \        V P                   4      '       d	   ^ V n        MRV9   d   ^M^V n        VP                  V n        V P                  f   VP                  V n        VP                  '       d   ^M^V n        VP"                  '       d   ^M^V n        V P'                  4       V n        R# )aF  Initialize the memory handler. Args:
- config: the model configuration
- continuous_batching_config: the continuous batching configuration
- dtype: the data type of the activation and the cache
- group_types: the list of all attention group types, formatted as strings
- group_size: the size (in layers) of an attention group
r3   N)r   rV   Úcache_dtypeÚactivation_dtyper[   r+   r&   Ú	page_sizer:   r]   rC   r	   Únum_attention_masksr~   r€   Úreturn_logprobsÚnum_output_rowsÚuse_async_batchingÚio_multiplierÚget_available_memoryÚavailable_memory)r…   r   rK   rO   rF   rC   s   &&&&&&r   r‘   Ú$PagedAttentionMemoryHandler.__init__E  sß   € ð ŒØ3ŒØ ÔØ %ÔØ4×?Ñ?ˆŒÜ& vÓ.Ô1BÀ6Ó1JÕJˆŒÜ˜kÓ*ˆŒØ$Œô (¨¯©×4Ò4Ø'(ˆDÕ$à,?À;Ô,N¡qÐTUˆDÔ$à&@×&WÑ&WˆÔ#Ø×&Ñ&Ò.Ø*D×*dÑ*dˆDÔ'à$>×$N×$NÐ$N™qÐTUˆÔà"<×"O×"OÐ"O™QÐUVˆÔØ $× 9Ñ 9Ó ;ˆÖr   c                óJ   <€ V ^8„  d   QhRS[ S[S[S[R3,          3,          /# )r   r   .)rQ   r/   r-   r   )r   rR   s   "€r   r   rD  m  s&   ø€ ÷ ñ ¡¡c©5±°c°­?Ð&:Õ!;ñ r   c                óP  € V P                   P                  \        V P                   4      ,          pV P                  p/ pV P                   P                  V P
                  P                  ,          pW@P                   P                  \        P                  P                  ,          ,          pV^ ^ ^ 3VR&   V P
                  P                  V P                   P                  V,           ^V,          ,           ,          p^V,          V P
                  P                  ,          pWE^ ^ 3VR&   V# )r   Úlm_headÚ	attention)
r   r!   r+   rH  r*   rG  ÚitemsizeÚ
vocab_sizerP   Úfloat32)r…   Úmem_per_q_tokenÚmem_per_k_or_v_tokenÚpeaksÚdelta_mÚdelta_ns   &     r   Úactivation_peakÚ+PagedAttentionMemoryHandler.activation_peakl  só   € àŸ+™+×9Ñ9¼MÈ$Ï+É+Ó<VÕVˆØ#Ÿ~™~ÐØˆð —+‘+×)Ñ)¨D×,AÑ,A×,JÑ,JÕJˆØ—;‘;×)Ñ)¬E¯M©M×,BÑ,BÕBÕBˆØ# Q¨¨1Ð-ˆˆiÑð ×'Ñ'×0Ñ0Ø�K‰K×#Ñ#ØõàÐ&Õ&õ'õ
ˆð Ð*Õ*¨T×-BÑ-B×-KÑ-KÕKˆØ%°°1Ð5ˆˆkÑàˆr   c                ó    <€ V ^8„  d   QhRS[ /# r¾   r—   )r   rR   s   "€r   r   rD  ƒ  s   ø€ ÷  ñ  ¡cñ  r   c                óÐ   € \        4       w  rr4V\        WC4      ,
          p\        WPP                  P                  ,          4      p\
        P                  ! RVR,           R24       V# )z–Calculate available GPU memory for cache allocation in bytes, accounting for the maximum memory percent limit
fixed by the continuous batching config.z'Memory available for cache allocation: z MBi   )r   r™   r   rV   ra   r   rk   )r…   r>   ÚtotalÚreservedÚ	allocatedrO  s   &     r   rN  Ú0PagedAttentionMemoryHandler.get_available_memoryƒ  s`   € ô )HÓ(IÑ%ˆ�(Ø ¤3 yÓ#;Õ;ÐÜÐ/·.±.×2SÑ2SÕSÓTÐÜ�ŠÐ=Ð>NÐRYÕ>YÐ=ZÐZ]Ð^Ô_ØÐr   c                ó6   <€ V ^8„  d   QhRS[ S[S[3,          /# r¾   ©r-   r   )r   rR   s   "€r   r   rD  Œ  s   ø€ ÷ Cñ C±u¹SÁ#¸Xµñ Cr   c                ó¶  € V P                   P                  pV P                   P                  pVe   Ve   V P                  W4      # Vf   Ve'   V P	                  WRR7      w  rV P                  W4      # V P	                  RRRR7      w  r4\        V P                  V4      p\        WP                  4      pV P	                  WRR7      w  rV P                  W4      # )aH  Infers max_batch_tokens and num_blocks based on the available memory and the size of the activation peaks.
If neither value is provided, we use a default value of 8192 for max_batch_tokens, apply bounds depending on the
available VRAM, and solve for num_blocks. If one value is provided, the other is found using a linear solve.N)Úcache_fill_per_batchgš™™™™™¹?)rh   ri   rh  )	rV   rh   ri   Ú_check_footprintÚ_solve_for_peaksrš   Ú_default_max_batch_tokensr™   Ú_min_max_batch_tokens)r…   rh   ri   Úupper_bound_vramr>   s   &    r   rc   ÚAPagedAttentionMemoryHandler.infer_max_batch_tokens_and_num_blocksŒ  sû   € ð  Ÿ>™>×:Ñ:ÐØ—^‘^×.Ñ.ˆ
ð Ò'¨JÒ,BØ×(Ñ(Ð)9ÓFÐFð Ò'¨:Ò+AØ+/×+@Ñ+@Ø À4ð ,Aó ,Ñ(Ðð ×(Ñ(Ð)9ÓFÐFð #×3Ñ3Ø!ØØ!$ð 4ó 
ÑÐô
 ˜t×=Ñ=Ð?OÓPÐÜÐ/×1KÑ1KÓLÐà'+×'<Ñ'<Ð=MÐptÐ'<Ó'uÑ$ÐØ×$Ñ$Ð%5ÓBÐBr   c          
      ór   <€ V ^8„  d   QhRS[ R,          RS[ R,          RS[R,          RS[S[ S[ 3,          /# )r   rh   Nri   rh  r   )r   Úfloatr-   )r   rR   s   "€r   r   rD  ª  sG   ø€ ÷  ñ  á �*ð ñ ˜$•Jð ñ $ d�lð	 ñ
 
‰s‘Cˆx�ñ r   c                ó2  € . pV P                   P                  4        F)  pV P                  WQW#4      w  rgVP                  Wg34       K+  	  \	        V Uu. uF  qˆ^ ,          NK  	  up4      p	\	        V Uu. uF  qˆ^,          NK  	  up4      p
Wš3# u upi u upi )a}  Returns max_batch_tokens and num_blocks so that their memory footprint is within the available memory for all
activation peaks. If neither value is given, a value must be provided for cache_fill_per_batch: this means we
solve for both variables by saying each batch fill a certain percentage of the cache (eg, if cache_fill_per_batch
is 0.01, each batch will fill 1% of the cache).)r]  r9   Ú_solve_for_peakr<   rš   )r…   rh   ri   rh  Ú	solutionsÚpeak_deltasÚmÚnÚsolutionÚfinal_mÚfinal_ns   &&&&       r   rj  Ú,PagedAttentionMemoryHandler._solve_for_peaksª  s“   € ð ˆ	à×/Ñ/×6Ñ6Ö8ˆKØ×'Ñ'¨ÀzÓh‰DˆAØ×Ñ˜a˜VÖ$ñ 9ô ±9Ó=±9 x —{�{±9Ñ=Ó>ˆÜ±9Ó=±9 x —{�{±9Ñ=Ó>ˆØÐÐùò >ùÚ=s   ÁBÁ4Bc                óŒ   <€ V ^8„  d   QhRS[ S[R3,          RS[R,          RS[R,          RS[R,          RS[ S[S[3,          /# )r   Úpeak.rh   Nri   rh  r   )r-   r   rp  )r   rR   s   "€r   r   rD  ¾  sY   ø€ ÷ !,ñ !,á‘C˜�H�oð!,ñ  �*ð!,ñ ˜$•Jð	!,ñ
 $ d�lð!,ñ 
‰s‘Cˆx�ñ!,r   c                óÀ  € V P                  V4      w  rVrxVf‹   Vf‡   Vf   \        R4      hTp	V P                  Wy,          W‰^,          ,          ,           WeV	,          ,           V P                  ) 4      p
\	        W©,          4      p\	        V
4      V P
                  ,          pW#3# Vfb   Tp\        V P                  W[,          ,
          W‹^,          ,          ,
          WgV,          ,           ,          4      p
W P
                  ,          pW#3# VfR   W0P
                  ,          p\	        V P                  W…W|,          ,           Wl,          V P                  ,
          4      4      pW#3# )zvReturns a couple of `(max_batch_tokens, num_blocks)` that satisfy the memory constraint for the given
activation peak.z>m must be provided if max_batch_tokens and num_blocks are None)Ú_equation_coefficientsr$   Ú_solve_quadraticrO  r   r[   r   )r…   r|  rh   ri   rh  r�   ÚcnÚcmnÚcmmru  rj   ÚMÚNs   &&&&&        r   rr  Ú+PagedAttentionMemoryHandler._solve_for_peak¾  s4  € ð  ×6Ñ6°tÓ<Ñˆ�ð Ò#¨
Ò(:à#Ò+Ü Ð!aÓbÐbØ$ˆAØ×-Ñ-¨c­g¸À½d½
Õ.BÀBÈaÍÅKÐRV×RgÑRgÐQgÓhˆIÜ" 9¥=Ó1ÐÜ˜Y›¨4¯?©?Õ:ˆJð  Ð+Ð+ð Òà ˆAÜ˜t×4Ñ4°rµvÕ=ÀÈÅdÅ
ÕJÈrÐZ[ÕT[Í|Õ\Ó]ˆIØ"§o¡oÕ5ˆJð  Ð+Ð+ð Ò%àŸ_™_Õ,ˆAÜ" 4×#8Ñ#8¸À3Å7½lÈBÍFÐUY×UjÑUjÕLjÓ#kÓlÐàÐ+Ð+r   c                óB   <€ V ^8„  d   QhRS[ RS[ RS[S[ S[ 3,          /# ©r   rh   ri   r   )r   r-   )r   rR   s   "€r   r   rD  á  s-   ø€ ÷ 	,ñ 	,±ð 	,Á#ð 	,É%ÑPSÑUXÐPXÍ/ñ 	,r   c                ó¾   € V P                  W4      pW0P                  8”  d   \        RV RV P                   24      hV^ 8:  g   V^ 8:  d   \        RV RV 24      hW3# )zDChecks if the footprint of the cache is within the available memory.zMemory footprint z is more than available memory z#Invalid values: max_batch_tokens = z, num_blocks = )Úcompute_memory_footprintrO  ÚMemoryErrorr$   )r…   rh   ri   Úmemory_footprints   &&& r   ri  Ú,PagedAttentionMemoryHandler._check_footprintá  s   € à×8Ñ8Ð9IÓVÐØ×3Ñ3Ô3ÜØ#Ð$4Ð#5Ð5TÐUY×UjÑUjÐTkÐlóð ð ˜qÔ  J°!¤OÜÐBÐCSÐBTÐTcÐdnÐcoÐpÓqÐqØÐ+Ð+r   c                ó2   <€ V ^8„  d   QhRS[ RS[ RS[ RS[/# )r   Úar  Úcr   )rp  r   )r   rR   s   "€r   r   rD  ì  s)   ø€ ÷ 
 ñ 
 ¡%ð 
 ©Eð 
 ±eð 
 Áñ 
 r   c                ó4  € V^ 8X  d   \        V) V,          4      # V^,          ^V,          V,          ,
          pV^ 8  d   \        RV R24      hV) \        V4      ,           ^V,          ,          pV^ 8  d   \        RV R24      h\        \        V4      4      # )u_   Largest positive root of aÂ·xÂ² + bÂ·x + c = 0. Falls back to linear when a == 0. Rounded down.z!No real solution (discriminant = Ú)zNo positive solution (root = )r   r$   r   r   )r…   rŽ  r  r�  ÚdiscriminantÚroots   &&&&  r   r  Ú,PagedAttentionMemoryHandler._solve_quadraticì  s‘   € à�Œ6Ü˜�r˜A•v“;ÐØ˜!•t˜a !�e a�iÕ'ˆØ˜!ÔÜÐ@ÀÀÈaÐPÓQÐQØ�”T˜,Ó'Õ'¨A°­EÕ2ˆØ�!Œ8ÜÐ<¸T¸FÀ!ÐDÓEÐEÜ”5˜“;ÓÐr   c                óN   <€ V ^8„  d   QhRS[ S[R3,          RS[ S[R3,          /# )r   rt  .r   rf  )r   rR   s   "€r   r   rD  ú  s,   ø€ ÷ '4ñ '4±%¹¸S¸µ/ð '4ÁeÉCÐQTÈHÅoñ '4r   c                ó  € Vw  r#rE\         P                  P                  pV P                  P                  pV P                  P                  pV P
                  p	V^V P                  ,          V P                  ,          V,          ,           W�P                  ,          ^,          ,           p
VV	^,          V,          ,           W�P                  ,          V,          ,           W�P                  ,          V P                  ,          V,          ,           W�P                  ,          ^,          ,           W�P                  ,          ^,          ,           pVW�P                  ,          V,          ,           pVW�P                  ,          V,          ,           pWºWÍ3# )z³Given some deltas corresponding to an activation peak, returns the coefficients for the memory polynomial of
that peak. The memory polynomial is described in that class docstring.)rP   r  rU  rG  rF  rM  rC   rH  r]   rK  r~   rI  )r…   rt  r[  r\  Údelta_mmÚdelta_mnr@   rŽ  r�  ÚkÚcoeff_nÚcoeff_mÚcoeff_mnÚcoeff_mms   &&            r   r~  Ú2PagedAttentionMemoryHandler._equation_coefficientsú  sW  € ð 0;Ñ,ˆ˜(ä�K‰K× Ñ ˆØ×!Ñ!×*Ñ*ˆØ×Ñ×%Ñ%ˆØ×Ñˆð Ø�$—/‘/Õ! D§N¡NÕ2°QÕ6õ7à—/‘/Õ! AÕ%õ&ð 	ð Ø�!�e�a�iõà×&Ñ&Õ&¨Õ*õ+ð —/‘/Õ!Ø×)Ñ)õ*Ø,-õ.õ.ð
 —/‘/Õ! AÕ%õ&ð —/‘/Õ! AÕ%õ&ð 	ð Ø×*Ñ*Õ*¨QÕ.õ/ð 	ð Ø×*Ñ*Õ*¨QÕ.õ/ð 	ð
  Ð3Ð3r   c                ó,   <€ V ^8„  d   QhRS[ RS[ RS[ /# r‡  r—   )r   rR   s   "€r   r   rD  $  s#   ø€ ÷ 
$ñ 
$¹ð 
$É#ð 
$ÑRUñ 
$r   c                ó,  € TpW P                   ,          p^ pV P                  P                  4        F_  pV P                  V4      w  rxršW„,          Ws,          ,           W”,          V,          ,           W£,          V,          ,           p\	        W[4      pKa  	  V# )zaEvaluate the memory polynomial at concrete (N, M) values, taking the max across activation peaks.)r[   r]  r9   r~  r™   )r…   rh   ri   rƒ  r„  Úmax_memory_footprintr|  r�   r€  r�  r‚  r‹  s   &&&         r   r‰  Ú4PagedAttentionMemoryHandler.compute_memory_footprint$  s   € àˆØŸ™Õ(ˆà ÐØ×(Ñ(×/Ñ/Ö1ˆDØ#×:Ñ:¸4Ó@ÑˆB�CØ!�v¨­�°µ¸1µÕ<¸s½wÈ½{ÕJÐÜ#&Ð';Ó#NÒ ñ 2ð $Ð#r   )rG  rO  r[   rF  rV   r   rC   rM  r~   rI  r]   rK  rH  N)r8  r9  r:  r;  r<  rl  rk  r‘   Úpropertyr]  rN  rc   rj  rr  ri  r  r~  r‰  r>  r?  r@  s   @r   rb   rb   5  s‹   ø‡ € ñ
ð  ÐØ $Ð÷%<ð %<ðN ÷ó ð÷, ð  ÷Cð C÷< ð  ÷(!,ð !,÷F	,ð 	,÷
 ð 
 ÷'4ð '4÷T
$ö 
$r   rb   )!rõ   Úmathr   r   r   Útypingr   rP   Úconfiguration_utilsr   Úgeneration.configuration_utilsr   Úutils.genericr	   Úcache_managerr
   r   r   r   Údistributedr   Úinitializationr   Úrequestsr   r   r   r   r&   r+   rG   rI   rb   rª   r   r   Ú<module>r­     s\   ðó ß !Ñ !Ý ã å 3Ý FÝ 9ß tÓ tÝ *Ý 6ß ZÓ Zõ
põwõ%÷BY)ñ Y)÷xy$ó y$r   