所有调用点都在这一个文件里(ascend/conn.py 是另一个后端,逻辑相同)。梳理如下:


_transfer_data 调用全景

_transfer_data 是底层 RDMA 传输的统一入口,上层按传输的数据种类分成 4 类调用:


1. KV Cache 正常传输(_send_kvcache_generic,行 669 / 676)

触发路径: send_kvcache_send_kvcache_generic(标准 MHA/MLA) send_kvcache_hisparse_send_kvcache_generic(HiSparse token 粒度) maybe_send_extra 里 SWA/NSA state → _send_kvcache_generic

两条代码路径:

路径行号条件行为
process_layer669enable_custom_mem_pool=True每层独立提交线程池,并发调 _transfer_data
process_layers676默认路径把所有层的 transfer_blocks 合并成一个大 batch,单次调 _transfer_data

传的内容: prefill KV pool → decode KV pool,以 page 为粒度做地址映射(prefill_kv_indicesdst_kv_indices)。


2. Staging Bulk 传输(send_kvcache_staged,行 557)

触发路径: _do_staging_transferstaging_strategy.transfersend_kvcache_staged

条件: prefill/decode TP size 不同 + staging buffer 启用时。

传的内容: prefill 先把多层 KV gather 到本地 CPU staging buffer,再用单次 bulk RDMA 把整个 staging buffer 打过去(staging_buffer.get_ptr()dst_staging_ptr + rank_offset,大小 per_rank_bytes)。是所有调用里 block 数最少(只有 1 个)但单块最大的。


3. Auxiliary Data 传输(send_aux,行 907)

触发路径: transfer_workeris_last_chunk=True 时 → send_aux(RDMA 路径,NVLINK 时走 TCP fallback)

传的内容: prefill aux pool(如 attention metadata、decode 需要的 attention output)→ decode aux pool,每个 buffer 各传一条 transfer_block。每次请求只在最后一个 chunk 触发一次。


4. Mamba State 传输(_send_mamba_state 行 1064 / _send_mamba_state_slice 行 1150)

触发路径: maybe_send_extra(state_type == “mamba”)→ 两者之一

方法行号条件行为
_send_mamba_state1064prefill/decode TP size 相同整段 state 直传,每个 tensor 一个 block
_send_mamba_state_slice1150prefill/decode TP size 不同按第 3 维(conv_dim/tp 或 num_heads/tp)切片,只传本 rank 负责的部分

传的内容: Mamba 的 conv_state 和 temporal_state,只有单个 state index(assert 了 len==1)。


总结

_transfer_data
├── KV Cache 主体     send_kvcache / send_kvcache_hisparse / SWA·NSA state
│   ├── per-layer 并发(custom_mem_pool)     process_layer   ×N 层
│   └── all-layer 合批(默认)               process_layers  ×1
├── Staging Bulk      send_kvcache_staged     ×1 超大块(gather 后整段打)
├── Aux Data          send_aux(RDMA 路径)   ×每个 aux buffer 一块
└── Mamba State       _send_mamba_state       ×每个 state tensor 一块
                      _send_mamba_state_slice  ×每个 tensor 的 TP 切片

send_kvcache_slice 是个例外——它绕开了 _transfer_data,直接调 engine.batch_transfer_sync,因为它要做 per-token、per-head 的细粒度切片,不走统一封装。