Measure prefill busy time between launches (#33595)
This commit is contained in:
@@ -1979,6 +1979,7 @@ class ScheduleBatch(ScheduleBatchDisaggregationDecodeMixin):
|
|||||||
prefill_stats: Optional[PrefillStats] = None
|
prefill_stats: Optional[PrefillStats] = None
|
||||||
forward_iter: Optional[int] = None
|
forward_iter: Optional[int] = None
|
||||||
launch_ts: Optional[float] = None
|
launch_ts: Optional[float] = None
|
||||||
|
after_idle_gap: bool = False
|
||||||
|
|
||||||
# === GPU tensors crossing to ForwardBatch (clone targets for stream isolation) ===
|
# === GPU tensors crossing to ForwardBatch (clone targets for stream isolation) ===
|
||||||
# Batched arguments to model runner
|
# Batched arguments to model runner
|
||||||
@@ -3201,6 +3202,7 @@ class ScheduleBatch(ScheduleBatchDisaggregationDecodeMixin):
|
|||||||
fpm_start_time=self.fpm_start_time,
|
fpm_start_time=self.fpm_start_time,
|
||||||
forward_iter=self.forward_iter,
|
forward_iter=self.forward_iter,
|
||||||
launch_ts=self.launch_ts,
|
launch_ts=self.launch_ts,
|
||||||
|
after_idle_gap=self.after_idle_gap,
|
||||||
extend_num_tokens=self.extend_num_tokens,
|
extend_num_tokens=self.extend_num_tokens,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -335,7 +335,7 @@ TEST_RETRACT_INTERVAL = envs.SGLANG_TEST_RETRACT_INTERVAL.get()
|
|||||||
TEST_RETRACT_NO_PREFILL_BS = envs.SGLANG_TEST_RETRACT_NO_PREFILL_BS.get()
|
TEST_RETRACT_NO_PREFILL_BS = envs.SGLANG_TEST_RETRACT_NO_PREFILL_BS.get()
|
||||||
|
|
||||||
|
|
||||||
DECODE_STEP_MAX_US = 2_000_000
|
STEP_MAX_US = 2_000_000
|
||||||
|
|
||||||
|
|
||||||
def _accumulate_decode_moment(
|
def _accumulate_decode_moment(
|
||||||
@@ -1705,6 +1705,7 @@ class Scheduler(
|
|||||||
self.process_batch_result(batch, result)
|
self.process_batch_result(batch, result)
|
||||||
else:
|
else:
|
||||||
# When the server is idle, do self-check and re-init some states.
|
# When the server is idle, do self-check and re-init some states.
|
||||||
|
self._sched_idled = True
|
||||||
self.on_idle()
|
self.on_idle()
|
||||||
|
|
||||||
# Update last_batch
|
# Update last_batch
|
||||||
@@ -1766,6 +1767,7 @@ class Scheduler(
|
|||||||
self.result_queue.append((batch.copy(), batch_result))
|
self.result_queue.append((batch.copy(), batch_result))
|
||||||
else:
|
else:
|
||||||
batch_result = None
|
batch_result = None
|
||||||
|
self._sched_idled = True
|
||||||
|
|
||||||
# Process the last batch
|
# Process the last batch
|
||||||
if self.last_batch:
|
if self.last_batch:
|
||||||
@@ -2044,7 +2046,8 @@ class Scheduler(
|
|||||||
self.total_prefill_uncached_tokens = 0
|
self.total_prefill_uncached_tokens = 0
|
||||||
self.total_prefill_busy_us = 0
|
self.total_prefill_busy_us = 0
|
||||||
self.decode_moment_totals: list[float] = [0.0] * 6
|
self.decode_moment_totals: list[float] = [0.0] * 6
|
||||||
self._prev_decode_launch_ts: Optional[float] = None
|
self._prev_step: Optional[Tuple[int, float, bool]] = None
|
||||||
|
self._sched_idled = False
|
||||||
self.load_inquirer = SchedulerLoadInquirer(
|
self.load_inquirer = SchedulerLoadInquirer(
|
||||||
disaggregation_mode=self.disaggregation_mode,
|
disaggregation_mode=self.disaggregation_mode,
|
||||||
ps=self.ps,
|
ps=self.ps,
|
||||||
@@ -3534,6 +3537,8 @@ class Scheduler(
|
|||||||
self.forward_ct += 1
|
self.forward_ct += 1
|
||||||
batch.forward_iter = self.forward_ct
|
batch.forward_iter = self.forward_ct
|
||||||
batch.launch_ts = time.monotonic()
|
batch.launch_ts = time.monotonic()
|
||||||
|
batch.after_idle_gap = self._sched_idled
|
||||||
|
self._sched_idled = False
|
||||||
|
|
||||||
if self.scripted_scheduler_hook is not None:
|
if self.scripted_scheduler_hook is not None:
|
||||||
self.scripted_scheduler_hook.on_run_batch(batch)
|
self.scripted_scheduler_hook.on_run_batch(batch)
|
||||||
@@ -3853,23 +3858,28 @@ class Scheduler(
|
|||||||
return
|
return
|
||||||
if all(is_health_check_generate_req(req) for req in batch.reqs):
|
if all(is_health_check_generate_req(req) for req in batch.reqs):
|
||||||
return
|
return
|
||||||
|
prev = self._prev_step
|
||||||
|
self._prev_step = (batch.forward_iter, batch.launch_ts, is_prefill)
|
||||||
|
# An idle pass keeps forward_iter contiguous (forward_ct advances in run_batch).
|
||||||
|
if prev is None or batch.after_idle_gap:
|
||||||
|
return
|
||||||
|
prev_iter, prev_ts, prev_is_prefill = prev
|
||||||
|
if prev_iter + 1 != batch.forward_iter or prev_is_prefill != is_prefill:
|
||||||
|
return
|
||||||
|
step_us = int((batch.launch_ts - prev_ts) * 1e6)
|
||||||
|
if not 0 < step_us < STEP_MAX_US:
|
||||||
|
return
|
||||||
if is_prefill:
|
if is_prefill:
|
||||||
# Busy span = run_batch entry -> result processed.
|
self.total_prefill_busy_us += step_us
|
||||||
span_us = int((time.monotonic() - batch.launch_ts) * 1e6)
|
|
||||||
self.total_prefill_busy_us += span_us
|
|
||||||
self.total_prefill_uncached_tokens += batch.extend_num_tokens
|
self.total_prefill_uncached_tokens += batch.extend_num_tokens
|
||||||
else:
|
else:
|
||||||
batch_size = len(batch.reqs)
|
batch_size = len(batch.reqs)
|
||||||
if self._prev_decode_launch_ts is not None:
|
_accumulate_decode_moment(
|
||||||
step_us = int((batch.launch_ts - self._prev_decode_launch_ts) * 1e6)
|
self.decode_moment_totals,
|
||||||
if 0 < step_us < DECODE_STEP_MAX_US:
|
batch_size,
|
||||||
_accumulate_decode_moment(
|
step_us,
|
||||||
self.decode_moment_totals,
|
batch_size + result.num_correct_drafts,
|
||||||
batch_size,
|
)
|
||||||
step_us,
|
|
||||||
batch_size + result.num_correct_drafts,
|
|
||||||
)
|
|
||||||
self._prev_decode_launch_ts = batch.launch_ts
|
|
||||||
|
|
||||||
def maybe_send_health_check_signal(self):
|
def maybe_send_health_check_signal(self):
|
||||||
if self.return_health_check_ipcs:
|
if self.return_health_check_ipcs:
|
||||||
|
|||||||
Reference in New Issue
Block a user