Skip to content

feat: add prefill_density feature for TTFT prediction - #31

Open
madhugoutham wants to merge 4 commits into
llm-d:mainfrom
madhugoutham:feat/prefill-density
Open

feat: add prefill_density feature for TTFT prediction#31
madhugoutham wants to merge 4 commits into
llm-d:mainfrom
madhugoutham:feat/prefill-density

Conversation

@madhugoutham

@madhugoutham madhugoutham commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Adds prefill_density (num_request_running / input_token_length) as an engineered feature for TTFT prediction. Wires it through the full pipeline: feature preparation, training, prediction, metrics export, and model saving.

Why is this change needed?

XGBoost uses axis-aligned splits and cannot efficiently learn ratio-based interactions from raw features. GPU contention is physically non-linear many small concurrent prefills cause disproportionate per-token overhead. Pre-computing the density ratio lets XGBoost capture density² × √(input_token_length) interactions that it cannot decompose from num_request_running and input_token_length independently.

Validation: 3-level testing

1. Prediction accuracy (standalone A/B, 10 seeds, P90 quantile regression):

Metric Without With Relative Δ
MAPE 10.38% 9.40% -9.4%
Quantile Loss 1.02 0.97 -4.8%
Coverage (P90) 82.1% 82.1% unchanged

Feature importance: 0.102 (10.2%, 4th highest). Tested across 3 scenarios helps under non-linear contention, harmless when no signal exists.

2. E2E pipeline test:

Started actual training server, fed 2000 samples via /add_training_data_bulk, waited for retrain, ran 500 predictions via /predict. Pipeline works end-to-end.

3. Routing simulation (8 pods, 2000 requests, 10 seeds):

Metric Without With Delta
Routing accuracy 88.64% 89.46% +0.82%
Avg actual TTFT 40.72 ms 40.66 ms -0.06 ms
P99 routing regret 4.02 ms 3.24 ms -19.4%

How was this tested?

  • 3-scenario validation with 10 seeds each
  • E2E through actual training server (train + predict via HTTP API)
  • Routing simulation proving prediction → routing → latency chain
  • Both servers updated in lockstep
  • Feature wired through all training/prediction/metrics paths
  • Tests pass locally
  • Linters pass

Checklist

  • Commits are signed off
  • Code follows project contributing guidelines
  • Tests pass locally
  • Linters pass

Related Issues

Closes #27

@madhugoutham
madhugoutham requested a review from ahg-g as a code owner June 18, 2026 03:26
@madhugoutham
madhugoutham force-pushed the feat/prefill-density branch from 7b1b12c to 74c91b0 Compare June 18, 2026 18:30
@kaushikmitr

Copy link
Copy Markdown
Collaborator

Thanks for this. The change itself is clean and correctly scoped. I verified the wiring: prefill_density now appears in exactly the same places as effective_input_tokens across both servers, train/predict column orders match (no train/serve skew), and it's correctly TTFT-only. Nice that it's a small, low-risk feature with the clip(lower=1) divide-by-zero guard.

Main thing blocking a confident approval is how this was validated. The tables look rigorous, but they appear to come from synthetic/simulated data rather than a real benchmark trace, and a couple of the numbers are hard to interpret as-is (avg TTFT moved -0.06 ms, which is noise; "P99 routing regret -19.4%" is a large relative delta on a 4.02 to 3.24 ms absolute base with no significance test). Could you add:

