Skip to content

feat: add configurable prefill queue scheduling - #1591

Merged
hiworldwzj merged 7 commits into
mainfrom
wzj_queue
Oct 16, 2026
Merged

hiworldwzj merged 7 commits into
mainfrom
wzj_queue

Conversation

@hiworldwzj

@hiworldwzj hiworldwzj commented Sep 23, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

This PR adds configurable prefill-queue scheduling before compute-token and KV-cache allocation, with three policies:

  • default: preserve the existing FCFS behavior while honoring internal inference priority.
  • promote_shortest: keep high-priority requests first, then promote the shortest normal prefill request without disturbing the relative order of the remaining requests.
  • hrrn: order normal prefill requests with token-based Highest Response Ratio Next (HRRN) aging.

It also separates router admission priority from inference-side scheduling priority, refines PD continuation handling, changes busy-node retry to opt-in, and adds documentation and focused tests.

Scheduling behavior

Decode requests are identified with the same rules used by request classification. They remain at the front of the queue in stable order and are not reordered by prefill policies.

Policy Behavior
default Stable sort by internal infer_high_priority; equal-priority requests remain FCFS.
promote_shortest Keep negative-priority requests first, then promote only the shortest normal prefill request while preserving every other request's relative order.
hrrn Keep negative-priority requests first, then order normal requests by token-based HRRN score.

The HRRN score is based on processed prefill work rather than wall-clock time:

score = waited_prefill_tokens / uncached_prefill_tokens
waited_prefill_tokens =
    processed_prefill_tokens - arrival_processed_prefill_tokens

Implementation details:

  • Each InferReq snapshots the backend's processed-prefill-token counter when it is constructed.
  • The uncached service cost is bound lazily when the request first participates in HRRN ordering, using max(1, input_len - cur_kv_len).
  • That service cost remains fixed across later chunked-prefill rounds, matching the intended HRRN model rather than shrinking dynamically as the request progresses.
  • Request ID is used as a deterministic tie-breaker across TP ranks.
  • The processed-token counter advances only when a selected prefill batch is submitted for execution.
  • Accounting reuses the token count already computed during resource selection, avoiding an extra pass and duplicate prefill_need_token_num calls.
  • Mixed prefill/decode batches include all tokens submitted in the selected prefill run mode.

PD priority and retry behavior

  • high_priority_request remains the router/shared-memory admission-priority flag.
  • infer_high_priority is an internal inference-side field; external requests cannot set it.
  • Only PD continuation segments (segment_index > 0) receive elevated inference priority. The first segment is not promoted merely because it has a cache hit.
  • LIGHTLLM_PD_NODE_BUSY_RETRY_TIMEOUT_SECONDS now defaults to 0, so busy-node retries are disabled unless a positive timeout is configured explicitly.

Motivation and expected impact

  • promote_shortest is intended primarily for PD-disaggregated Prefill nodes. It can improve time to first token for short prompts with a deliberately limited queue reorder.
  • hrrn favors requests with small uncached service cost while token-based aging allows long-waiting requests to overtake newly arrived short work, reducing starvation risk.
  • Token-based aging avoids wall-clock skew across TP ranks and does not require a configured throughput estimate.

Documentation

  • Add a dedicated Chinese guide covering policy semantics, examples, rollout guidance, and extension points.
  • Update the Chinese and English server-argument references.
  • Credit the original HRRN design and implementation inspiration from SGLang PR #32911.

验证

已 rebase 到 upstream/main 3d9415f44470202b9bd24e9b5b6f32ded726413a,保留原有两个提交。冲突处理中保留 upstream 的整组 shm_req 分配和 stop 参数逻辑,并更新优先级字段、整组分配 mock 和测试导入顺序。

CPU 测试:241 项通过,4 项失败。这 4 项在未修改的 upstream/main 上同样复现,分别涉及 full-attention DP 容量,以及 PD 缓存优先级最大年龄、最小 prompt 长度和节点资源等待时间的默认值。

