Harden the affinity wiring per opus review (F-1, F-2)

- A chunked-led batch now seeds affinity_batch_warm_led from the CHUNK's
  class instead of the first loop candidate: a 65536 first chunk is
  cold-led (later colds are free density, caps bound them); latching
  from a warm follower inverted cold-led-admits-everything and could
  spuriously STOP the scan, under-filling the forward.
- The policy additionally requires no LoRA and no L3 hicache-storage:
  their pre-classification continues make "first classified candidate"
  drift from the true FCFS head, mis-routing the defer accounting.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-12 08:07:36 +00:00
parent 6a1e862f48
commit cf46defddd

View File

@@ -2572,12 +2572,29 @@ class Scheduler(
affinity_on = (
envs.SGLANG_CP_PREFILL_AFFINITY_GROUP.get()
and not self.enable_priority_scheduling
# The pre-classification continues (LoRA compatibility, L3
# prefetch pending) would make "first classified candidate" drift
# from the true FCFS head and mis-route the defer accounting —
# the policy is only exact (and only validated) without them.
and not self.enable_lora
and not self.enable_hicache_storage
and self.server_args.enable_cp_shared_kv_prefill_bs_gt1
and is_nsa_prefill_cp_in_seq_split()
)
affinity_window_used = 0
affinity_head_pending = True # first classified candidate = FCFS head
affinity_batch_warm_led: Optional[bool] = None
if affinity_on and adder._chunked_req_in_batch is not None:
# A chunked-led batch must carry the CHUNK's class: a 65536 first
# chunk is cold-led (further colds are free density and the caps
# bound them); a tail chunk over a big cached prefix is warm-led.
# Latching from the first loop candidate instead would invert
# cold-led-admits-everything and spuriously STOP the scan.
chunked = adder._chunked_req_in_batch
affinity_batch_warm_led = (
len(chunked.prefix_indices)
+ int(getattr(chunked, "host_hit_length", 0) or 0)
) >= int(envs.SGLANG_CP_PREFILL_AFFINITY_WARM_FLOOR.get())
for req in self.waiting_queue:
if self.enable_lora and req.lora_id not in running_loras:
@@ -2642,6 +2659,9 @@ class Scheduler(
- (1 if adder._chunked_req_in_batch is not None else 0)
== 0
),
# None = nothing admitted yet; only reachable together
# with batch_empty_for_affinity=True (which decides
# first), so False is never read as a real class here.
batch_warm_led=bool(affinity_batch_warm_led),
is_head=is_head,
head_defer_count=req.affinity_defer_count,