Add routing key based schedule policy (#16840)

This commit is contained in:
fzyzcjy
2026-01-10 10:16:23 +08:00
committed by GitHub
parent 15da3061bc
commit 1f0ea4f958
5 changed files with 293 additions and 5 deletions

View File

@@ -1,6 +1,12 @@
from __future__ import annotations
import logging
from sglang.srt.managers.prefill_delayer import PrefillDelayerSinglePassExecutor
from sglang.srt.utils import get_bool_env_var
_ROUTING_KEY_POLICY_DEBUG_LOG = get_bool_env_var("SGLANG_ROUTING_KEY_POLICY_DEBUG_LOG")
logger = logging.getLogger(__name__)
# Copyright 2023-2024 SGLang Team
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,7 +25,7 @@ from sglang.srt.managers.prefill_delayer import PrefillDelayerSinglePassExecutor
import os
import random
from collections import defaultdict
from collections import Counter, defaultdict
from contextlib import contextmanager
from enum import Enum, auto
from typing import TYPE_CHECKING, Dict, List, Optional, Set, Union
@@ -78,6 +84,7 @@ class CacheAgnosticPolicy(Enum):
FCFS = "fcfs" # first come first serve
LOF = "lof" # longest output first
RANDOM = "random"
ROUTING_KEY = "routing-key" # prioritize by routing key frequency in running batch
class SchedulePolicy:
@@ -101,7 +108,9 @@ class SchedulePolicy:
# It is used to find the matching prefix for in-batch prefix caching.
self.waiting_queue_radix_tree = RadixCache.create_simulated()
def calc_priority(self, waiting_queue: List[Req]) -> bool:
def calc_priority(
self, waiting_queue: List[Req], running_batch: Optional[ScheduleBatch] = None
) -> bool:
if self.policy == CacheAgnosticPolicy.FCFS:
if self.enable_priority_scheduling:
SchedulePolicy._sort_by_priority_and_fcfs(
@@ -136,6 +145,9 @@ class SchedulePolicy:
)
elif policy == CacheAgnosticPolicy.RANDOM:
SchedulePolicy._sort_randomly(waiting_queue)
elif policy == CacheAgnosticPolicy.ROUTING_KEY:
if running_batch is not None:
SchedulePolicy._sort_by_routing_key(waiting_queue, running_batch)
else:
raise ValueError(f"Unknown CacheAgnostic Policy: {policy=}")
return prefix_computed
@@ -288,6 +300,39 @@ class SchedulePolicy:
)
)
@staticmethod
def _sort_by_routing_key(
waiting_queue: List[Req], running_batch: ScheduleBatch
) -> None:
"""Sorts waiting queue by routing key frequency in running batch."""
routing_key_counts = Counter(
r.routing_key for r in running_batch.reqs if r.routing_key
)
if _ROUTING_KEY_POLICY_DEBUG_LOG:
waiting_keys_before = [r.routing_key for r in waiting_queue]
logger.info(
f"routing_key_counts={dict(routing_key_counts)}, "
f"waiting_keys_before={waiting_keys_before}"
)
if not routing_key_counts:
return
def sort_key(req: Req):
key = req.routing_key
if key and key in routing_key_counts:
count = routing_key_counts[key]
return (0, -count, key)
else:
return (1, 0, key or "")
waiting_queue.sort(key=sort_key)
if _ROUTING_KEY_POLICY_DEBUG_LOG:
waiting_keys_after = [r.routing_key for r in waiting_queue]
logger.info(f"waiting_keys_after={waiting_keys_after}")
@staticmethod
def _calc_weight(cur_node: TreeNode, node_to_weight: Dict[TreeNode, int]) -> None:
for child in cur_node.children.values():

View File

@@ -1433,6 +1433,7 @@ class Scheduler(
metrics_collector=(
self.metrics_collector if self.enable_metrics else None
),
routing_key=recv_req.routing_key,
http_worker_ipc=recv_req.http_worker_ipc,
dllm_config=self.dllm_config,
)
@@ -1907,7 +1908,7 @@ class Scheduler(
self.tree_cache.check_hicache_events()
# Get priority queue
self.policy.calc_priority(self.waiting_queue)
self.policy.calc_priority(self.waiting_queue, self.running_batch)
if TEST_RETRACT and running_bs > TEST_RETRACT_NO_PREFILL_BS:
# If we are testing retraction and the running batch size exceeds

View File

@@ -2837,7 +2837,15 @@ class ServerArgs:
"--schedule-policy",
type=str,
default=ServerArgs.schedule_policy,
choices=["lpm", "random", "fcfs", "dfs-weight", "lof", "priority"],
choices=[
"lpm",
"random",
"fcfs",
"dfs-weight",
"lof",
"priority",
"routing-key",
],
help="The scheduling policy of the requests.",
)
parser.add_argument(