fix(dsv4): honor prefill limits and derive SWA capacity - #116
Open
jpezzulli wants to merge 1 commit into
Open
Conversation
Preserve configured DSV4 chunked-prefill limits and keep pool-provided chunk budgets live across in-place cache rebuilds. Derive the minimum DSV4 SWA pool from max prefill, validate expert absolute overrides, price pinned windows consistently, reject truncating geometries, and expose requested/effective/pool-cap/source/reason across startup and every rebuild outcome.
avlp12
pushed a commit
to avlp12/FreeToken
that referenced
this pull request
Aug 25, 2026
Cherry-picked from upstream PR FlashML-org#116 (jpezzulli, FlashML-org/FreeToken@466dee7). Genuinely missing fix, not covered by our FlashML-org#105 (ca94148) or the FlashML-org#101-based df6c340: those two already stopped forcing max_extend_tokens up to max_seq_len, but left _dsv4_window_floor_pages() hard-capped at min(prefill_reach_pages, 8) pages (1024 tokens) regardless of the configured --max-prefill-length. The DSV4 SWA/window pool therefore stayed undersized for any real chunk size, so DSV4PagedKVCache.prefill_chunk_budget silently truncated prefill chunks far below what --max-prefill-length requested, turning one large prompt into many tiny chunks (per-chunk kernel-launch and compressor-carry overhead) -- the likely root cause of our 171-400 tok/s prefill ceiling. This commit adds dsv4_required_swa_pages()/dsv4_prefill_chunk_budget() to kvcache/dsv4_cost_model.py, derives swa_num_pages_override from max_extend_tokens/max_running_req in engine._adjust_config (unless an explicit --swa-num-tokens override is given and is large enough), makes CacheManager.prefill_chunk_budget a live delegation to the pool instead of a construction-time snapshot (stale after in-place cache rebuilds), and adds requested/effective/pool-cap/source/reason reporting through cache_status.py, scheduler.py, api_server.py, cache_report.py, and control_cli.py. Conflicts resolved against our own additions in the same functions: engine/config.py (kept our distributed_timeout=1800.0 alongside the new swa_num_token_override/swa_capacity_source fields), engine/engine.py (kept df6c340's comment explaining why max_extend_tokens is honored), and scheduler/cache.py (kept our host-RAM KV tier attach_host_tier / maybe_flush_host_tier / _host_restore machinery alongside the new live prefill_chunk_budget property). tests/dsv4 + tests/kvcache: 529 passed, 1 skipped. tests/engine/test_cache_budget.py, tests/engine/test_attention_backend_matrix.py, tests/scheduler/test_cache_rebuild.py, tests/server/test_cache_args.py, tests/server/test_rebuild_maintenance.py: 98 passed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #115.
Summary
This fixes two DSV4 prefill correctness defects and makes
--max-prefill-lengththe normal single sizing knob for DSV4:prefill_chunk_budgetfrom the live KV pool so an in-place SWA rebuild cannot leave the scheduler with a stale startup budget;--swa-num-tokensas a validated expert absolute-capacity override;The locally validated
--max-prefill-length 24576configuration is not introduced as a universal default. The existing default remains unchanged; 24,576 is only the value validated on the hardware/checkpoint below.Root causes
max_extend_tokensafter CLI/config resolution.CacheManagercopied the initial pool'sprefill_chunk_budget; DSV4 rebuilds reinitialize pool geometry, so the copy became stale.derived/explicitsource state.Behavior and precedence
For DSV4, startup now computes the minimum usable SWA pages as the concurrent/radix reserve plus twice
ceil(max_prefill / window_page_size), matching the pool's live chunk-budget inverse. That derived absolute window is used consistently by the cost model, page solver, and allocation.--swa-num-tokensremains an expert override. It must be positive, aligned to the resolved SWA page size, no smaller than the capacity required by--max-prefill-length, and no larger than the usable full-history anchor. Generic radix-SWA models retain their existing ratio sizing unless an explicit absolute override is supplied.Live rebuilds recompute the pool budget and the scheduler rereads it. Rebuild replies and all rejection/timeout/preflight paths expose:
requested_prefill_tokenspool_prefill_cap_tokenseffective_prefill_tokensswa_capacity_source(derived,explicit, ornone)prefill_limiting_reasonThe displayed SWA/full ratio is derived from allocated live geometry when an absolute window supersedes the fallback ratio.
Tests
Focused regressions:
Result: 132 passed.
Complete non-slow suite with GPU 0 available:
env CUDA_VISIBLE_DEVICES=0 PYTHONPATH=/opt/freetoken/src/python \ /opt/freetoken/.venv/bin/python -m pytest -q -m "not slow"Result: 1,377 passed, 8 skipped, 11 deselected.
Explicitly not run
slow(large kernel sweeps / real-checkpoint reads) were deliberately deselected.needs_weightsAIME E2E suite was not enabled.tests/e2e/test_cache_rebuild.pyserver test was not run because its required small-model environment was not configured.A real-checkpoint DSV4 serving workload and live rebuild were run manually as described below; these do not replace the omitted automated E2E suites.
Live validation
Environment:
184a4f114d00b7805274841488f2906233b5a961deepseek-ai/DeepSeek-V4-Flash-0731Configuration: 524,288 full-history tokens,
--max-prefill-length 24576, 4,602 MoE cache slots,--memory-ratio 0.90, no explicit SWA flag.Startup resolved to:
derived, reasonrequested_and_swa_pool;Representative workload: 65,525 input tokens and 1,023 decoded tokens completed without OOM, using prefill chunks 24,576 + 24,576 + 16,373. TTFT was 25.631 s, aggregate prefill throughput 2,556.43 tok/s, decode throughput 40.58 tok/s, end-to-end time 50.817 s, and peak GPU memory was 90,071 MiB.
A live expert resize to 41,344 SWA tokens reported requested 24,576, pool/effective 19,200, source
explicit, reasonswa_pool; restart restored the derived 52,096-token geometry. An invalid ratio preflight returned HTTP 422 with all five observability fields and did not alter cache state.No main-versus-branch performance A/B is claimed: this is a correctness/configuration change, and
maincannot express the same DSV4 one-knob geometry without post-start mutation. The performance numbers above are branch validation only.