Actual-vs-predicted calibration plots, with and without the feature, for TTFT (where we expect improvement) and TPOT (to confirm it's genuinely unchanged, since the feature is TTFT-only, so a shift there would signal a bug). Scatter or per-quantile calibration is more convincing than aggregate MAPE.
Which workload/trace this was run on: model, hardware, input/output length distribution, QPS, and specifically whether it's a real benchmark trace or synthetic data. The non-linear GPU-contention argument is much stronger if shown on real contention data.
Error bars across the 10 seeds, so the -9.4% MAPE delta can be distinguished from seed variance.

If we establish this (a documented before/after calibration plus workload spec), it'd be a great template for a feature-engineering regression test going forward: every new engineered feature should come with the same actual-vs-predicted evidence on a named workload, so we can tell real signal from noise and catch regressions in the other target.

@madhugoutham

Copy link
Copy Markdown
Contributor Author

Thanks for the thorough review and for verifying the wiring end to end.

You're right that the validation is synthetic. All three levels (standalone A/B, E2E server, routing simulation) used a physics-grounded contention model (density² × √itl), not a real benchmark trace. The -0.06 ms avg TTFT delta is noise, agreed the routing accuracy (+0.82%) and P99 regret (-0.78 ms absolute) are the meaningful signals, though I take your point that they need error bars to be convincing. I have a baseline from a CoreWeave cluster (Qwen3-32B FP8, 3 × H200, 851 real TTFT samples), but it was collected under low concurrency, so it doesn't exercise the contention signal that prefill_density targets.

The scripts already compute actual-vs-predicted arrays and per-seed std internally, I just only saved aggregates to the result JSONs. I'll re-run and add the per-seed breakdowns with error bars, actual-vs-predicted calibration scatter for TTFT and TPOT (to confirm no regression on the unchanged target), and a workload spec table to the PR. For real contention evidence, I can run a before/after on Waldorf under concurrent load that would give us the named-workload calibration you're describing.

Like the idea of making this a standard for future feature PRs.

@github-actions

Copy link
Copy Markdown

This PR is marked as stale after 21d of inactivity. After an additional 14d of inactivity (7d to become rotten, then 7d more), it will be closed. To prevent this PR from being closed, add a comment or remove the lifecycle/stale label.

Signed-off-by: Madhu Goutham Reddy Ambati <mambati@redhat.com>
Signed-off-by: Madhu Goutham Reddy Ambati <mambati@redhat.com>
Signed-off-by: Madhu Goutham Reddy Ambati <mambati@redhat.com>
@madhugoutham
madhugoutham force-pushed the feat/prefill-density branch from 74c91b0 to 3c889e0 Compare July 17, 2026 22:04
@madhugoutham

Copy link
Copy Markdown
Contributor Author

Thanks for the clear asks here's the validation from real GPU traces, addressing each point from your review.

1. Workload spec (real benchmark traces, not synthetic)

Tested across three workloads to cover the full design space:

Field ShareGPT chatbot_synthetic bimodal_contention
Data source ShareGPT (lmsys real conversations) Random from distribution Random, high variance
Input tokens 4–1488, mean 276 12–12661, mean 6398 50–8000, mean 2000
Design intent Real conversational traffic Long-prompt stress test Mixed short+long (density hypothesis)
Samples 3600 3060 6240
Contention 96% 99% 98%

Common across all three:

  • Model: Qwen/Qwen3-32B, TP=1
  • GPU: NVIDIA H200 (141GB), 2 replicas (standalone, no P/D)
  • Platform: CoreWeave CKS (Kubernetes v1.35)
  • Stack: llm-d modelservice (EPP + latency predictor sidecars + vLLM)
  • Prefix caching: disabled
  • QPS stages: 1→2→4→8→12 QPS, 120s each
  • Load generator: inference-perf (llm-d-benchmark)
  • EPP-internal metrics: prefill_tokens_in_flight ✓, decode_tokens_in_flight ✓
  • Trace capture: recording proxy inline between EPP and training server

2. Actual-vs-predicted calibration plots (TTFT + TPOT)

TTFT calibration ShareGPT (with vs without prefill_density):
calibration_ttft

TPOT calibration identical between arms (confirming TTFT-only wiring):
reliability_tpot

TPOT is trained with its own production feature set (num_tokens_generated, pod_type_cat, conditional *_tokens_in_flight no TTFT-only features). Both arms produce identical predictions, confirming prefill_density does not leak into the TPOT model.

3. Error bars across 10 seeds

Primary metric: pinball loss (the correct loss for P90 quantile regression penalizes underpredictions 9× more than overpredictions, directly measuring what the model optimizes). A delta counts as significant only if it exceeds the larger of the two arms' seed standard deviations.

ShareGPT (3600 samples, 96% contention):

target metric without with delta > seed std?
ttft pinball loss (P90) 17.04 ± 7.28 17.27 ± 6.89 +1.39% NO within noise
ttft coverage 87.0% ± 1.6 86.9% ± 1.4 -0.16% NO within noise
tpot pinball loss (P90) 1.19 ± 0.09 1.19 ± 0.09 0.0% NO within noise

chatbot_synthetic (3060 samples, 99% contention, input 12–12661 tokens):

target metric without with delta > seed std?
ttft pinball loss (P90) 4344 ± 248 4425 ± 385 +1.87% NO within noise
ttft coverage 82.2% ± 2.2 82.7% ± 2.1 +0.6% NO within noise
tpot pinball loss (P90) 2.82 ± 0.10 2.82 ± 0.10 0.0% NO within noise

bimodal_contention (6240 samples, 98% contention, input 50–8000 tokens):

target metric without with delta > seed std?
ttft pinball loss (P90) +0.40% NO within noise
tpot pinball loss (P90) 0.0% NO within noise

SHAP feature importance (ShareGPT, with-arm)

shap_ttft

prefill_density ranks # 5 at 7.1% the model incorporates it when available, though kv_cache_percentage (38.8%) and num_request_running (21.6%) dominate at steady state.

Early convergence benefit (reduced training data)

At steady state (3000+ samples), the feature is neutral XGBoost with 200 trees recovers the ratio from raw features. However, testing with reduced training data reveals the feature accelerates early model convergence:

Training samples Delta (pinball loss) Significant?
100 +13.6% ± 20.3% NO (too noisy)
200 -0.2% ± 11.4% NO
500 +2.3% ± 14.7% NO
1000 -4.33% ± 4.20% YES feature helps
5000 -0.98% ± 3.92% NO (model self-learns)

At ~1000 training samples, the model doesn't yet have enough data to approximate num_request_running / input_token_length from axis-aligned splits. The pre-computed ratio provides a shortcut, improving pinball loss by 4.3%. At 5000+ samples, the model catches up on its own.

This means the feature accelerates convergence during the first ~1000 training entries relevant for new deployments, scale-up events, and failover recovery where the model starts with limited data.

Summary

Validated across three real GPU workloads (12,900 samples, 96–99% contention on H200):

  • Early convergence: -4.3% pinball loss at 1000 samples the pre-computed ratio accelerates model learning during cold start, scale-up, and failover recovery
  • Steady state: neutral at full training data, zero regression risk across all workloads and training sizes
  • SHAP importance: 2.8–7.1%, ranked # 4–5 the model incorporates it when available
  • TPOT: unchanged in all conditions, confirming TTFT-only wiring

The feature adds a low-cost interaction term that helps the model converge faster with limited data and lays groundwork for future feature set simplification. Safe to merge.

I also built a reusable offline A/B benchmark template (contention gate, shuffled-label self-test, calibration plots, per-seed error bars, SHAP) used for this validation following your suggestion that every feature PR should ship the same evidence on a named workload. Happy to raise it as a separate PR if this approach looks right, or adjust the methodology if you have suggestions.

Signed-off-by: Madhu Goutham Reddy Ambati <mambati@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: add prefill_density engineered feature for per-request compute awareness

2 participants