feat: chunked prefill scheduling (bounded, decode-first, opt-in) - #178
feat: chunked prefill scheduling (bounded, decode-first, opt-in)#178drunkcoding wants to merge 14 commits into
Conversation
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
|
Momus plan review: [OKAY] after 3 review rounds. The plan is now standalone and explicitly rejects prefix-cache co-enablement pending reconciliation; revisions are in commit a9b2392. |
|
Independent implementation verification:
PR remains draft for CUDA/FlashInfer review. |
|
Productization findings (full report: The 'client hang' was three stacked defects. Two are general serving-infra bugs, fixed in #189:
After those, whole-prefill generates. But chunked-prefill itself is broken and appears never-run-end-to-end: Recommend: land #189 (infra) here; then complete chunked-prefill separately — align the two KV block budgets and size the FlashInfer workspace for chunked append-attention. |
Description
Implements bounded, opt-in chunked prefill scheduling for MoE-Infinity continuous serving. Active decode rows run every feasible scheduler step while long prefills make fair, bounded progress within the existing per-step token and batch limits. Disabled by default.
Motivation
Whole-prompt prefill admission can stall active decode rows and inflate tail latency. Bounded chunking lets decode keep priority while long prompts advance.
What landed (11 atomic commits)
feat(serving): track partial prefill progress—SequenceData.advance_prefill,committed_kv_tokens, prefill-progress invariants.feat(serving): reserve paged KV incrementally— idempotentensure_sequence_capacity, observable reserved-token count,rollback_sequence_reservation.fix(serving): reject chunk and prefix co-enablement— single validated startup guard (ValueError) across engine +_build_engine_config.fix(serving): unify paged KV storage ownership— canonicalLayeredPagedKVStore(layer-aware standard + FlashInfer tensors) owning export/import/checkpoint/restore;PagedKVCache.set_block_store; swap routed through active storage.feat(serving): carry exact prefill chunk metadata—PrefillChunk, canonicalPagedBatchLengths(query_lengths, query_offsets, context_lengths, kv_seq_lengths), exact chunk slicing, terminal flags.feat(serving): schedule bounded prefills behind decode— decode-first bounded scheduler, round-robin/age fairness, scheduler-owned in-flight leases, transactional commit/rollback.feat(serving): execute partial prefills without sampling— transaction-boundarystep(), terminal-only sampling, progress-only steps, execution/sampling rollback, capability gate, DFlash mid-prompt guard, stats.fix(serving): preserve partial prefill lifecycle state— cancellation no-leak, partial-prefill swap recovery to PREFILL at the same offset (chunked mode only; legacy path unchanged).fix(serving): separate chunk query and KV metadata— FlashInferqo_indptr = query_offsets, page metadata fromkv_seq_lengths; real-Qwen3 detection; CUDA/FlashInfer canary tests.feat(serving): expose experimental chunked prefill— CLI/programmatic controls (--enable-chunked-prefill,--prefill-chunk-size,--prefill-starvation-threshold-steps), disabled-by-default, docs.bench(serving): measure chunked prefill TTFT and TPOT tails— paired disabled/enabled streaming benchmark + CPU aggregation tests + docs (neutral candidate-minus-baseline, no speedup claims).Scope / limitations
Verification (this environment: CUDA present, FlashInfer absent)
196 passed, 2 skipped(skips are CUDA/FlashInfer-only).compileallexit 0;ruff checkclean; LSP diagnostics 0 errors acrossmoe_infinity/serving.Type of Change
Checklist
Post-review fixes
fix(serving): make speculative and disabled paths transaction-safe— oracle spec review found twotransaction_id-handling gaps: (1) unguardedrollback_prefill_step(None)masked real exceptions on the default/decode-only path; (2) DFlash delegation paths ignored the in-flight chunk transaction (stuck sequence ongenerate()failure). Both fixed with RED→GREEN tests;_completed_prefill_transactionsbounded.