pre-commit(Black、Flake8)与 git diff --check 通过。本次只做 rebase 和兼容修正,没有新增 GPU 性能测试。

@shihaobai
shihaobai self-requested a review September 28, 2026 04:23
@sufubao

sufubao commented Oct 14, 2026

Copy link
Copy Markdown
Collaborator

在 rebase 后的提交 cf79bfd47a831c7c4162172c6215de700033ca36 上完成了长短请求混合负载对比。两种策略都明显降低短请求首 token 延迟;本轮没有显示 HRRN 优于 promote_shortest。

测试配置:同一块 H100 80GB、Qwen3.5-0.8B、同一个 Jenkins 构建镜像;纯文本,短输入 128 tokens、长输入 16384 tokens,均输出 128 tokens。batch_max_tokens=1024、chunked_prefill_size=1024、running_max_req_size=256、graph_max_batch_size=256,容器 nofile=65536。三组仅修改 --prefill_queue_strategy,镜像、GPU/驱动、模型清单、测试脚本及每轮请求摘要均已核对一致。

每个场景先运行一次完整混合负载预热,再测量三次;每种策略共 864 个测量请求,全部成功。下表为三次测量各项指标的中位数,P95 为每轮请求分布 P95 的中位数。

场景 策略 短请求 TTFT 中位数 / P95(ms) 长请求 TTFT P95(ms) 输出 tokens/s 吞吐相对默认
长请求先到 default 1636 / 2724 20083 477.61 —
长请求先到 promote_shortest 335 / 407 20139 475.01 −0.5%
长请求先到 hrrn 369 / 430 20239 473.50 −0.9%
交错到达 default 4197 / 7713 19896 808.22 —
交错到达 promote_shortest 308 / 409 20358 791.10 −2.1%
交错到达 hrrn 375 / 505 20345 792.14 −2.0%

promote_shortest 的短请求 TTFT 中位数分别降低 79.5% / 92.7%,HRRN 分别降低 77.5% / 91.1%;长请求 P95 TTFT 上升约 0.3%–2.3%。改善主要体现在首 token 更早返回:短请求 TPOT 中位数增加约 6%–21%,完整响应时间未缩短,短请求 P95 完整响应延迟增加约 0.4%–2.3%。

负载及结果范围:

  • 长请求先到:48 个长请求在 0–47ms 计划发送,48 个短请求在 60–107ms 计划发送。
  • 交错到达:192 个请求按 500 requests/s 计划发送,共 382ms;每四个请求中一个长请求、三个短请求。这是有限积压负载,不能据此验证持续流量下的抗饥饿保证。
  • 计划发送时间相同,实际客户端发送存在偏差;各策略突发场景分组 P95 偏差约 50–88ms,交错场景约 1–9ms,原始记录保留。
  • HRRN 的“长请求先到”场景首个正式重复仍触发了约 12 秒的 TileLang 迟发编译,吞吐为 308.8 tokens/s;后两次为 473.5、474.2。三次记录均保留,上表取中位数;这次异常不能直接归因于调度策略,也不能据此断言两种新策略的细微差异有统计意义。

CI 原始指标、配置、服务日志和实验记录已归档(以下为内部 Jenkins 地址):default #10、promote_shortest #11、HRRN #12。三组均通过 exp 记录实际服务版本、硬件及配置;镜像未 push。

@sufubao

sufubao commented Oct 14, 2026

Copy link
Copy Markdown
Collaborator

补充完成多 GPU 混合负载和 PD 详细测试,提交仍为 cf79bfd47a831c7c4162172c6215de700033ca36。结果按模式与负载有明显差异,不能从之前的快速测试判断两种策略普遍等价,也不能认为 HRRN 普遍领先。

