Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions python/sglang/srt/managers/schedule_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,10 @@ def __init__(
self.can_run_list = []
self.preempt_list = []
self.new_chunked_req = None
# Continuation chunks of an already-running chunked req. Their prefix
# was credited to log_hit_tokens on the first chunk, so per-tier
# cached-token stats must not count them again.
self.continuation_chunk_reqs = []
self.log_hit_tokens = 0
self.reprocessed_log_hit_tokens = 0
# TODO(lsyin): report the real input tokens excluding page alignment
Expand Down Expand Up @@ -698,6 +702,7 @@ def add_chunked_req(self, req: Req):
req.set_extend_input_len(min(req.extend_input_len, _rem_tokens))
req.fill_ids = req.fill_ids[: len(req.prefix_indices) + req.extend_input_len]
self.can_run_list.append(req)
self.continuation_chunk_reqs.append(req)
self._update_prefill_budget(
0,
req.extend_input_len,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ class PrefillStats:
new_token_ratio: float
num_running_reqs: QueueCount
num_new_seqs: int # len(can_run_list)

# Detailed prefix-cache hit split.
# log_hit_tokens should equal:
# log_hit_tokens_device + log_hit_tokens_host + log_hit_tokens_storage
# when storage accounting is enabled. Without L3 storage, storage is 0.
log_hit_tokens_device: int = 0
log_hit_tokens_host: int = 0
log_hit_tokens_storage: int = 0

reprocessed_log_input_tokens: int = 0
reprocessed_log_hit_tokens: int = 0
num_pending_tokens: int = 0
Expand All @@ -72,11 +81,30 @@ def from_adder(
enable_priority_scheduling: bool = False,
num_pending_tokens: int = 0,
):
# Skip continuation chunks of a chunked prefill: their prefix was
# already credited (to both log_hit_tokens and the per-tier split) on
# the first chunk, and re-reading req.cached_tokens_* here would count
# the same hit once per chunk.
continuation_reqs = getattr(adder, "continuation_chunk_reqs", [])
split_reqs = [req for req in adder.can_run_list if req not in continuation_reqs]
log_hit_tokens_device = sum(
getattr(req, "cached_tokens_device", 0) for req in split_reqs
)
log_hit_tokens_host = sum(
getattr(req, "cached_tokens_host", 0) for req in split_reqs
)
log_hit_tokens_storage = sum(
getattr(req, "cached_tokens_storage", 0) for req in split_reqs
)

return cls(
log_input_tokens=adder.log_input_tokens,
log_hit_tokens=adder.log_hit_tokens,
reprocessed_log_input_tokens=adder.reprocessed_log_input_tokens,
reprocessed_log_hit_tokens=adder.reprocessed_log_hit_tokens,
log_hit_tokens_device=log_hit_tokens_device,
log_hit_tokens_host=log_hit_tokens_host,
log_hit_tokens_storage=log_hit_tokens_storage,
new_token_ratio=adder.new_token_ratio,
num_running_reqs=QueueCount.from_reqs(
running_reqs, enable_priority_scheduling
Expand Down Expand Up @@ -523,11 +551,25 @@ def report_prefill_stats(
)
iter_msg = f" [{batch_iter}]" if LOG_FORWARD_ITERS else ""

cache_split_msg = (
f"#cached-token-device: {prefill_stats.log_hit_tokens_device}, "
f"#cached-token-host: {prefill_stats.log_hit_tokens_host}, "
)

if (
getattr(self.scheduler, "enable_hicache_storage", False)
or prefill_stats.log_hit_tokens_storage > 0
):
cache_split_msg += (
f"#cached-token-storage: {prefill_stats.log_hit_tokens_storage}, "
)

msg = (
f"Prefill batch{iter_msg}, "
f"#new-seq: {prefill_stats.num_new_seqs}, "
f"#new-token: {prefill_stats.log_input_tokens}, "
f"#cached-token: {prefill_stats.log_hit_tokens}, "
f"{cache_split_msg}"
f"{token_usage_msg}"
f"#running-req: {prefill_stats.num_running_reqs.total}, "
f"#queue-req: {len(self.scheduler.waiting_queue)}, "
Expand Down
Loading