perf: precompute kv_indptr once per decode step
- bind_tasks builds kv_indptr (prefix sum of seq_lens) a single time - fwd_decode/fwd_prefill reuse it instead of rebuilding per layer - Removes 24 cumsum launches per decode step (was ~1ms/step at B=4) - Decode B=4: 9.60 -> 7.82 ms/step (-18.5%), +22.8% tok/s
This commit is contained in:
@@ -341,8 +341,7 @@ class CudaBackend(AttentionBackend):
|
|||||||
b = q.size(0)
|
b = q.size(0)
|
||||||
q_3d = q.squeeze(1)
|
q_3d = q.squeeze(1)
|
||||||
|
|
||||||
kv_indptr = torch.zeros(b + 1, dtype=torch.int32, device=q.device)
|
kv_indptr = kv_cache.kv_indptr
|
||||||
kv_indptr[1:] = kv_cache.seq_lens.cumsum(0).to(torch.int32)
|
|
||||||
|
|
||||||
out = attn_paged_decode(
|
out = attn_paged_decode(
|
||||||
q_3d,
|
q_3d,
|
||||||
@@ -376,9 +375,7 @@ class CudaBackend(AttentionBackend):
|
|||||||
b = q.size(0)
|
b = q.size(0)
|
||||||
q_len = q.size(1)
|
q_len = q.size(1)
|
||||||
|
|
||||||
kv_indptr = torch.zeros(b + 1, dtype=torch.int32, device=q.device)
|
kv_indptr = kv_cache.kv_indptr
|
||||||
kv_indptr[1:] = kv_cache.seq_lens.cumsum(0).to(torch.int32)
|
|
||||||
|
|
||||||
qo_indptr = torch.arange(b + 1, dtype=torch.int32, device=q.device) * q_len
|
qo_indptr = torch.arange(b + 1, dtype=torch.int32, device=q.device) * q_len
|
||||||
|
|
||||||
q_flat = q.reshape(b * q_len, q.size(2), q.size(3))
|
q_flat = q.reshape(b * q_len, q.size(2), q.size(3))
|
||||||
|
|||||||
@@ -203,6 +203,8 @@ class KVCache:
|
|||||||
seq_lens: [batch_size] — per-request total sequence lengths
|
seq_lens: [batch_size] — per-request total sequence lengths
|
||||||
out_cache_loc: [batch, new_seq_len] or [batch, 1] — write indices
|
out_cache_loc: [batch, new_seq_len] or [batch, 1] — write indices
|
||||||
max_len: max(seq_lens) as Python int — avoids GPU sync in decode
|
max_len: max(seq_lens) as Python int — avoids GPU sync in decode
|
||||||
|
kv_indptr: [batch+1] int32 — prefix sum of seq_lens, precomputed once
|
||||||
|
per step so the attention backend avoids rebuilding it per layer.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
k_buffer: Tensor
|
k_buffer: Tensor
|
||||||
@@ -212,6 +214,7 @@ class KVCache:
|
|||||||
seq_lens: Tensor
|
seq_lens: Tensor
|
||||||
out_cache_loc: Tensor
|
out_cache_loc: Tensor
|
||||||
max_len: int = 0
|
max_len: int = 0
|
||||||
|
kv_indptr: Optional[Tensor] = None
|
||||||
|
|
||||||
|
|
||||||
class PagePool:
|
class PagePool:
|
||||||
@@ -434,6 +437,9 @@ class PagePool:
|
|||||||
req_pool_indices, write_pos
|
req_pool_indices, write_pos
|
||||||
].unsqueeze(-1)
|
].unsqueeze(-1)
|
||||||
|
|
||||||
|
kv_indptr = torch.zeros(len(seq_lens) + 1, dtype=torch.int32, device=device)
|
||||||
|
kv_indptr[1:] = seq_lens_t.cumsum(0).to(torch.int32)
|
||||||
|
|
||||||
return KVCache(
|
return KVCache(
|
||||||
k_buffer=self._storage.k_buffer,
|
k_buffer=self._storage.k_buffer,
|
||||||
v_buffer=self._storage.v_buffer,
|
v_buffer=self._storage.v_buffer,
|
||||||
@@ -442,6 +448,7 @@ class PagePool:
|
|||||||
seq_lens=seq_lens_t,
|
seq_lens=seq_lens_t,
|
||||||
out_cache_loc=out_cache_loc,
|
out_cache_loc=out_cache_loc,
|
||||||
max_len=max(seq_lens),
|
max_len=max(seq_lens),
|
||||||
|
kv_indptr=kv_indptr,
|
||||||
)
|
)
|
||||||
|
|
||||||
# ---- internals ----
|
# ---- internals ----
|
||||||
|
|||||||
Reference in New Issue
Block a user