24组正式实验、320,640个测量请求,全部成功。普通模式6张H100,每个prefill预算用3张卡轮换三种策略并平衡顺序;PD为同机1P1D、NCCL,各预算固定GPU对,P策略改变、D参数固定。Qwen3.5-0.8B纯文本、无MTP,短输入128 tokens、长输入4K/8K/16K,输出128 tokens。batch_max_tokens=chunked_prefill_size分别为1024/4096,running_max_req_size=graph_max_batch_size=256,nofile=65536,CPU核隔离。每场景2轮完整混合预热、5轮正式测量。

同卡比较核对了镜像、驱动、CPU绑定、模型清单、客户端代码及每轮payload/计划发送时间摘要。任何策略的某轮若与TileLang编译重叠,该卡三策略对应轮次同时排除;原始记录均保留,每卡/场景至少3轮干净配对。以下变化为各卡配对对数比均值换算百分比,95%区间由GPU与负载轮次交叉bootstrap获得,保留共同种子的相关性及编译排除的缺失单元。PD每预算仅一个GPU对,区间主要反映重复负载的不确定性。

代表场景:8K长输入、25%长请求,持续60请求/s、8秒。相对 default 的变化(延迟负值更好,吞吐正值更好):

模式 / Prefill预算 策略 短TTFT P95 长完整延迟P95 输出吞吐
普通 / 1024 promote_shortest +1.6% +13.1% -10.1%
普通 / 1024 hrrn -9.1% +5.7% -4.7%
普通 / 4096 promote_shortest +57.0% +26.8% -14.7%
普通 / 4096 hrrn +1.7% +3.9% -2.2%
1P1D / 1024 promote_shortest -93.3% +6.1% -4.0%
1P1D / 1024 hrrn -92.8% -0.9% +0.9%
1P1D / 4096 promote_shortest -22.1% +30.0% -8.3%
1P1D / 4096 hrrn -3.5% -1.9% +0.6%

同场景 HRRN相对promote_shortest 的配对变化与95%区间:

模式 / 预算 短TTFT P95 长完整延迟P95 吞吐
普通 / 1024 -10.5% [-13.9, -6.3] -6.5% [-8.5, -4.8] +5.9% [+4.3, +8.0]
普通 / 4096 -35.2% [-44.1, -27.2] -18.0% [-21.6, -13.9] +14.7% [+10.6, +18.5]
1P1D / 1024 +6.9% [-1.4, +15.8] -6.6% [-8.2, -5.4] +5.1% [+4.1, +6.6]
1P1D / 4096 +23.9% [-9.6, +80.9] -24.6% [-27.5, -21.6] +9.8% [+8.7, +10.7]

两处代价:

  • 1P1D / 1024:16个16K长请求先到,随后持续8秒短请求流(120/s)。相对默认,HRRN短TTFT P95降低63.6%,但长完整延迟P95增加 65.5% [60.7, 70.4];promote_shortest的长尾增加73.8%。有限测试不能证明持续流量下无饥饿。
  • 1P1D / 4096:16K长输入、90%短请求、120请求/s。HRRN相对promote_shortest的长完整延迟P95增加 10.3% [3.2, 18.3],吞吐下降 5.6% [4.1, 7.3]。

完整六场景还覆盖长请求先到的突发、4K/20请求每秒低负载、16K/120请求每秒过载与短请求占多数。部分突发/低负载指标的区间仍很宽,跨零不表示已证明等价;±5%只作为本次工程参考线。不同预算组硬件/NUMA不同,未把跨预算绝对差异单独归因于预算。普通模式使用token ID列表、PD使用重分词校验精确长度的文本,未直接混比两种模式的绝对性能。

所有原始请求、配置、服务日志、编译标记和统计输入哈希已归档,实验及最终评估均通过exp记录实际服务版本、硬件和配置。沿用同一CI构建镜像、未push;测试容器已清理,八卡空闲。

@hiworldwzj
hiworldwzj merged commit 832ac62 into main Oct 16, 2026
1 check passed
@hiworldwzj
hiworldwzj deleted the wzj_queue branch October 16, 2026 06:45
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.

2 participants