[Disagg][NIXL] Fix heterogeneous attn-TP KV transfer for replicated GQA heads (NIXL_ERR_NOT_FOUND) (#31968)

This commit is contained in:
siweil
2026-07-29 14:13:23 +08:00
committed by GitHub
parent ef6c07008b
commit 9bdbb180b1
2 changed files with 137 additions and 6 deletions
+27 -6
View File
@@ -791,12 +791,33 @@ class NixlKVManager(CommonKVManager):
else:
# One prefill rank feeds multiple decode ranks: interleave num_groups
# head-groups in the src dlist so each decode rank picks its slice.
dst_tp_rank_in_group = decode_kv_args.decode_tp_rank % decode_tp_size
num_groups = decode_tp_size // prefill_tp_size
num_heads_to_send = dst_heads_per_rank
src_head_start = (
dst_tp_rank_in_group * dst_heads_per_rank
) % src_heads_per_rank
#
# Under GQA the decode side can have MORE attn-TP ranks than there are
# KV heads (decode_tp_size > total_kv_heads). In that case consecutive
# decode ranks replicate a shared KV head, so the src dlist must
# interleave one group per UNIQUE source head-slice, not one per decode
# rank -- otherwise it addresses past the registered KV region and
# prep_xfer_dlist raises NIXL_ERR_NOT_FOUND.
#
# Reuse the shared replicated-KV head map (integer division under
# replication, not modulo) that the mooncake backend already relies
# on, so the two backends stay in sync.
from sglang.srt.disaggregation.common.staging_buffer import (
compute_head_slice_params,
)
src_head_start, num_heads_to_send, _, _ = compute_head_slice_params(
prefill_tp_size,
decode_tp_size,
self.kv_args.engine_rank,
decode_kv_args.decode_tp_rank,
total_kv_heads,
)
# num_groups (distinct head-groups packed in one prefill rank's src
# region) and head_group_idx (this peer's group) are NIXL-specific and
# not returned by the shared helper, so derive them here.
dst_replication = max(1, decode_tp_size // total_kv_heads)
num_groups = decode_tp_size // prefill_tp_size // dst_replication
head_group_idx = src_head_start // dst_heads_per_rank
dst_head_offset = 0