feat: add timed() context manager and backend supports()

- Each backend exposes static supports(**kwargs) for capability query
- CudaBackend.supports checks head_dim + kernel availability
- FlashAttnBackend/TorchNativeBackend always return True
- timed() context manager gated by ASTRAI_TIMED=1 env var, logs via logger.info
- Wraps warmup prefill/decode, execute_prefill, and execute_decode
This commit is contained in:
2026-08-07 20:51:30 +08:00
parent e0f7fa8e13
commit 05739629fc
2 changed files with 58 additions and 23 deletions
+17 -7
View File
@@ -388,6 +388,10 @@ class TorchNativeBackend(AttentionBackend):
runs SDPA directly on the projected q/k/v.
"""
@staticmethod
def supports(**kwargs) -> bool:
return True
def fwd_decode(
self,
q: Tensor,
@@ -479,6 +483,15 @@ class CudaBackend(AttentionBackend):
Raises ``RuntimeError`` if the required kernel is not available.
"""
@staticmethod
def supports(**kwargs) -> bool:
head_dim = kwargs.get("head_dim", -1)
return (
head_dim in (32, 64, 128, 256)
and is_available("attn_paged_decode")
and is_available("attn_paged_prefill")
)
def fwd_decode(
self,
q: Tensor,
@@ -575,15 +588,12 @@ class FlashAttnBackend(AttentionBackend):
Prefill / non-contiguous decode: falls back to KV gather +
``flash_attn_func``.
This backend only does flash attention — inputs ``flash-attn`` cannot
express (missing package, custom attention mask on prefill, fp32,
unsupported head_dim) raise a clear error instead of silently falling
back to torch.
For a torch fallback, select ``TorchNativeBackend`` instead.
"""
@staticmethod
def supports(**kwargs) -> bool:
return flash_attn_available()
def fwd_decode(
self,
q: Tensor,