Add: persistent kernel-context execution resources (K2) - #2176
Conversation
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Kernel mode borrows the caller's device and stream for a bounded asynchronous operator. Define its C ABI, invocation envelope, and lifecycle contracts without enabling kernel execution in any backend. - Add the four simpler_kernel_mode entries, validating unsupported stubs, and distinct invalid-argument and invalid-state errors. - Latch the execution identity once. Program init latches PROGRAM before side effects; errors and finalization cannot change the mode. Separate thread binding, program attachment, and borrowed-device adoption, and guard the onboard device lifecycle by that identity. - Latch PROGRAM in ensure_acl_ready before its first ACL call. The entry is reachable without simpler_init, so taking ACL ownership is itself what makes a context a program context; leaving it unlatched would let a later kernel latch coexist with acl_ready_, whose finalize resets a device the context does not own. - Decide a kernel-mode arena capacity refusal across every region before touching any of them. The commit sequence rolls all regions back on failure, so a refusal raised from inside it would release the committed bases a captured graph still names. - Pin the 40-byte invocation header and every field offset. Make its trailing reserved bytes explicit and require both reserved fields to be zero. Payload validation belongs to the AICPU consumer. - Derive scalar counts from the callable signature. Preserve the existing factory signatures and serialized layout, with fixed callable offsets and tests that ignore historical padding bytes. - Require the kernel capability probe when loading a runtime. Resolve its lifecycle entries only for a supported context and publish the pointers after initialization succeeds. - Provide the kernel phase/cleanup state machine and restricted, non-throwing operation tables, compiled in its unit test until production integration. Keep stream/event handles encapsulated. - Cover wire bytes, scalar counts, error contracts, cleanup retries, arena refusal over real committed regions, and shared-library capability negotiation including failed-init recovery. Keep uniform-export checks for all eight components. Kernel init remains unsupported, so no production call latches KERNEL. Production integration must supply generation checks, safe enqueue/close serialization, and graph-resource lifetime enforcement.
nalinaly
left a comment
There was a problem hiding this comment.
本次为静态代码 review,未运行测试、未修改实现。建议修复三处逻辑问题后再合并,具体触发条件和修改建议见对应行内意见:
- prepare 未验证 callable 完整长度,截断的可变尾部可导致 Host 越界读取。
- 持久内存连续释放失败时,allocator 清空跟踪记录,破坏 close 的真实重试能力。
- C++ finalize 正常返回失败分支,导致 Python 误判成功并清空 registry。
本次不将 capture 外 init/prepare 的同步契约讨论列为缺陷。
533f67a to
bc4c0ac
Compare
Provision persistent kernel streams, events, runtime arguments, and callable uploads on top of the K1 ABI. Preserve retryable teardown ownership, validate complete callable images, and surface explicit finalize failures through the public worker API.
上板实测:K2 押的那个前提已经验过了(过),外加一条它该写进契约的约束这个 PR 拥有的东西——一条专用 AICPU 流 + 一条 hidden AICore 流 + 五个 环境:a2a3 onboard、CANN 9.0.0、torch_npu 2.7.1。代码与全部结果在 ✅ 1. "常驻 event 集被多张捕获图共享"——这是 K2 的核心押注,此前没人验过。已验,过。kernel 模式的两条流和五个 event 是建一次、活到 context 结束的;而 vLLM 每个 batch 桶捕一张图,于是 N 张图会 record/wait 同一批 event 对象。H7「分桶切换」默认这成立。 Probe D(两张图共享同一批常驻 event/stream,各写自己的 pattern 进同一对 device slot):
零 ACL 错误。背靠背那一臂是最硬的——同一个 event 在上一次 record 可能还在飞的时候被第二次 record,这正是常驻 event 集最该崩的地方,也是 vLLM 实际会产生的形状。 K2 的资源模型可以按"context 常驻"设计,不需要 per-graph 复制。 ✅ 2. 双流形状与 capture 相容,两条独立路径各验一次
计划把 Probe B 标为"最要紧""不通则整段返工,930 前返工窗口极窄"——已经通了。 🔴 3. 一条 K2 应当写进契约的约束:这五个 event 不能跨捕获边界被等待Probe C 实测: K2 只创建和持有这批 event,record/wait 经 ops 表( 这不是假设,已经有一个实例:#2187 binder 里 if (h.consume_prepare_tail &&
!step(KernelLaunchStep::PrepareWait, ops.wait_event(ops.context, h.caller, h.prepare_tail)))
建议 K2 的 event 集文档写明:每个 event 的"上一次 record"与"这次 wait"必须落在同一个捕获上下文内,否则 107024。 这条同时也解释了 §12.2 为什么两个存活分支都要求"不 enqueue 旧 tail wait"。 🟠 4.
|
Dependency and review scope
Depends on #2064 (K1), rebased onto its current head
31b03d92d6908d3141589de35369e3b67aef0a82.There is exactly one K2 commit above that base.
K1 is still open and its branch belongs to another fork, so this Draft PR targets
mainand temporarily includes the dependency in GitHub's diff. Review the K2-only comparison. Rebase onto merged K1 before marking this PR ready.Summary
ACL_EVENT_SYNC.Review fixes
PersistentKernelArgsthrough the realfinalize_commonpath.ChipWorker::finalize()throw on device teardown failure; its destructor catches failures at the non-throwing cleanup boundary.Validation
test_chip_worker.py,test_kernel_mode_c_api.py): 53 passed, 36 skipped.Tests cover complete callable truncation/range rejection, prepare reuse, duplicate IDs, persistent allocation retry, stream/event close retry, explicit wrapper retry, unclosed destruction, fatal-device admission shutdown, and zero calls to all intercepted ACL/device lifecycle APIs during kernel mode.
Boundaries / remaining acceptance
supported()remains zero and kernel launch remains a rejecting stub. Fake downstream consumption is not a production binder/event-protocol test.