[core] WAR barrier for overlap schedule buffer writes, without fwd occupancy cost (#26380)
This commit is contained in:
@@ -1621,6 +1621,9 @@ class SchedulerDisaggregationDecodeMixin:
|
|||||||
if self._engine_paused:
|
if self._engine_paused:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# WAR barrier: this iter's schedule writes to shared GPU buffers wait for prev forward's reads.
|
||||||
|
self.schedule_stream.wait_stream(self.forward_stream)
|
||||||
|
|
||||||
# Get the next batch to run
|
# Get the next batch to run
|
||||||
batch = self.get_next_disagg_decode_batch_to_run()
|
batch = self.get_next_disagg_decode_batch_to_run()
|
||||||
self.cur_batch = batch
|
self.cur_batch = batch
|
||||||
|
|||||||
@@ -436,6 +436,9 @@ class SchedulerDisaggregationPrefillMixin:
|
|||||||
if self._engine_paused:
|
if self._engine_paused:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# WAR barrier on shared GPU buffers (req_to_token_pool / SWA mapping).
|
||||||
|
self.schedule_stream.wait_stream(self.forward_stream)
|
||||||
|
|
||||||
# Get the next batch to run
|
# Get the next batch to run
|
||||||
batch = self.get_next_disagg_prefill_batch_to_run()
|
batch = self.get_next_disagg_prefill_batch_to_run()
|
||||||
self.cur_batch = batch
|
self.cur_batch = batch
|
||||||
|
|||||||
@@ -105,6 +105,16 @@ class FutureMap:
|
|||||||
self.new_seq_lens_buf = torch.empty(
|
self.new_seq_lens_buf = torch.empty(
|
||||||
(self.req_pool_size,), dtype=torch.int64, device=self.device
|
(self.req_pool_size,), dtype=torch.int64, device=self.device
|
||||||
)
|
)
|
||||||
|
# Pinned host copy of new_seq_lens_buf + private stream for fwd-prepare
|
||||||
|
# D2H pulls (gated only on publish, off the schedule stream).
|
||||||
|
if _is_cuda or _is_hip:
|
||||||
|
self.new_seq_lens_cpu_pinned = torch.empty(
|
||||||
|
(self.req_pool_size,), dtype=torch.int64, pin_memory=True
|
||||||
|
)
|
||||||
|
self.fwd_prepare_d2h_stream = torch.get_device_module(self.device).Stream()
|
||||||
|
else:
|
||||||
|
self.new_seq_lens_cpu_pinned = None
|
||||||
|
self.fwd_prepare_d2h_stream = None
|
||||||
if self.spec_algo.is_some():
|
if self.spec_algo.is_some():
|
||||||
self._forward_buf_initialized = False
|
self._forward_buf_initialized = False
|
||||||
|
|
||||||
@@ -194,9 +204,20 @@ class FutureMap:
|
|||||||
return
|
return
|
||||||
if self.publish_ready is not None:
|
if self.publish_ready is not None:
|
||||||
self.publish_ready.wait()
|
self.publish_ready.wait()
|
||||||
new_seq_lens = self.new_seq_lens_buf[fi]
|
batch.seq_lens = self.new_seq_lens_buf[fi]
|
||||||
batch.seq_lens = new_seq_lens
|
|
||||||
batch.seq_lens_cpu = new_seq_lens.cpu()
|
if self.fwd_prepare_d2h_stream is None or self.publish_ready is None:
|
||||||
|
batch.seq_lens_cpu = batch.seq_lens.cpu() # bootstrap / non-CUDA
|
||||||
|
batch.seq_lens_sum = int(batch.seq_lens_cpu.sum())
|
||||||
|
return
|
||||||
|
|
||||||
|
# seq_lens_cpu off the schedule stream: D2H the relay buf on a private
|
||||||
|
# stream (gated on publish), host-select via req_pool_indices_cpu.
|
||||||
|
self.fwd_prepare_d2h_stream.wait_event(self.publish_ready)
|
||||||
|
with torch.get_device_module(self.device).stream(self.fwd_prepare_d2h_stream):
|
||||||
|
self.new_seq_lens_cpu_pinned.copy_(self.new_seq_lens_buf, non_blocking=True)
|
||||||
|
self.fwd_prepare_d2h_stream.synchronize()
|
||||||
|
batch.seq_lens_cpu = self.new_seq_lens_cpu_pinned[batch.req_pool_indices_cpu]
|
||||||
batch.seq_lens_sum = int(batch.seq_lens_cpu.sum())
|
batch.seq_lens_sum = int(batch.seq_lens_cpu.sum())
|
||||||
|
|
||||||
def publish(self, future_indices: torch.Tensor, new_seq_lens: torch.Tensor) -> None:
|
def publish(self, future_indices: torch.Tensor, new_seq_lens: torch.Tensor) -> None:
|
||||||
|
|||||||
@@ -1408,6 +1408,9 @@ class Scheduler(
|
|||||||
if self._engine_paused:
|
if self._engine_paused:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# WAR barrier: this iter's schedule writes to shared GPU buffers wait for prev forward's reads.
|
||||||
|
self.schedule_stream.wait_stream(self.forward_stream)
|
||||||
|
|
||||||
# Get the next batch to run
|
# Get the next batch to run
|
||||||
batch = self.get_next_batch_to_run()
|
batch = self.get_next_batch_to_run()
|
||||||
self.cur_batch = batch
|
self.cur_batch = batch
|
||||||
|
|||||||
@@ -142,21 +142,23 @@ class EagleDraftInputV2Mixin:
|
|||||||
cur_kv_lens_cpu = torch.tensor(cur_kv_lens, dtype=torch.int32, device="cpu")
|
cur_kv_lens_cpu = torch.tensor(cur_kv_lens, dtype=torch.int32, device="cpu")
|
||||||
nxt_kv_lens_cpu = torch.tensor(nxt_kv_lens, dtype=torch.int32, device="cpu")
|
nxt_kv_lens_cpu = torch.tensor(nxt_kv_lens, dtype=torch.int32, device="cpu")
|
||||||
|
|
||||||
|
# non_blocking H2D: a blocking .to() syncs the schedule stream, which the WAR
|
||||||
|
# barrier has chained to the prev forward -> host stalls a full forward.
|
||||||
|
cur_kv_lens_device = cur_kv_lens_cpu.to(device=batch.device, non_blocking=True)
|
||||||
|
nxt_kv_lens_device = nxt_kv_lens_cpu.to(device=batch.device, non_blocking=True)
|
||||||
if page_size == 1:
|
if page_size == 1:
|
||||||
out_cache_loc = alloc_token_slots(batch.tree_cache, num_needed_tokens)
|
out_cache_loc = alloc_token_slots(batch.tree_cache, num_needed_tokens)
|
||||||
else:
|
else:
|
||||||
cur_kv_lens = cur_kv_lens_cpu.to(device=batch.device)
|
|
||||||
nxt_kv_lens = nxt_kv_lens_cpu.to(device=batch.device)
|
|
||||||
last_loc = get_last_loc(
|
last_loc = get_last_loc(
|
||||||
batch.req_to_token_pool.req_to_token,
|
batch.req_to_token_pool.req_to_token,
|
||||||
batch.req_pool_indices,
|
batch.req_pool_indices,
|
||||||
cur_kv_lens,
|
cur_kv_lens_device,
|
||||||
)
|
)
|
||||||
out_cache_loc = alloc_paged_token_slots_extend(
|
out_cache_loc = alloc_paged_token_slots_extend(
|
||||||
batch.tree_cache,
|
batch.tree_cache,
|
||||||
cur_kv_lens,
|
cur_kv_lens_device,
|
||||||
cur_kv_lens_cpu,
|
cur_kv_lens_cpu,
|
||||||
nxt_kv_lens,
|
nxt_kv_lens_device,
|
||||||
nxt_kv_lens_cpu,
|
nxt_kv_lens_cpu,
|
||||||
last_loc,
|
last_loc,
|
||||||
num_needed_tokens,
|
num_needed_tokens,
|
||||||
@@ -165,8 +167,8 @@ class EagleDraftInputV2Mixin:
|
|||||||
assign_req_to_token_pool_func(
|
assign_req_to_token_pool_func(
|
||||||
batch.req_pool_indices,
|
batch.req_pool_indices,
|
||||||
batch.req_to_token_pool.req_to_token,
|
batch.req_to_token_pool.req_to_token,
|
||||||
cur_kv_lens_cpu.to(device=batch.device),
|
cur_kv_lens_device,
|
||||||
nxt_kv_lens_cpu.to(device=batch.device),
|
nxt_kv_lens_device,
|
||||||
out_cache_loc,
|
out_cache_loc,
|
||||||
bs,
|
bs,
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user