Skip to content

Commit d1327ae

Browse files
authored
add thead vendor attention backend (#297)
### PR Category <!-- One of [Core | Vendor | OP | Tools | Others] --> vendor ### PR Type <!-- One of [User Experience | New Features | Bug Fixes | Improvements | Performance | Breaking Change | Deprecations | Test Case | Docs | Others] --> User Experience ### Description <!-- Describe what this PR does and why. --> add thead vendor attention backend ### Related Issues <!-- Link any related issues: Fixes #issue, Closes #issue, or Related to #issue --> ### Changes <!-- List the key changes made in this PR. --> - add thead vendor attention backend ### Testing <!-- How has this change been tested? Include test commands, hardware used, etc. --> - verify qwen3.6-35B use vendor attention backend on PPU without accuracy and perf verify minicpm5 use vendor attention backend on PPU with accuracy and perf ### Checklist - [ ] I have run the existing tests and they pass - [ ] I have added tests for my changes (if applicable) - [ ] I have updated the documentation (if applicable)
1 parent 56847fe commit d1327ae

8 files changed

Lines changed: 598 additions & 32 deletions

File tree

vllm_fl/dispatch/backends/flaggems/flaggems.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from typing import Optional, Union
1212

1313
import torch
14+
import os
1415

1516
from vllm_fl.dispatch.backends.base import Backend
1617

@@ -206,7 +207,14 @@ def attention_backend(self, use_mla: bool = False, use_sparse: bool = False) ->
206207

207208
if use_sparse:
208209
raise ValueError("use_sparse=True requires use_mla=True.")
209-
# TODO: return "vllm_fl.dispatch.backends.flaggems.impl.attention.AttentionFLBackend"
210+
211+
use_flaggems_attn = os.environ.get(
212+
"VLLM_FL_USE_FLAGGEMS_ATTN", "0"
213+
).lower() in ("1", "true", "yes")
214+
215+
if use_flaggems_attn:
216+
print("Using FlagGems attention backend.")
217+
return "vllm_fl.dispatch.backends.flaggems.impl.attention.AttentionFLBackend"
210218

211219
return AttentionBackendEnum.TRITON_ATTN.get_path()
212220

vllm_fl/dispatch/backends/flaggems/impl/attention.py

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ def get_supported_kernel_block_sizes() -> list[int | MultipleOf]:
7474

7575
@staticmethod
7676
def get_name() -> str:
77-
return "FL"
77+
return "CUSTOM"
7878

7979
@classmethod
8080
def supports_attn_type(cls, attn_type: str) -> bool:
@@ -457,7 +457,7 @@ def __init__(
457457
self.num_queries_per_kv = self.num_heads // self.num_kv_heads
458458

459459
self.attn_type = attn_type
460-
self.vllm_flash_attn_version = 2 if current_platform.device_type == "txda" else 3 # 2 #get_flash_attn_version()
460+
self.vllm_flash_attn_version = 2 # FlagGems only supports FA2
461461
# Cache the batch invariant result for use in forward passes
462462
self.batch_invariant_enabled = _bi_mode
463463

@@ -468,6 +468,34 @@ def __init__(
468468
### TODO(lms): support quant to int8/int4 each query input and low precision compute
469469
self.supports_quant_query_input = False
470470

471+
def do_kv_cache_update(
472+
self,
473+
layer,
474+
key: torch.Tensor,
475+
value: torch.Tensor,
476+
kv_cache: torch.Tensor,
477+
slot_mapping: torch.Tensor,
478+
):
479+
"""Write key/value into the paged KV cache.
480+
481+
This is called by vLLM's unified_kv_cache_update custom op
482+
*before* forward(), so forward() should NOT repeat the write.
483+
"""
484+
if self.attn_type in (AttentionType.ENCODER_ONLY, AttentionType.ENCODER):
485+
return
486+
487+
key_cache, value_cache = kv_cache.unbind(0)
488+
reshape_and_cache_flash(
489+
key,
490+
value,
491+
key_cache,
492+
value_cache,
493+
slot_mapping,
494+
self.kv_cache_dtype,
495+
layer._k_scale,
496+
layer._v_scale,
497+
)
498+
471499
def forward(
472500
self,
473501
layer: torch.nn.Module,
@@ -532,35 +560,11 @@ def forward(
532560
layer,
533561
)
534562

535-
# For decoder and cross-attention, use KV cache as before
563+
# For decoder and cross-attention, use KV cache as before.
564+
# NOTE: KV cache write is handled by do_kv_cache_update() which is
565+
# called separately by vLLM's unified_kv_cache_update custom op.
536566
key_cache, value_cache = kv_cache.unbind(0)
537567

538-
# key and value may be None in the case of cross attention. They are
539-
# calculated once based on the output from the encoder and then cached
540-
# in KV cache.
541-
if (
542-
self.kv_sharing_target_layer_name is None
543-
and key is not None
544-
and value is not None
545-
):
546-
# Reshape the input keys and values and store them in the cache.
547-
# Skip this if sharing KV cache with an earlier attention layer.
548-
# NOTE(woosuk): Here, key and value are padded while slot_mapping is
549-
# not padded. However, we don't need to do key[:num_actual_tokens]
550-
# and value[:num_actual_tokens] because the reshape_and_cache_flash
551-
# op uses the slot_mapping's shape to determine the number of
552-
# actual tokens.
553-
reshape_and_cache_flash(
554-
key,
555-
value,
556-
key_cache,
557-
value_cache,
558-
attn_metadata.slot_mapping,
559-
self.kv_cache_dtype,
560-
layer._k_scale,
561-
layer._v_scale,
562-
)
563-
564568
if not attn_metadata.use_cascade:
565569
cu_seqlens_q = attn_metadata.query_start_loc
566570
seqused_k = attn_metadata.seq_lens
@@ -606,8 +610,8 @@ def forward(
606610
q_descale=layer._q_scale.expand(descale_shape),
607611
k_descale=layer._k_scale.expand(descale_shape),
608612
v_descale=layer._v_scale.expand(descale_shape),
609-
num_splits=attn_metadata.max_num_splits,
610-
s_aux=None, ### self.sinks is support in FA3
613+
num_splits=0, # FlagGems does not support num_splits > 0
614+
s_aux=None,
611615
)
612616
return output
613617

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Copyright (c) 2026 BAAI. All rights reserved.
2+
3+
"""
4+
Thead backend for vllm-plugin-FL dispatch.
5+
6+
This backend provides operator implementations for T-Head PPU accelerators.
7+
"""
8+
9+
from .thead import TheadBackend
10+
11+
__all__ = ["TheadBackend"]
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
"""Copyright (c) 2026 BAAI. All rights reserved."""
2+
3+
from .attention import TheadFlashAttentionBackend, TheadFlashAttentionImpl
4+
5+
__all__ = ["TheadFlashAttentionBackend", "TheadFlashAttentionImpl"]

0 commit comments

Comments
 (0)