虽然全异步能够解决skewness bubble,然而随着训练的进行,rollout worker间的请求高低优先级特性可能发生改变,部分rollout worker上的高优先请求可能由于kvcache压力而被迫排队,部分rollout worker上可能都是低优先级的kvcache,因此,需要runtime的在rollout worker间迁移高优先请求以及其对应计算的kvcache,本文详解具体的实现;
Sglang runtime KVCache migration
首先在server_args中新增—enable-kv-migration,来判断是否允许开启kvcache迁移;
# KV cache migration over HTTP (peer-to-peer between sglang servers)
enable_kv_migration: bool = False
kv_migration_watchdog_timeout: float = 60.0随后新增和runtime kvcache迁移相关的请求的ReqInput和ReqOutput
@dataclass
class GetTransferSessionInfoReqInput(BaseReq):
pass
@dataclass
class GetTransferSessionInfoReqOutput(BaseReq):
success: bool
tp_rank: int = -1
pp_rank: int = -1
session_id: str = ""
host_kv_data_ptrs: List[int] = field(default_factory=list)
host_kv_item_lens: List[int] = field(default_factory=list)
page_size: int = 0
message: str = ""
@dataclass
class GetRequestExtraTokenSizeReqInput(BaseReq):
input_ids: List[int]
extra_key: Optional[str] = None
@dataclass
class GetRequestExtraTokenSizeReqOutput(BaseReq):
success: bool
extra_token_size: int = 0
matched_token_size: int = 0
total_token_size: int = 0
message: str = ""
@dataclass
class AllocateTokenForTransferReqInput(BaseReq):
input_ids: List[int]
extra_key: Optional[str] = None
extra_token_size: int = 0
migration_id: Optional[str] = None # set by HTTP layer to share id across ranks
@dataclass
class AllocateTokenForTransferReqOutput(BaseReq):
success: bool
migration_id: str = ""
tp_rank: int = -1
pp_rank: int = -1
kv_indices: List[int] = field(default_factory=list)
message: str = ""
@dataclass
class TransferRequestKVCacheTarget:
tp: int
pp: int
session_id: str
host_kv_data_ptrs: List[int]
host_kv_item_lens: List[int]
kv_indices: List[int]
@dataclass
class TransferRequestKVCacheReqInput(BaseReq):
input_ids: List[int]
extra_key: Optional[str] = None
matched_token_size: int = 0
extra_token_size: int = 0
target_per_rank: List[TransferRequestKVCacheTarget] = field(default_factory=list)
@dataclass
class TransferRequestKVCacheReqOutput(BaseReq):
success: bool
message: str = ""
@dataclass
class CommitTransferRequestKVCacheReqInput(BaseReq):
migration_id: str = ""
@dataclass
class CommitTransferRequestKVCacheReqOutput(BaseReq):
success: bool
matched_after_commit: int = 0
message: str = ""随后在python/sglang/srt/kv_migration/io_types.py中新增迁移相关的class类,新增类PendingMigration和TransferTarge,分别指示实际inflight的migration操作,放在target端,用于await/commit或者watchdog后释放,TransferTarget代表peer rank的metadata,包括tp/pp信息,session id,分配的host_kv_data_ptrs和kv_indices;
@dataclass
class PendingMigration:
"""In-flight migration on the target side, awaiting /commit or watchdog."""
input_ids: List[int]
extra_key: Optional[str]
full_key: "RadixKey"
matched_aligned: int
matched_node: "TreeNode"
host_locked_nodes: List["TreeNode"]
host_tail_indices: "torch.Tensor"
created_at: float = field(default_factory=time.monotonic)
@dataclass
class TransferTarget:
"""One peer rank's metadata for /transfer_request_kvcache."""
tp: int
pp: int
session_id: str
host_kv_data_ptrs: List[int]
host_kv_item_lens: List[int]
kv_indices: List[int]随后再来看定义在srt/kv_migration/tree_helpers.py中定义的一些函数,首先是collect_host_pages函数,其中,从root_node开始,不断的匹配key,将中间的所有page添加到pages列表中,并把沿途的TreeNode放入path_nodes中,其中,如果遍历到某个node时,发现