本文定义 NInfer 从产品请求到模型执行与结果发布的顶层控制面。它是请求生命周期、调度顺序和跨模块 提交关系的维护者权威。
本文只规定长期稳定的边界:
- 谁拥有请求、顺序、缓存策略和物理状态;
- 请求在哪些稳定状态之间转换;
- 模型状态、输出状态和资源状态何时可以对外发布;
- cancellation 和 failure 如何到达唯一终态。
资源选择和上下文缓存策略由 资源调度与上下文缓存定义;KV 的页、replica、block table 和 consumer contract 由 Paged KV Context Store定义。
Generation purpose 的 NInfer Engine 固定运行:
- 一张 GPU;
- 一个常驻模型实例;
- 启动时确定的
max_concurrency=1..8; - 一个有界 FIFO 等待队列;
- 不抢占已经激活的请求;
- 每个 decode round 将全部 decode-ready 请求组成一个紧凑批次。
Text、Vision、prefix reuse、MTP、DFlash/DFlash2、CLI 和 HTTP serving 都通过公共 ninfer::Engine 路径。
MTP、DFlash 和 DFlash2 是 Program 内部的执行后端,不产生第二套请求调度或结果发布机制。
Qwen3.8-27B 的 DFlash2 支持启动固定 K=1..15、full/optimized proposal head、Text/Vision 和
exact-batch CUDA Graph。它复用 family-owned masked-draft 状态事务,五层 local context
属于 StateImage,不分配 full backend KV;独立 context frontier 与 main frontier 的关系、
条件 proposal q 和最终提交规则见 DFlash2。
同一个公共 Engine 还提供启动时固定的 CausalScoring purpose。它只服务离线文本评分:
CausalScoreCore 串行调用 Program,窗口使用临时的空 State 与 Main KV,不创建请求、continuation、
checkpoint 或 cache replica,也不进入 Scheduler/ResourceManager。Generation 与 CausalScoring
不在运行期切换,评分专用 staging 只在 CausalScoring 启动时分配。
max_concurrency 限制同时激活的请求数,不把共享 KV 容量平均切分给 lane。请求只有在 Program
证明其完整执行资源已经得到保障后才会进入 Active;进入 Active 后,它不会因为另一个请求或
inactive cache 的保留而丢失完成能力。
本文不覆盖多 GPU placement、active request preemption、priority/QoS、跨 Engine context store 或大规模 continuous batching。这些工作负载需要重新定义 admission 与公平性合同,不能直接从当前 小并发模型外推。
请求路径只有四层:
Gateway
│ product/protocol input
▼
Frontend
│ PreparedPrompt / OutputSession
▼
Engine
│ request order / lifecycle / publication
▼
Program
physical resources / model execution
Gateway 是 CLI、HTTP server 或其他产品入口,拥有:
- 协议解析、连接和 streaming transport;
- message、tool、media 到公共输入的转换;
- URL、path 和 data acquisition;
- response schema、usage 和产品侧错误;
- Gateway 自身的并发与连接生命周期。
Gateway 不选择请求顺序、缓存来源、active lane 或 KV page。
Frontend 拥有模型家族的输入与输出语义:
- tokenizer、chat template、Vision preprocessing 和 MRoPE prompt construction;
- owning
PreparedPrompt及其内容 identity; - stop、thinking/content channel、detokenization、最终文本和模型私有结构化输出;
- model output 中可由历史 renderer 精确重建的 prefix-execution boundary;
- 每个请求独占的
OutputSession。
Frontend 可以预览一次模型输出将产生的语义效果,但只有 Engine 完成提交后才能发布该效果。 Frontend 不拥有等待队列、cache catalog 或物理模型状态。
Engine 是请求控制平面,拥有:
- outstanding capacity、FIFO queue 和 request deadline;
- request record、active slots、cancellation 和 response event;
- Scheduler 与 ResourceManager;
- admission、prefill、decode、control、capture 和 terminal 的编排;
- 模型提交、输出提交和 response publication 的顺序;
- Engine-wide failure cleanup;
- 可供 Gateway 读取的 Engine availability;其事实仍只由 EngineCore 的 failure/lifecycle 状态拥有。
Engine 理解请求、预算、finish reason 和可发布输出,不解释 transformer layer、KV plane 或 allocator。
Program 是 exact target package 的唯一物理执行入口,拥有:
- active sequence 与完整 continuation state;
- State/KV stores、allocator、replica、reference 和 reservation;
- prefill、ordinary decode、MTP/DFlash 和 forced control;
- provisional model state 及 accepted-prefix commit/rollback;
- resident prefix identity、shortlist digest 及 committed execution provenance;
- resource feasibility、物理 transition 和
ResourceResult; - workspace、CUDA Graph 和 target execution schedule;
- CausalScoring 窗口的临时 State/KV 与
lm_head/logprob staging。
Program 不维护 FIFO、SessionIndex、cache retention 价值或用户可见输出。
| 事实或决策 | 唯一所有者 |
|---|---|
| 协议、连接、transport | Gateway |
| prompt 与 output 语义 | Frontend |
| waiting queue、request record、response event | EngineCore |
| Engine availability | EngineCore;Gateway 只读取并映射为外部 readiness |
| FIFO head、backfill、prefill/decode 顺序、round membership | Scheduler |
| logical lane、cache catalog、session binding、retention policy | ResourceManager |
| model-output reconstruction-boundary 语义与 preview state | Frontend |
| committed resident prefix execution provenance | Program;Engine 只验证并搬运 metadata |
| physical State/KV、reservation、placement、model state | Program |
其他组件可以读取 owner 发布的稳定 summary,但不能复制一份可独立修改的同类状态。
Scheduler 维护:
- 当前 FIFO head;
- staged-prefill owner;
- admission、prefill 与 decode 的公平门;
- 每轮紧凑执行成员;
- blocked head 的 backfill protection。
Scheduler 不读取 checkpoint payload、victim list、resource vector 或 allocator 状态。
ResourceManager 维护:
- logical lane 状态;
- private/shared checkpoint catalog;
- SessionIndex 与 prefix candidate index;
- retention class、命中观测和逻辑 claim;
- admission、capture 与 finish 的缓存策略。
它把请求和缓存候选交给 Program 评估,并采用 Program 返回的完整物理结果。它不维护一份 Device/Host bytes、page refcount 或 allocator free space 的镜像。
Program 中的真实 stores 与 allocators 是物理事实的唯一权威。Program:
- 从完整候选终态计算占用、共享、回收和阶段峰值;
- seal 与当前
resource_revision绑定的 opaqueResourcePlan; - 执行唯一的物理 transition;
- 返回足以让 ResourceManager 更新逻辑 catalog 的完整结果。
Program 不根据 session、FIFO 位置或用户身份决定缓存价值。
Engine 构造时读取 .ninfer identity,并从 closed registry 选择 exact compile-time package。Package 提供
同一组 Frontend、request-plan、Program 和 execution-result 语义;target identity、artifact binding、模型
view 与 execution leaves 保持 package-private。Qwen3.6 family 的共享 schedule 通过 compile-time Variant
实例化,worker hot path 不执行 runtime family selection。
27B 与 35B-A3B package 是同一 identity-free Qwen3.6 family 的平级 Variant,任何一方都不以另一方 的差异补丁定义。共享算法与实例存储的归属不同:
src/targets/qwen3_6拥有SequencePlan<Variant>、RequestPlan<Variant>和Program<Variant>算法,以及 Text/Vision/speculative schedule、state transaction、workspace composition 和 CUDA Graph capture/replay 机制。Family 同时拥有 tokenizer/template、输出语义、 media preprocessing、MRoPE prompt construction、owning prepared-prompt/output-session 类型、 semantic weight-view schemas 和 passive Vision definitions。- 每个
src/targets/<package>拥有注册 identity、storage profile、binder、LoadedModel、配置、 dimensions/storage facts、填充后的 immutable family model view、private leaf payload、diagnostics、 graph frontier values 和 Program instance bytes。Package alias 并实例化 family runtime 类型,不复制 Program、schedule、workspace composition、state transaction 或 graph-capture 算法。 - Package 提供三类 execution leaves:attention projection、GDN projection/control、post-mixer。
Leaf 调用的闭合数学或状态变换仍由
src/ops实现。
Family 不拥有 target identity、registry entry、artifact binder、target leaf implementation 或 live Program instance storage;family schedule 内没有 runtime family selection 或 target-dependent branch。 每个 Program 独占可变状态和 device allocation。Prepared prompt 不携带 exact-target tag;各 artifact 的共同 frontend resources 及具体清单由相应 artifact reference 定义。
权重、State/KV backing、block-table matrices、workspace 与 CUDA Graph resources 在 Engine 开始接受请求前 建立。运行期改变 ownership、mapping、frontier 与 replica placement,但不重建这些大块 Device allocations。
请求沿以下稳定状态前进:
Waiting
-> Materializing
-> Prefill
-> DecodeReady | ControlReady
-> TerminalPending
-> Finished
- Waiting:只有 owning prompt 和输出状态,没有 Program sequence。
- Materializing:资源 transition 已取得逻辑 claim;source 在 commit 或 abort 前仍有效。
- Prefill:请求已经 Active,正在消费 prompt suffix。
- DecodeReady:可加入下一次紧凑 decode round。
- ControlReady:Frontend 要求提交规范的 forced-control suffix。
- TerminalPending:模型执行已经终止,但 active resources 尚未完成 retain 或 release。
- Finished:资源与输出均已提交,response 可以完成。
ResourceManager 的 lane 状态是:
Free -> Materializing -> Active -> TerminalPending -> Free
请求只有在 materialization 的物理结果和逻辑结果均成功采用后才能进入 Active。Terminal request
必须保留 active ownership,直到完整 checkpoint 被发布或全部 active resources 被释放。
Streaming request 在 admission 选择提交后、任何输出 delta 前发布一次 GenerationStart;其中的
prompt token 和 reused-prefix token 是已提交的资源选择事实,不等待 prefill 完成。
Control lane、StateImage slot、KV execution row 和 decode batch row 是不同身份:
- lane 是 Engine 的长期 active request 位置;
- State/KV execution resource 由 Program 分配;
- compact row 只是当前 GPU unit 的序号。
它们不得互相推导所有权。
Gateway 可以在 prepare 或 media acquisition 前取得自己的 request lifetime。Engine outstanding capacity 从非零输出请求成功 submit 开始,由两个独立事实共同释放:
response_done worker 已形成最终 result 或 error
consumer_released wait 已结束,或 GenerationHandle 被放弃
release_capacity =
response_done && consumer_released && !capacity_released
两者可以任意先后,但 capacity 只释放一次。请求句柄被放弃只设置 cancellation 和
consumer_released,不会从 consumer thread 调用 Program。
Active continuation 是可写的模型状态;published checkpoint 是不可变的可复用状态。一个可复用 checkpoint 必须证明同一 frontier 上的完整 State、Main KV、selected backend KV 和继续执行所需 metadata。
Session key 只是查找提示,不拥有 continuation。每个请求进入 Engine 时取得单调的
publication_order;只有更新顺序更晚的完成结果才能替换 SessionIndex binding。
只有 Engine worker 修改 request record、Scheduler、ResourceManager 和 Program。Ingress、consumer 和 transport thread 通过队列、cancellation flag 与 response event 交互,不直接改变模型状态。
一个 worker boundary 按语义顺序处理:
- 接收等待请求的 timeout 或 cancellation;
- 推进已经开始的 resource transition;
- 完成可以结算的 TerminalPending 请求;
- 冻结 active cancellation snapshot;
- 在公平门允许时尝试一次 admission;
- 选择 staged prefill、forced control 或紧凑 decode;
- 运行至多一个模型 execution unit;
- 提交模型、预算和 Frontend 输出状态;
- 发布 response event 与观测。
具体循环拆分可以变化,但以下顺序不能变化:
- in-flight GPU unit 必须先到稳定边界,再修改其资源映射;
- Program commit 必须先于用户输出发布;
- resource result 必须先被采用,lane 才能改变可见状态;
- 一个 global resource topology transition 未结算时,不启动另一个 transition。
Scheduler 先确定唯一可尝试的 waiting request,ResourceManager 再为它选择缓存与资源终态。 资源条件不能反向改变 FIFO 所有权。
FIFO head 暂时受 active incumbents 阻塞时,Scheduler 记录 protected head 和必须结束的 donor set。 后续请求只有在 Program 证明以下条件时才能 backfill:
borrower 持续占用其完整 active reservation 后,既定 donor set 结束仍足以让 head 以 root 且释放全部 inactive cache 的方案进入。
这个证明不使用“borrower 预计先完成”的时间假设。改变全局资源拓扑的 transition 会推进
resource_revision,之后的 backfill 必须重新证明。
Scheduler 保证:
- 同时最多一个 staged-prefill request;
- 已有 decode work 不会被连续 prefill 饿死;
- decode round 包含所有且仅包含当前 decode-ready requests;
- batch 使用精确
B,不以 inactive lane padding 到max_concurrency。
Program 接收紧凑的 SequenceHandle[B] 和每行预算。Prefix reuse 只减少 materialization 或 suffix
prefill,不创建另一条调度路径。
只有会改变 admission 结论的事实才重新触发检查:
- waiting queue 或 FIFO head 变化;
- lane 释放;
- staged-prefill gate 变化;
- resource transition 到达终态;
- Program 的全局资源 revision 变化。
普通 decode frontier 推进、输出发布和统计更新不扫描 cache catalog,也不重复运行 pressure planner。
Engine 跨模块编排两类互不替代的事务。
Resource transition 在以下边界改变全局资源或 ownership:
- waiting request materialization;
- active checkpoint capture;
- terminal retain 或 release;
- inactive checkpoint 的 placement 或删除。
需要 planning、allocation 或 transfer 的路径遵循:
logical choice
-> Program seals ResourcePlan
-> RunningTransaction
-> ResourceResult
-> ResourceManager adopts result
ResourcePlan 与 Program 的 resource_revision 绑定。Start 前过期的 plan 可以无副作用地重新规划;
start 后不能更换 source、victim 或 stage 顺序。Abort 也必须返回完整终态,使所有 claim、pin 和已提交
的安全降级得到唯一解释。
资源候选、可行性公式、成本模型和有界搜索由 资源调度与上下文缓存定义。
Prefill finalization、decode 和 control execution 可以产生 move-only PendingBatch:
frozen sequence membership
provisional tokens
per-row produced extent
per-row accepted-prefix execution metadata
Program-owned provisional state
Engine 对每行输出进行 Frontend preview,形成 accepted-prefix decision,再用一次
Program::commit 或 Program::abort_pending 消费整个 batch。Program 同时提交或回滚该 prefix
对应的 Main/backend KV、recurrent state、RNG 和 speculative state。
非取消行遵循:
1 <= accepted_tokens <= produced_tokens
nonterminal -> accepted_tokens == produced_tokens
terminal -> accepted_tokens may be a produced prefix
取消行使用零 accepted token 并进入 terminal。Engine 不允许逐行遗弃一个仍未消费的
PendingBatch。
一次模型输出的可见顺序是:
Frontend preview
-> Program commits accepted model state and resident prefix execution provenance
-> terminal resource result, when required
-> generation budget and scheduler accounting
-> OutputSession commits preview
-> publish stream/aggregate event
因此 consumer 不会看到尚未提交的 token,也不会看到与 Program frontier 不一致的 continuation。 Forced control 使用同一提交顺序,但 token 由 Frontend 提供,不调用 sampler,也不推进 sampling RNG。
Frontend 产生的 boundary metadata 只描述当前 accepted span 内的相对位置。Engine 验证它落在该 span 内并随
对应 row 搬运,不解释 delimiter,也不修改 resident identity。Program 使用 pending row 的 base frontier
转换为绝对位置,并与 accepted token、Main/backend state 及 prefix digest 原子提交。Program commit 失败时,
OutputSession 的 preview state 同样不提交;ordinary、MTP、DFlash 和 forced control 共享这一所有权链。
成功终止的 Active request 先进入 TerminalPending:
choose retain or release
-> Program publishes one complete checkpoint or releases the sequence
-> ResourceManager adopts the terminal result
-> optional SessionIndex update
-> lane becomes Free
Checkpoint 的逻辑 publication slot 在 activation 时已经保留。若 retention 无法形成完整 continuation, 确定性终态是 release,而不是让请求停留在 TerminalPending。
Cancellation 在 Engine worker 的稳定边界生效:
| 观察到 cancellation 时的状态 | 结果 |
|---|---|
| Waiting | 不创建 Program state,直接结束请求 |
| Materializing | abort resource transition,并采用其完整结果 |
| Active | 当前 GPU unit 稳定后进入 TerminalPending 并 release |
| PendingBatch | 通过 cancelled row decision 提交或整体 abort |
| 已 commit、尚未 adopt | 先 adopt 已提交结果,再执行 terminal 路径 |
Cancellation 不修改 in-flight mapping,也不从未完成的 active state 发布 checkpoint。
在 Program mutation 前可以只拒绝当前请求:
- queue timeout、overload 或 waiting cancellation;
- 输入超过公开 context contract;
- prompt 或 generation request 无法表示;
- 即使采用 root source 并释放全部 inactive cache,单请求仍不可行。
以下情况说明共享物理状态已无法安全解释,必须使整个 Engine 失败:
- GPU mutation 后既不能 commit 也不能形成稳定 abort;
PendingBatchmembership 或 disposition 不一致;- handle owner/generation 不匹配;
- resource、checkpoint completeness 或 noexcept adoption invariant 被破坏。
Cleanup 顺序必须先终止 Program 中未决的 resource/model transaction,再释放 active state,最后清空 ResourceManager 与完成所有 request response。内部不变量错误不能降级成 cache miss、等待或重试。
以下约束属于 Engine 架构,但具体实现由 Program 和下层文档定义:
- Program 在启动时建立固定数量的 control/state/table resources;
- growing KV 由共享 paged pools 支持,active request 持有完整增长 reservation;
- 一个 GPU execution unit 内 State/KV mapping 保持稳定;
- CUDA Graph 按合法 exact-
Btopology 建立,request identity 和 page IDs 是稳定输入数据,不是 graph key; - ordinary decode 不运行 catalog scan、pressure search 或后台 replica scan;
- workspace 是 Program 启动时统一规划的 backing,Vision、Text 和 speculative schedule 按互斥 lifetime 使用其内部区域。
Serve warmup 使用同一个公共 Engine 执行路径,但其 request-level context cache 固定关闭。Warmup 可以建立 CUDA Graph、library 和 allocator 的运行时状态,结束后不得留下可供外部请求命中的 continuation 或占用 checkpoint catalog。
- 请求顺序只由 Scheduler 决定。
- logical cache policy 只由 ResourceManager 决定。
- physical occupancy、reservation、feasibility 和 model state 只由 Program 决定。
- Active publication 前必须具备完整 continuation 和完成 reservation。
- 一个 global resource topology transition 在任意时刻至多一个。
- 一个
PendingBatch必须由一次 Program commit 或 abort 完整消费。 - Program、Frontend 和 budget 均提交后,模型输出才对 consumer 可见。
- TerminalPending 结束前不得释放或复用该请求的 active ownership。
- Cancellation 只能在线性化的 worker boundary 改变请求状态。
- 每个 accepted request、resource transaction 和 model transaction 都有有限且唯一的终态。
| 职责 | 主要位置 |
|---|---|
| 公共 Engine facade | include/ninfer/engine.h, src/runtime/engine/engine.cpp |
| Engine worker 与 request lifecycle | src/runtime/engine/engine_core.h, src/runtime/engine/request_record.h |
| Scheduler | src/runtime/engine/scheduler.h, admission_policy.* |
| ResourceManager 与 materialization planner | src/runtime/engine/resource_manager.h, materialization_planner.h |
| package-neutral runtime contracts | src/runtime/contract/types.h |
| family Program algorithms | src/targets/qwen3_6/impl/runtime/ |
| family frontend semantics, owning prompt/output types, semantic model views | src/targets/qwen3_6/ |
| registered identities, binding, model views, execution leaves, Program instance storage | src/targets/<package>/ |
| device primitives, tensors/views, checked layouts, arenas, graph RAII, physical KV, raw transfers | src/core/ |
generic .ninfer framing, descriptors, binding primitives, materialization |
src/artifact/ |
| semantic Ops | src/ops/, include/ninfer/ops/ |
| shared JSON/message-to-owning-input adapter | src/product/prompt_input/ |
| media URL/path/data acquisition | src/product/media_acquire/, CLI and serving |
| media decode from already-owned bytes | src/media/decode/ |
| HTTP Gateway | src/serve/ |
| target-private inventories, source recipes, conversion, payload verification | tools/convert/<target>/ |
这些路径用于定位当前 authority,不把文件拆分固化为外部接口。
include/ninfer/engine.h 与 include/ninfer/types.h 是 in-tree application 使用的 opaque Engine
interface 和 owning host values;NInfer 当前不安装或导出 C++ SDK。include/ninfer/ops/ 是
repository-internal semantic Op contracts。.ninfer 是唯一 C++ 产品 artifact,不通过扩展名检测、
兼容 shim 或第二套产品入口加载其他格式。CLI、server 和 inference benchmark 只通过公共 Engine
推理;converter 不提供 Python model-inference route。
Artifact 不解释 checkpoint execution semantics;runtime 不拥有模型数学或 target state;media
acquisition 不链接到 target。每个语义闭合的 Op(包括 fused、fixed-shape 和 device-specialized
实现)都归 src/ops,不按最初调用者或是否已跨 target 复用决定归属。
相邻文档:
- 资源调度与上下文缓存:resource vector、checkpoint capability、pressure planning 和 physical transition;
- Paged KV Context Store:typed pools、logical pages、replicas、block tables 和 consumer address contract;
- Op development:Op 正确性与性能准入;
- CLI与 HTTP serving:外部行为。