Skip to content

[Feature] CCU 完整用户 kernel 接入方案:通信域、独立 mission、AIV 触发与生命周期 #2971

Open

Description

@ChaoZheng109

Summary

为 simpler 增加完整用户 CCU kernel 的运行支持:上层交付原生 HCOMM CCU kernel,simpler 在通信域内准备资源、注册 kernel,并在 L2 执行时为独立 mission 使用独立 stream 从 Host launch;用户 AIV kernel 通过 ISA 触发 CCU,动态参数随 AIV args 传入、组织成 CcuCallArgs,由提交接口发布后触发 CCU;使用 ready/trigger/done 三个独立 Event,单次操作完成接入 TMR 的 defer wait。第一版一个 L3 一个通信域,默认一个 kernel 对应一个 mission,只要求异步提交。

本文描述整体方案、各层接口职责、生命周期与技术验证状态,不安排负责人、并行任务或 PR 拆分。不修改 PyPTO;使用手写的等价上层产物验证交接接口。

Motivation / Use Case

相关实现为 #2954、#2955、#2956。当前方案需要避免把 simpler 扩展为用户通信算法的 codegen 框架:上层不应被要求使用受限的 CcuBuildContext,simpler 也不应把所有算法嵌入自己生成的 while/if 服务程序。

目标是让上层决定完整 CCU 控制流和通信逻辑,simpler 提供与现有 Worker、通信域、AIV 和异步完成机制一致的运行基础。用户能够启动多个独立 mission,并由设备侧工作流决定触发顺序,而非被 Host launch 顺序约束。

Proposed API / Behavior

1. 核心边界

  • 上层负责完整用户 CCU kernel:等待触发、通信算法、动态参数读取、循环次数、单次完成发布及正常退出。
  • simpler 负责产物加载、通信资源与内存准备、SDK 注册、Host launch、设备资源描述发布、完成适配、资源保活、错误报告和收尾。
  • simpler 不提供算法 DSL,不要求 CcuBuildContext,不生成统一算法分发 while/if,不以统一 dispatcher/CallFunc 作为本方案基础。
  • CCU 循环和 AIV 触发次数由用户配套 kernel 保证匹配。第一版同一 mission 最多一个未完成操作,用户通过 tensor 参数读写关系或显式依赖保证串行;依赖覆盖 CCU 异步完成,而不只是 AIV 返回。第一步不承诺检测漏依赖,第二步增加提交占用保护与报错。
  • 复用 ISA/HCOMM 的既有触发与同步机制;只补 simpler 运行时必要的适配,避免重新定义一套触发编码或请求队列。

2. 上层交付物与 callable

CCU 定义作为 ChipCallable 的附属产物,与原有 orchestration 和 AIC/AIV binaries 一同交付:

ChipCallable
  +-- L2 orchestration
  +-- AIC/AIV kernel binaries
  +-- CCU kernel definitions
        +-- Host module binary
        +-- native kernel entry / adapter entry
        +-- ABI and required metadata

这里的产物是已编译的 Host 模块及原生 HCOMM kernel 定义入口,不承诺加载任意离线 CCU 指令 bin。HCOMM 在注册阶段记录、翻译并下发指令的步骤仍存在;“simpler 不做 codegen”指 simpler 不定义和翻译用户算法。

模块入口接受已准备的资源绑定,提供原生 HCOMM kernel 定义。具体导出函数 ABI 需要在实现时确定,并校验版本、入口及必要元数据;不能重新引入携带算法操作的 builder context。

CCU 定义属于 L2 ChipCallable。第一版默认该 callable 的一个 kernel 对应一个本地 mission;ccu_id 按 callable 的 kernel 列表编号,不另行要求 mission 实例表。每次 L2 run 准备并 launch 当前 callable 的全部 CCU kernels,不因共享域而启动其他 callable 的 missions。用户无需重复传递 kernel 数量或待准备 callable 清单。实际硬件资源有上限,准备不足时明确失败,不能静默少注册或用串行队列冒充独立 mission。

区分三个对象:

对象 含义 生命周期
CCU 定义 上层模块、入口和描述 随 callable 管理
CCU 注册实例 定义绑定 device、domain、资源后的 SDK 注册结果 可随 domain 缓存、复用
CCU 执行实例 一次 Host launch 的 mission 与本轮 L2 AICPU/AICore 执行生命周期一致

同一个 kernel handle 换不同 stream 再次 launch,不等于已经获得两个独立并发实例。并发实例需要独立的 mission 和可变执行资源。

3. L3 Worker 与通信域

  • 第一版一个 L3 只有一个通信域,不支持按域选择 kernel group,不依赖 Add: configure A5 URMA jetties through workspace engines #2929;多通信域分组是后续扩展。
  • 保留 Worker.register(ChipCallable) 和普通 chip 任务提交路径。rank、rank 数、成员由建域配置确定,不重复传准备 rank 数量或 CCU handle 清单。
  • 建域通过 workspace_engines 声明 CCU 后端需求,不额外要求业务代码提供 ccu_callable、ccu_group_id、SDK/ISA build ID。构建兼容性由产物元数据与 runtime 校验,具体兼容规则随 ABI 明确。
  • runtime 在建域时为合法窗口取得、交换并保存各 rank 的 CCU 地址、范围和 token,发布设备可消费的描述;建域不 launch mission。
  • 实际依赖域资源的 HCOMM 注册,在 callable 与域关联后完成并可缓存。第一版每个本地 rank 建立到域内其他所有 rank 的 channel,提供按 peer rank 索引的表;kernel 选择实际使用的连接,不要求预声明 peer 子集。容量不足明确失败,不静默缩减连接范围。
  • orch.submit_next_level_group 不增加额外 CCU handle、实例清单或资源数量参数。callable/domain 关联与资源查找由 runtime 管理。
  • 多 rank 资源初始化必须共同推进,避免逐 rank 阻塞初始化造成互相等待;失败需要协调传播和回滚。这不意味着每轮执行增加跨 rank READY 屏障。

4. CCU workspace 与地址

当前 L2 callable 的 comm_ctx
  -> CCU workspace
       -> missions[ccu_id]
            ready / trigger / done 的地址和 mask
            参数承载区地址、容量等控制信息
            第二步增加的 owner 状态

ccu_id 的作用域是所属 L2 callable,不是 L3 全局编号。runtime 查找必须关联当前 callable 的资源表,不能混用不同 callable 的同号条目。用户不传硬件 mission ID,不手写 Event 地址。编译时确定的索引可直接放在 AIV wrapper 中,动态选择才需要随 args 传入。

workspace 管理控制资源、控制参数及必要的参数承载空间;tensor 地址、大小和本轮标量不要求在建域时预先配置。参数承载区容量如何声明、布局、对齐和发布 ABI 仍待确定,不承诺已经自动推导。用户业务通信窗口与后端控制/参数承载区须区分,不能照搬 URMA 的内部布局。

通信域管理逻辑窗口与后端访问描述。AIV 对端映射 VA、URMA 注册描述与 CCU 地址/token 不是同一种表示。CCU 使用对应窗口的地址/token 和相应 channel 执行通信;窗口凭据与 channel 分别管理,交换原始地址不会自动得到 AIV 可解引用的映射。

凭据必须针对合法范围且不得超出对应内存生命周期。真实 domain VMM 窗口与 HcommCcuGetMemToken、channel 的兼容性仍需验证。当前检查到的 ISA 统一 workspace 尚无 CCU 分支,HCOMM 提供底层资源原语;上述 workspace 描述表与查找属于待实现的适配能力。

5. 每轮业务参数与提交接口

user TaskArgs -> L2 orchestration -> AIV args
  -> AIV 构造 CcuCallArgs(tensor 地址、大小、标量等)
  -> submit(comm_ctx, ccu_id, call_args)
       -> 登记异步完成条件
       -> 发布本次参数并保证 CCU 可见
       -> ISA trigger
  -> 用户 CCU kernel 读取参数并执行

submit 是语义示意,不是已经冻结的 API 名称。可以采用 PyPTO 的 CcuCallArgs 参数组织方式;具体布局、发布/读取机制和用户 kernel 获取资源的 ABI 仍需共同明确和验证。

底层 ISA CkeTrigger(ckeSlotVA, mask, ubScratch) 只发送信号,不携带业务参数,ubScratch 也不是参数载荷。提交接口封装参数发布与触发,传递地址/大小/标量等描述,不复制 tensor 数据。Host launch 只提供必要初始信息,具体资源在注册时绑定还是经 taskArgs/LoadArg 注入,由 native ABI 确定;不另建每轮 Host 参数构造 DSL。

参数承载区及引用数据保持有效到实际完成,不因 AIV 返回就复用。同一 mission 的下一次写参数与触发须等前次完成并回收。第一版不提供队列、多槽或自动参数快照,也不要求 consumed Event;同一 AIV 内不能绕过回收条件连续提交。第一版只接入异步提交及 AICPU defer wait,不要求 AIV 同步等待接口。

6. L2 Worker、L2 Host 与卡内 READY

L2 Worker 解析 callable/domain 身份,管理本设备资源与 run 的 prepare/launch/poll/finalize;HCOMM/ACL 操作位于 L2 Host backend。

登记 callable 定义
  -> 与实际域关联,准备/复用 channel 和注册资源
  -> 发布 workspace 描述
  -> 在安全执行边界初始化本轮可变状态
  -> Host 在各独立 stream launch 本轮本卡 missions
  -> CCU 初始化后发布 ready
  -> 本地 AICPU 确认本轮所需 missions ready,清零并确认生效
  -> 放行本卡 AIV

simpler 只保证卡内 READY,不增加 runtime 跨 rank READY 屏障。算法所需跨 rank 初始化握手、同步及顺序由用户完整 CCU kernel 保证。Host launch 返回不是 ready 证明;Host 也不能先同步等待 CCU stream 结束再启动 AIV,否则会与等待触发的 CCU 死锁。

prepare 可以流水化,但不启动本轮 CCU,不提前改写上一轮仍使用的状态。CCU launch 归属本轮 L2 执行事务;具体接入需验证第 9 节的资源复用边界。

7. 多 mission 执行

Host launch A -> stream A -> mission A waits on gate A
Host launch B -> stream B -> mission B waits on gate B

AIV trigger B -> B executes/completes while A still waits
AIV trigger A -> A executes/completes

执行顺序由用户设备逻辑决定。独立 stream 还需配合独立 mission、事件和可变状态;通信算法本身的跨 rank 依赖仍须用户保证相容。

不承诺任意数量的 kernel、rank 或任意并发模式。mission、事件、寄存器、指令空间及 channel 都需要容量检查。注册和资源管理不应固定继承旧方案的“两 rank、一个 session 单槽请求”作为用户算法接口限制;具体支持范围需有验证证据。

8. L2 Device、Event 与 defer wait

每个 mission 使用三个独立硬件 Event,先各使用 bit0:

Event 发布方 消费方 含义
ready CCU AICPU 观察并整体清零 本地初始化完成,允许首次提交
trigger AIV CCU EventWait 消费清位 参数已发布,可开始执行
done CCU AICPU 观察并整体清零 本次通信及必要同步完成

算法内部搬运和跨 rank 同步事件另行分配。外部按 bit 选择性清零尚未验证成功,因此不同握手信号不能合并到一个 Event。正常路径不引入 GM ready/done sequence 状态机、consumed 或额外 recycle AIV。

设备编排仍提交普通 AIC/AIV 任务,通过 tensor 参数读写方向或显式依赖表达真实输入输出及同 mission 串行关系;把地址写入参数区不会自动让 TensorMap 发现依赖。

AIV 登记 AsyncCtx 完成条件 -> 发布参数 -> trigger -> 可以返回
CCU EventWait -> 读参数 -> 通信及必要同步完成 -> 发布 done
已有运行时确认普通执行完成且异步条件满足
  -> CCU 适配清除 done,并确认生效
  -> 退休条件、完成任务、释放依赖
  -> 下一次 AIV 才可复用参数和触发

复用现有 AsyncCtx 与 TMR defer wait,不另建 AIV FIN 检查。AICPU 直接观察/整体清 Event 的 SDK 探针已通过;完整用户 AIV + CCU + runtime 集成尚需验收,不能把探针当作已完成集成。

第一步只实现三 Event 正常协议,不承诺准确检测用户漏依赖导致的重叠提交。 超时不等于冲突检测,普通 Event 读后置位不是原子占用。

第二步再增加 workspace owner 和提交报错,不阻塞第一步。 每 mission 独立对齐的 owner 为 FREE 或本次提交标识,由 runtime 管理,不要求用户维护 operation_sequence。提交接口先准备可用的异步完成/错误记录,再在写共享参数前原子申请 owner:成功才写参数并触发;失败登记本任务的 CCU_SUBMIT_CONFLICT,不覆盖参数、不触发,不排队。用户 CCU kernel 不读取、不维护 owner。

CCU 专用错误只在 CCU defer-wait poll 中处理,不给每个普通任务 FIN 增加检查。失败提交也必须进入错误 completion;其回收不能清除赢家的 Event 或 owner。记录容量不足沿用既有登记失败处理。成功回收须校验 owner,清 done 并确认,再释放 owner 和任务依赖。trigger 前失败可安全回滚自己的资源,trigger 后失败不能直接释放占用。

原子类型、标识编码和 AIV/AICPU 可见性需要实现与硬件验证。该机制只检测实际重叠,不能保证发现时间上恰好串行的缺失依赖。

9. 生命周期、错误与退出

  • 用户负责 kernel 正常退出。mission 的本次执行不应作为域生命周期的永久服务跨 run 残留。
  • 单次操作完成允许相应任务结束 defer wait;整个 mission 退出才允许释放执行资源。两者不可混同。
  • 最后一次触发应先完成本次通信并发布相应完成,再正常退出。三次触发对应三次操作并退出是正常情况;第三次仅退出却不发布已登记的完成才是错误。
  • AICPU 对已登记但未完成的操作报告明确超时/执行错误,阻止依赖任务继续;它不需要也不能推断用户 kernel 实际循环了多少次。
  • AICPU/AICore 普通工作完成后,Host 对仍未退出的 CCU 做有界等待。CCU 可能尚在完成尾部工作,不能以瞬时未退出直接认定错误。
  • 超时日志包含 run、rank、domain、kernel/mission 以及已登记完成条件的实际状态;错误原因未知时不得直接断言“循环次数写错”。
  • 异常 mission 可尝试公开的 stream abort 能力,但必须保留原始运行失败,并确认停止范围与资源安全。abort 返回成功或 stream 标记完成不等于通信操作成功。
  • 当前测试已发现 abort 隔离风险,不能承诺只中止一个 mission 后其他 mission 可继续运行。整轮失败收尾、相关 mission 停止确认以及后续恢复仍需验证。
  • 在停止未确认时,不卸载仍可能使用的模块,不释放相关参数区、通信窗口或访问凭据。

跨 run 准备流水化与安全复用

沿用现有 L2 执行模型:准备可以流水化,设备执行串行。可变状态隔离与安全复用由 runtime 负责,不要求用户增加跨 run 依赖。

模块、注册资源、channel、窗口凭据及控制资源可缓存。prepare B 可以与 run A 重叠,准备 B 的独立 launch 参数和资源引用,但不得提前清 A 的 Event、重置 owner 或覆盖仍使用的参数槽;需要提前上传的参数使用独立存储。

run A 普通设备工作结束、异步记录退休
  -> 本轮所有 CCU streams 确认结束
  -> runtime 允许复用执行资源
  -> run B 初始化状态、launch CCU、卡内 READY、执行

单次 done 不是 mission 结束;同一 stream 的顺序不能代替 Host 状态写入和不同 stream 的协调。CCU stream 结束必须纳入 L2 run 切换条件。停止未确认时,B 即使已 prepare,也不得 launch 或重置相关资源,进入既定失败收尾。正常退出看 stream,不要求用户额外发布 EXITED 或实现固定 stop/final-wake 状态机。

Alternatives Considered

  • simpler 的 CcuBuildContext + 统一 while/if:要求 simpler 承担受限算法构建接口,且控制流归属不符合上层完整 kernel 模型,不采用。
  • 统一 dispatcher + CallFunc:已有相关 SDK 源码能力,但本方案直接 launch 用户完整 kernel,无需以跨 kernel 调用作为基础;不增加其共享调用资源和调度约束。
  • 每次业务通信由 Host launch:不符合 AIV 在设备侧驱动通信的目标。Host 负责本轮 mission 启动,内部操作由 AIV 触发。
  • 第一版同 mission 并发队列:暂不实现;当前 trigger 置位会合并,第一版采用单未完成操作与任务依赖,未来再适配可靠队列。

Additional Context

已验证的能力与证据

验证日期:2026-11-09。环境:Ascend950DT_9581、Linux aarch64、CANN 9.3.0;使用独立 checkout 和 task-submit 分配设备。基础 checkout 为 f0e7989ed1785b3fd5bffb4c7119469991d2a622,测试为单独编译的 SDK 探针,不代表此 checkout 已实现本文的 simpler 集成。

目标实际库已确认提供 CCU 注册、launch、事件地址查询、内存 token 和 aclrtStreamAbort 接口;探针编译链接成功。

验证内容 结果 边界
同 die、两个独立 stream 的原生 CCU kernel 通过 单设备、单 rank、两个 mission
先 launch A,再 launch B,先触发 B 通过 确认两个 mission 都开始执行;B 完成时 A 尚未产生结果
AIV 每次写入不同 GM 值,CCU 等待触发后读取 通过 每个 kernel 包含两次等待/读取,Host 观察对应结果
正常退出后复用注册结果重新 launch 通过 连续两轮,正常清理成功
单独 abort A 后让 B 继续 失败,复验一致 不具备已验证的 mission 中止隔离保证

正常测试任务:task_20261109_205330_56258414081,exit 0:

PASS reverse_trigger_dynamic_args_relaunch run=0
PASS reverse_trigger_dynamic_args_relaunch run=1
reset_device rc=0
finalize rc=0

探针逻辑:两个 kernel 均先写 ready 标志,再分别等待自己的 gate 两次,每次从 GM 读取值并写回结果。AIV 写参数后执行与 ISA 相同的 CKE 写入及同步机制。先给 B 输入 21、22 并确认 B 退出且 A 输出仍为 0,再给 A 输入 11、12;重复整轮。这里不把“直接包含 ISA 公共头文件”“真实跨 rank 数据通信”“完整 TMR 接入”或“任意用户循环”算作已上板验证。

异常测试任务:task_20261109_205443_57760118738;复验任务:task_20261109_205659_62429823587,均 exit 1。复验在 A/B 均进入等待后 abort A,记录 stream 状态,再触发 B 并等待明确的 5 秒:

abort_A_waiting_mission rc=0
aborted_A_sync rc=0
post_abort_stream_0 query_rc=0 status=0 complete_enum=0
post_abort_stream_1 query_rc=0 status=1 complete_enum=0
aiv_trigger rc=0
aiv_done rc=0
FAIL value timeout

观测结论仅为:A 被标记完成,B 仍未完成且无法按预期继续。尚未定位 SDK/驱动内部原因,不能直接断言其内部停止了全部 CCU 资源,也不能承诺故障后的无损恢复。

后续 Event 与触发语义实验(2026-11-10 补充)

以下仍为独立 SDK 探针,不代表 simpler 集成完成;详细过程见 Event 实验评论。

验证 结果与范围
CCU 被独立 hold 挡住时,AIV 两次置位同一 trigger 只消费一次,需额外触发才能通过第二次等待;否定自动排队。任务 task_20261109_211539_125392423186,exit 0;不是双核同时写测试
AICPU 直接观察 Event,重复读取及消费后再置位 task_20261110_101327_217500917805、task_20261110_101533_227068426871,exit 0;含 AICPU 先轮询、后触发和数据检查
AICPU 直接写映射 Event task_20261110_142315_9101210735,exit 0;不需要额外 recycle AIV
AICPU/AIV 写入与整体清零矩阵 task_20261110_142511_14598427528,exit 0;两方可整体清零,CCU 原生 EventWait 可按 mask 消费
ready 观察、重复完成与清零后硬件等待 task_20261110_142815_24438619976,exit 0;清零后 CCU 确实继续阻塞,重新置位才推进,确认不是读到软件影子值
外部按 bit 选择性清零候选编码 task_20261110_143513_49658612233 控制检查通过,但 24 个候选均未实现目标选择性清零;不能将进程 exit 0 解读为选择性清零成功

未覆盖任意并发 set/clear 竞争、真实跨 rank 通信或完整 TMR 集成;不宣称这些映射操作已成为 ISA/HCOMM 标准 AICPU API。早期 GM ready/done 与四 Event/consumed 方案均已由本正文三 Event 协议替代。11 月 9 日消费 ACK 探针部分语义通过但整体退出超时,不计为完整通过,也不是首版协议要求。

实施过程中必须完成的验证

  • 独立原生 kernel 注册与 Host launch。
  • 同 die 双 mission 并存及后 launch 先触发完成。
  • AIV 写 GM 参数、CCU 读取,以及正常结束后重复 launch。
  • 真实通信域窗口、CCU token、channel 和远端描述绑定;两 rank 起步验证实际通信及数据正确性。
  • domain 指定成员/子域的初始化与 rank 映射,不把基础双 rank 示例当作所有拓扑支持证明。
  • 多 kernel 资源需求汇总、实例容量配置、资源不足报告及部分失败回滚;不把 SDK 默认资源额度当作无限容量。
  • 使用项目 pin 的 ISA 入口完成实际触发适配,确认 SDK/ISA 版本兼容、首轮触发顺序与多轮事件语义。
  • 用户完整 while/有限循环与退出,CcuCallArgs 发布/读取 ABI、同 mission 串行请求、参数保活与完成后复用。
  • 真实 AICPU/TMR 完成检测、AIV FIN 后 pending、数据可见性、跨轮旧完成隔离与下游依赖释放。
  • 未发布完成、提前退出、触发与消费不匹配时的有界错误报告;复用现有超时机制并补足 CCU 定位信息。
  • 完整 L3 Worker -> L2 Worker -> L2 Host -> L2 Device 链路及直接 L2 入口的一致性。
  • mission 与本轮 L2 执行结束对齐,domain 参数区跨 run 复用及安全释放。
  • 定位/确认 stream abort 对其他 CCU mission 的影响范围;验证整轮失败收尾、停止证明及后续运行恢复。此项是已知失败点,不是已支持能力。
  • 准备流水化不覆盖上一轮可变状态;CCU stream 完成参与 run 切换,失败时阻止不安全复用。
  • 第二步:双 AIV 原子占用冲突、失败者不写参数/不触发、错误经 CCU defer wait 上报,以及回滚与 owner 校验;不阻塞第一步。

后续扩展(非第一版验收):多通信域 kernel 分组与 #2929 配置衔接、一 kernel 多 mission 实例、可靠队列及 AIV 同步等待。

参考

Activity

  1. YunjiQin commented on Nov 9, 2026

    @YunjiQin
    Collaborator

    想确认一个并发场景:如果两个不同的 AIV 同时 trigger 同一个正在运行的 mission、同一个 gate/event,实际会发生什么?尤其是第二次 trigger 到达时,第一次尚未被消费,或者 mission 仍在执行第一次通信。

    方案第 5 节已说明,mission 顺序执行不保证 trigger 自动排队或 GM 参数快照。那么这里的底层行为究竟是保留两次请求并串行处理、返回可检测的 busy/错误,还是事件可能合并/覆盖,导致某次触发没有对应执行且不立即报错?

    如果需要用户配套 AIV/CCU kernel 自行实现握手或多槽协议,能否明确同一 mission 的多生产者使用契约:如何避免参数覆盖,以及如何让两个 AIV 登记的 defer wait 分别对应自己的完成,避免一次完成误释放两个任务?目前列出的验证覆盖两个独立 mission,建议补充“两个 AIV 并发触发同一 mission”的验证,明确支持条件与不满足条件时的可观测结果。

  2. deleted a comment from lwDavid on Nov 9, 2026
  3. sunkaixuan2018 commented on Nov 9, 2026

    @sunkaixuan2018
    Contributor

    补充一下完成、run 状态、失败收口和原生 module ABI 这四项的实现契约。Yunji 已经提出同一 mission 多生产者的问题,这里不重复;domain VMM 窗口与 CCU token/channel 的验证也不在这条评论展开。

    1. CCU 完成接入 TMR

    每个执行中的 mission 使用独立 completion slot。同一个 mission 的不同操作用单调递增的 operation_sequence 区分;不同 mission 通过不同 slot 地址区分。completion 存储属于本轮 run,在所有对应 TMR condition 退休前不能复用地址。

    AIV 在 trigger 前登记一个新的 COMPLETION_TYPE_CCU:

    • CompletionToken.addr 指向该 mission 的 completion slot;
    • backend_cookie 保存期望的 64 位 operation_sequence;
    • engine 为 CCU;
    • expected_value 保留为 0,避免把 64 位 sequence 截断到现有 32 位字段。

    CCU 发布完成时,先写 status/native_error,完成数据可见性要求后,最后提交 completed_sequence。AICPU 的 CCU poll 规则固定为:小于期望值是 PENDING,等于期望值时按 status 返回 READY/FAILED,大于期望值是协议错误,不能用 >= 把跳号当成成功。失败必须阻止下游任务;retire 只退休本任务登记的 condition。

    单次操作完成和 mission 退出是两个状态。前者释放对应 TMR 依赖,后者才允许回收 stream、执行实例和 run 控制内存。

    2. 本轮 mission 状态和启动顺序

    每次 run 为每个 mission 分配一个控制块,至少包含 run_generation、mission_id、state、last_completed_sequence 和 error_code。状态按下面的方向推进:

    INIT -> LAUNCHED -> READY -> EXITING -> EXITED
                           \-> FAILED
    

    原生 kernel 只有在 task args、gate/event 和本轮参数区都可用后才能发布 READY。Host 先在所有 rank 上启动本轮全部 mission,再共同等待全部 READY,确认后才允许普通 AICPU/AIV 工作进入设备。HcommCcuKernelLaunch 返回本身不算 READY 证明。

    用户 kernel 仍自行决定循环和退出条件,但要响应 run 控制块中的 stop 请求,并在正常返回前发布 EXITED。如果 kernel 可能阻塞在 EventWait,stop 请求必须配套独立 stop gate 或可识别的最终 wake;只写一个 GM 标志不能唤醒正在等待的 mission。Host 的 bounded wait 观察的是 EXITED/FAILED 和实际 stream 停止证明,不用“暂时还没退出”推断循环次数错误。

    3. 失败范围和资源保留

    当前探针已经说明 abort 一个 mission 后,不能假设其他 mission 还能继续。因此首版按整轮失败处理:任一 mission 进入 FAILED、超时或需要 abort,本轮所有 CCU mission 停止接收新工作,所有相关 TMR 任务失败,不继续运行 sibling mission。

    如果所有 mission 都正常退出且各 stream 的物理停止得到证明,可以保留注册实例和 domain,下一轮重新 launch。只要存在 timeout、abort 后停止范围不明或 stream 完成未确认,就把本轮标记为 unconfirmed,停止该 domain 的新 CCU admission,并继续持有 module、stream、参数区、通信窗口和 token。只有后续取得完整停止证明,或执行经过验证的 device reset/进程 teardown,才能释放这些资源。

    错误报告保留最早的业务/执行错误;清理或停止失败作为附加信息,不能覆盖原始错误,也不能被解释成通信成功。

    4. 原生 Host module ABI

    module 使用版本化 C/POD ABI,不把算法操作做成 simpler 回调,也不再暴露 CcuBuildContext。建议固定两个导出面:

    1. module manifest:返回 ABI version、struct size、SDK/PTO-ISA build identity、kernel 数量和 kernel records;
    2. kernel definition entry:由 simpler 解析符号后直接交给 HCOMM 完成 query/register。

    每个 kernel record 至少包含 callable-local kernel_id、所属 group、entry symbol、task-argument layout version、参数区大小与对齐、能力 flags。所有 reserved 字段必须为 0;未知版本、未知 flag、重复 ID、越界字符串或不匹配的 build identity 在 domain prepare 前失败。

    simpler 负责从 callable 的精确字节加载 module、校验 manifest、查询和分配资源、注册 kernel、创建 stream、launch、停止及保活。module 只定义原生 CCU 控制流和通信算法。C ABI 边界禁止异常穿出,上传/发布的数据结构不得包含 Host 指针。

    这类 module 是可信 Host 代码,不提供 sandbox。缓存身份需要覆盖 module 字节、manifest、entry、SDK/PTO-ISA build identity;使用 RTLD_LOCAL,并保证实际 dlopen 的字节与计算身份的字节一致。

    以上四项确定后,首个实现 PR 可以先冻结 module/descriptor/completion ABI;Worker、domain 和硬件执行分层接入,不需要再回到统一 builder/service-program 模型。

  4. ChaoZheng109 commented on Nov 10, 2026

    @ChaoZheng109
    CollaboratorAuthor

    @YunjiQin 针对这里提出的同一 mission 多生产者问题,我们补查了 PTO-ISA、HCOMM/HCCL 和 RTS 源码,并做了几组独立硬件实验。结论是:当前 AIV trigger 是事件置位,不是一次有独立参数快照的任务入队;第一版先不支持同一 mission 的并发提交,采用用户任务依赖 + 显式消费确认,后续再接入 ISA 的可靠队列。

    底层行为

    PTO-ISA 的 CkeTrigger 向 CCU Event 的映射地址写入 (1ULL << 63) | mask,并执行同步;mask 是事件位集合,不是请求次数。HCOMM 的 EventWait 等待指定事件位,满足后清位。消费前重复设置同一位不会累计请求次数;如果第二次置位在第一次消费清位后生效,则可以留给后续等待。关键是事件消费时序,不是 mission 是否仍在进行上一轮通信。

    当前 ISA 触发封装没有消费 ACK、请求队列或 busy 检查。不能依赖重复触发立即报错;有可能只观察到少了一次执行,最终等待对应完成的任务超时。普通 GM 参数槽也没有自动快照。

    这与 Host HcommCcuKernelLaunch -> rtCCULaunch 不同:后者会为每次调用生成带参数的 stream 任务/SQE。同一 stream 的有序下发机制不能直接套用到 AIV 写 CKE;同一 kernel handle 跨 stream 重叠 launch 的自动仲裁保证也尚未确认。

    实验结果及边界

    环境为 Ascend950DT_9581、Linux aarch64、CANN 9.3.0,使用隔离 SDK 探针和 task-submit。探针手写了与 ISA 相同的 CKE 写入机制,未直接调用项目 pin 的 ISA 封装,也未接入实际 TMR/defer wait。

    实验 结果 能证明的范围
    同 die 两个独立 mission:先 launch A、再 launch B,先触发 B;每个 mission 两次动态参数读取,正常退出后重复一轮 task_20261109_205330_56258414081,exit 0 B 可在 A 等待时先完成;独立 mission 的反序触发、参数读取和正常重启可行,不代表任意并发容量
    先用独立 hold 事件阻止 CCU 消费目标事件,再对同一目标 gate/mask 写两次,最后释放 hold task_20261109_211539_125392423186,exit 0 只通过一次目标 EventWait;额外触发第三次才通过第二次等待。两次预置触发不累计
    同一次 AIV 执行中,提交参数 1001、等待 ACK=1,再复用参数槽提交 1002、等待 ACK=2 task_20261109_230026_6957287823,两项语义检查 PASS,但整体 exit 124 两次请求分别消费,参数都正确;第二次 ACK 后刻意阻塞 CCU 后续输出,AIV 仍能退出,说明接收确认可与最终完成分离。清理接口均返回成功,但进程退出超时原因未定位,不能把整项测试记为完全通过
    abort 等待中的 A,再触发独立 B task_20261109_205443_57760118738、task_20261109_205659_62429823587,均 exit 1 A abort/sync 成功,但 B 未按预期继续;不能承诺单 mission abort 的隔离性,内部原因未定位

    重复置位实验的 AIV 路径是两次独立的单 block AIV kernel 调用,每次写一次,Host 等待前一次 AIV 完成后再调用下一次;CCU 在这两次调用期间始终被 hold 挡住。它不是两个 AIV 核同时写的测试,但已经否定“底层自动保留每次 trigger”的假设。真正的双 AIV 同时提交及所有竞争时序尚未覆盖。

    ACK 实验之前的两版探针在注册阶段失败,未进入握手验证;专用日志定位到 SDK 翻译 CCU Add 指令报错。最终改成无加法的两次固定请求才完成上述语义检查,不将通用计数循环算作已验证能力。

    第一版使用契约

    第一版不实现请求队列,不支持同一 mission 的多个 AIV 并发提交。不同 mission 的独立执行不受此限制,但仍需满足数据依赖、资源隔离和硬件容量要求。

    1. 用户在触发同一 mission 的 AIV 任务之间建立依赖,保证提交不重叠。同一次 AIV 内多次触发,也必须逐次等待消费确认。这个限制是首版提交协议的限制,不是“相同 kernel 名称天然存在数据依赖”。
    2. AIV 写入参数并保证可见后触发,然后等待本次独立序号的消费 ACK,收到后才返回或复用参数槽。不能用 pipe_barrier 或 AIV stream 完成代替消费 ACK。
    3. 配套用户 CCU kernel 必须执行 EventWait -> Load/保存本次需要的参数 -> 发布 ACK。仅修改 AIV 不够;ACK 不能早于参数取走。使用现有 HCOMM 原语发布 GM 确认,不改变 CKE 硬件编码,不依赖未验证的 gate 清零读回协议。
    4. 消费 ACK 与通信完成分开。ACK 只允许回收已取走的请求参数;参数指向的输入输出数据仍需保活到实际通信完成。CCU 完成通信并满足数据可见性要求后,再发布对应完成条件供 defer wait 使用。
    5. 完成条件必须区分 mission、本轮 run 和本次操作,不能用共享布尔完成位让一次完成误释放两个任务。具体 completion ABI、轮次复用及 AICPU 观察规则仍需实现和验证;本条回复不将其他评论中的具体字段和判定规则视为已验证。
    6. 违反首版提交约束属于不支持的用法,不能承诺底层提供即时 busy/并发错误。ACK 等待和最终完成等待都需要有界超时与可定位错误,不能无限自旋。实际 TMR 任务依赖若等待最终 defer wait 完成才放行后继,首版接受这种更强串行化,不承诺 ACK 后即可提前调度下一任务。
    AIV task 1: 写参数 -> trigger -> 等消费 ACK -> AIV 返回
                         CCU: 等事件 -> 取参数 -> ACK -> 通信 -> 完成通知
                                                                      |
                                                       满足任务依赖后放行
                                                                      v
    AIV task 2: 写参数 -> trigger -> 等消费 ACK -> AIV 返回
    

    上述首版契约取代正文中“不限制一个 mission 的未完成触发数”和不强制握手的宽泛表述;这里限制的是提交/参数消费协议,ACK 不等于通信完成。实现验收仍需补齐直接 ISA 调用、真实 TMR 完成适配、超时路径及 ACK 探针退出异常。

    后续演进

    后续推进 ISA 提供统一的 AIV 多生产者提交与 CCU 消费协议,再由 simpler 适配,逐步取消仅因共享 mission 而要求的任务依赖。当前 ISA 已有 A5 GM atomicAdd 计数用法,但完整 CCU 请求队列尚未实现、未上板验证。

    队列需要保存每次参数,区分申请序号与请求已就绪,处理容量、回收、发布顺序和通知竞态;CKE 只负责唤醒,不能作为请求数本身。AIV 入队后一般无需逐请求等待消费 ACK,但仍需消费进度回收槽位,以及独立的最终完成通知。建议 ISA 统一设备侧协议,simpler 管理域内队列内存、生命周期和 TMR/HBG 完成适配,避免为不同 runtime 各建一套提交协议。

    参考源码:ISA CkeTrigger、ISA A5 原子计数、HCOMM EventWait 翻译、RTS CCU 任务提交。

  5. ChaoZheng109 commented on Nov 10, 2026

    @ChaoZheng109
    CollaboratorAuthor

    @sunkaixuan2018 针对你前面提出的完成通知和启动状态方案,补充一下我们的实验结果及第一版边界。

    当前倾向是第一版先采用一个最小的 GM 状态协议,把首次触发和单次完成通知跑通,但将其明确定位为过渡方案。

    从职责边界看,simpler 应负责 CCU kernel 的注册、launch、资源生命周期以及异步完成接入,不应维护与用户 CCU kernel 内部逻辑绑定的状态机。理想情况下,这些交互应由 ISA/HCOMM 提供标准接口,上层生成的 kernel 和 simpler 分别使用同一套接口。目前这条链路还不完整,因此我们先补最小协议,不扩展成完整的 READY/STOP/EXITED 等状态机。

    我们已在 a5dt(Ascend950DT、CANN 9.3.0)验证了硬件 Event 路径,两轮实验均正常退出:

    • Host 通过 HcommCcuEventAlloc/GetAddr 分配、映射事件,CCU 绑定同一个 Event。
    • AICPU 可以直接读取事件,观察到 CCU EventRecord(done) 发布的完成位。
    • AICPU 先轮询、AIV 后触发时,能够观察到 0 → 1;看到完成后,CCU 写入的数据校验通过。此时 CCU mission 仍未结束,说明可以观察单次完成,而不必等待 stream 结束。
    • AICPU 重复读取不会自动清位。由 CCU 执行 EventWait(done) 清位后,AICPU 能观察到 0,再次触发后又能观察到 1。

    因此,硬件 Event 的完成观察能力已经验证。当前缺口是消费后的回收:尚未找到并验证 AICPU 直接清位的接口,不能断言硬件不支持。 已验证的回收方式需要额外 AIV 发控制信号,再由 CCU 清位,会增加控制流程和调度开销。首次触发方面,GM ready 握手已跑通;使用硬件 ready Event 的完整启动流程尚未单独验证。

    基于这些结果,建议第一版只保留:

    • ready:CCU 完成必要初始化后发布,AICPU 据此放行首次 AIV。
    • done_seq:CCU 在本次通信及必要同步完成后发布,AICPU 按期望序号解除 defer wait。

    另外,单次触发完成和整个 mission 结束分开处理:前者通过 done_seq 等完成协议通知 AICPU,供 defer wait 解除任务依赖;后者由 Host 观察该 mission 所属 stream,通过 aclrtStreamQuery 查询或 aclrtSynchronizeStreamWithTimeout 有界等待,并检查错误。正常结束路径不要求用户 CCU kernel 额外发布 EXITED 状态。这里要求 stream 的任务范围明确;若其后还排有其他任务,stream 完成也包含这些任务。超时不代表 mission 已停止,不能仅凭超时释放它仍可能访问的资源。

    这仍然是一个需要上层 kernel 配合的临时契约。资源由 simpler 管理,状态发布尽量封装为统一辅助接口,避免让用户手写状态维护细节。后续优先推动 ISA/HCOMM 补齐标准的就绪、完成观察及回收接口,再替换这层临时协议。

  6. ChaoZheng109 commented on Nov 10, 2026

    @ChaoZheng109
    CollaboratorAuthor

    补充 CCU kernel 分组与 #2929 的依赖边界:按通信域选择 CCU kernel 组不要求第一版实现,也不作为第一版 CCU 接入的合入前置条件。

    第一版默认注册用户在 callable 中提供的全部 CCU kernel,不提供按不同通信域选择不同 kernel 集合的能力。这一限制指 kernel 集合的选择能力,不意味着不同通信域共享同一份执行状态或底层通信资源。

    后续待 #2929 合入,再复用其 workspace_engines 通信后端配置入口,增加 CCU kernel 分组及选择能力:上层 callable 提供多组 kernel,创建通信域时通过 CCU 后端 config 指定该域使用哪一组。具体配置字段届时确定,不另建独立的选择接口。

    这项后续扩展不改变已有原则:用户提供多少 kernel,就注册对应的 kernel;参与 rank 从通信域成员配置推导,不要求用户额外声明 CCU handle 数量或重复声明 rank 数量。本条说明调整正文中“#2929 后支持多通信域 kernel 分组”的分期含义,避免将其理解为整个 CCU 第一版都必须等待 #2929。

  7. ChaoZheng109 commented on Nov 10, 2026

    @ChaoZheng109
    CollaboratorAuthor

    @YunjiQin @sunkaixuan2018 请确认下面更新后的 Event 交互方案及边界。本条替代我此前提出的“先用最小 GM ready/done_seq 状态协议跑通”的过渡方案:最新实验已验证 AICPU 可以直接读、置位和清空硬件 Event,因此不再需要为 ready、消费确认、单次完成另建 GM 状态协议,也不需要额外的 recycle AIV。 GM 仍用于业务参数和数据。

    最新硬件验证

    环境:a5dt、Ascend950DT、CANN 9.3.0。独立 SDK 探针,不代表 simpler 已完成集成。

    • task_20261110_142315_9101210735:AICPU 写 Event 触发 CCU,并通过回收事件驱动 CCU 清位,exit 0。
    • task_20261110_142511_14598427528:CCU/AIV/AICPU 三方操作矩阵,exit 0。AIV 与 AICPU 均能读取、置位,以及通过写 0 清空测试事件;三方观察一致。置位 bit0 保留已有 bit1;CCU EventWait(mask) 能只清指定 bit。
    • task_20261110_142815_24438619976:直接清位闭环,AICPU 清位与 AIV 清位两个对照均通过,exit 0。CCU 发布 ready 后,AICPU 观察 ready 再触发;两次操作完成及数据校验通过,观察期间 mission 保持运行。清位后特意让 CCU 执行原生 EventWait,确认其持续阻塞,重新置位后才继续并写出最终结果,证明清除的是实际事件状态,不只是读回值。
    • task_20261110_143513_49658612233:AICPU/AIV 各测试 12 组选择性清位候选编码,共 24 组,正常退出、控制检查通过,但没有一种得到“清 bit0、保留 bit1”的结果。初始为 0b11 时写 0b10 仍为 0b11,写低 16 位反掩码得到 0xffff。目前只把外部整体清零列为已验证能力,不承诺 AICPU/AIV 按 bit 清位;也不据有限探测断言硬件不存在其他机制。

    这些是当前硬件和 SDK 上的实测能力,尚需封装为 ISA/platform 接口并确认版本支持,不能把探针中的寄存器访问直接当成已经存在的公共 ISA API。

    每个 mission 的资源

    每个独立 mission 分配 4 个独立 Event,先各使用 bit0:

    Event 发布方 观察/消费方 含义
    ready CCU AICPU 观察并清零 必要初始化完成,可以接收首次请求
    trigger AIV CCU EventWait 消费并清位 提交一次请求
    consumed CCU AIV 观察并清零 本次所需参数已取走
    done CCU AICPU 观察并清零 本次通信及必要同步完成

    虽然一个 Event 有多个 bit,但外部直接清位当前只验证了整体清空,因此不将独立握手信号合并到同一个 Event,避免清掉另一方仍需观察的信号。通信算法内部的搬运/跨 rank 同步事件另行计入资源需求,并检查硬件容量。

    Event 随注册实例所绑定资源管理,每轮 run 在安全停止边界初始化状态;每个 mission 的触发、完成资源和可变参数存储独立。Host 将 Event 句柄绑定给原生 CCU kernel,将需要的映射地址发布到设备实例描述。AIV 通过实例描述选择触发资源,不需要直接操作硬件 mission ID。

    首次触发

    确认上轮相关执行已停止
      -> 初始化本轮事件状态
      -> Host launch CCU mission
      -> CCU 完成必要初始化并 EventRecord(ready)
      -> AICPU 观察 ready,清零并确认生效
      -> 放行首次 AIV 提交
    

    ready 必须位于用户 kernel 接受请求所必需的初始化之后;算法若需要前置的跨 rank 初始化,也应完成后再发布。不用固定 sleep,也不把 Host launch 返回当作 ready 证明。

    单次提交、完成和复用

    AIV:
      登记本次 done 完成条件
      -> 写业务参数并保证可见
      -> 置位 trigger
      -> 等待 consumed
      -> 清零 consumed 并确认生效
      -> AIV 返回,任务仍可处于 defer wait
    
    CCU:
      EventWait(trigger),消费触发位
      -> 读取/保存本次所需参数
      -> EventRecord(consumed)
      -> 执行用户通信逻辑
      -> 等待搬运及算法要求的跨 rank 同步完成
      -> EventRecord(done)
      -> 等待下一次请求,或按用户控制流正常退出
    
    AICPU:
      本次任务完成必须同时满足 AIV 已返回和 done 已观察到
      -> 清零 done 并确认生效
      -> 退休完成条件,标记任务完成并释放依赖
      -> 才允许同一 mission 的下一次 AIV 提交
    

    清位必须先于释放依赖,避免上一次 retire 清掉下一次操作刚发布的完成。消费确认与通信完成仍然分开:consumed 不代表通信完成,输入输出数据必须保活到实际完成。

    之前已明确的首版“同一 mission 的提交建立依赖、AIV 等待消费确认”保持不变。这里把确认载体改为独立硬件 Event;不引入并发请求队列,不以 Event 位代替请求计数。重复使用同一组事件,以相应消费方完成清位作为下一次使用的前提。不能在同一次 AIV 中绕过该回收前提连续复用同一个 done;如需这样的批内多次提交,必须另外定义逐次完成/回收或独立槽位,不能默认得到支持。

    接口职责与结束处理

    上层/用户 CCU kernel 仍需要表达“已就绪、已消费参数、单次操作已完成”这些外部协议点,但不应手写地址映射、缓存维护、寄存器编码和清位细节。用统一辅助接口封装,后续由 ISA 承接标准 record / poll / clear / wait 能力;simpler 管理资源、描述发布、调度及 defer wait 适配,不分析用户算法或生成统一 while/if 服务程序。

    单次完成不等于整个 mission 结束。最后一次操作应发布 done 后按用户控制流退出;整个 mission 的结束由 Host 查询/同步所属 stream 并检查错误,正常路径不要求用户额外发布 EXITED。超时不等于已停止,停止未确认时不能释放或重置仍可能被访问的资源。

    集成验收边界

    基础三方 Event 操作、直接清位、硬件 ready 观察和重复完成已验证。完整的用户 AIV + CCU + simpler AICPU 协议仍需端到端验收,覆盖 consumed 的发布/观察/清位、AIV 返回与 done 的不同先后顺序、先 retire 后放行、连续多轮和跨 run 旧状态隔离,以及超时/错误收尾。现有测试是单 rank、串行操作,不把它扩展为任意并发或真实跨 rank 通信的保证。

    请两位重点确认:四个 Event 的归属、清位先于释放依赖的规则,以及将交互动作封装为基础库接口、而非让用户维护 GM 状态机的职责边界。

  8. sunkaixuan2018 commented on Nov 10, 2026

    @sunkaixuan2018
    Contributor

    PR1~PR5 开发计划(当前)

    整体边界:用户提供包含一个或多个完整原生 CCU kernel 的 module;simpler 不生成通信算法,只负责 module/资源管理、HCOMM 注册、mission launch、完成接入、停止和保活。

    1. PR1:原生 ABI 与打包(Add: define native CCU module and three-Event ABI #2974)——定义 module manifest、kernel record、固定 launch 参数、每 mission 独立 completion slot,以及精确字节加载和校验。
    2. PR2:Domain 准备与注册——在每个通信域内准备 CCU instance、channel/event/token/window,完成多 rank query/register/assign 和失败回滚。
    3. PR3:TMR 完成接入——AIV 先登记 completion,再发布动态参数和 trigger;AICPU 按 64 位 sequence 精确 poll/retire。
    4. PR4:Mission 生命周期——每 mission 独立 stream/control/gate/slot;全部 rank、全部 mission READY 后放行;失败时整轮停止,停止未确认则保留资源。
    5. PR5:Worker 端到端——串起 Worker.register(ChipCallable) -> domain prepare -> launch -> 普通任务/TMR -> close,用两个独立 mission 验证 B 先完成、A 后完成,并覆盖复用、失败和资源保留。

    首版明确限制:同一 mission 同时最多一个未完成操作;不支持同 mission 多生产者、trigger 排队、GM 参数快照或多槽协议。不同 mission 可以并行。

    当前 PR1 已 Ready for review;真实 A5 已验证 native query/register/assign,以及 launch -> READY -> AIV trigger -> completion -> final wake -> EXITED -> stream complete。下一步完成正式 Worker 纵向用例,再使用同一可配置用例执行 16 轮日常验证和 1,000 轮验收。

  9. YunjiQin commented on Nov 10, 2026

    @YunjiQin
    Collaborator

    结合最新 Event 方案,想再明确三个用户接口问题:

    1. 不支持并发 trigger 同一个 mission 时,如何向用户报错? 首版限制已经明确,但如果用户漏加依赖,两个 AIV 实际并发提交,是否会在提交前检测并拒绝?由哪一层检测、返回什么错误、如何定位到相关 mission/AIV 任务?目前只说明底层没有 busy 检查、消费确认和完成等待需要有界超时;超时未必能区分并发违规与通信故障,也尚未说明参数被覆盖或完成信号被误匹配的情况能否可靠检测。请明确首版提供的是主动违规检测,还是仅有超时兜底,以及无法检测的边界。

    2. CCU mission 是否必须由用户 kernel 控制正常退出,具体需要配合什么协议? 我的理解是用户决定循环次数/退出条件,最后一次操作发布 done 后返回,Host 通过所属 stream 确认结束。最新 Event 方案说正常路径不需要额外发布 EXITED,但此前契约要求响应 stop、配套 final wake 并发布 EXITED,后面的开发计划仍保留这条路径。请统一:用户只需正常返回,还是必须实现 stop/final wake/EXITED?正常退出与异常停止分别由谁负责?

    3. 动态参数是否必须经过 GM,能否通过映射的 CCU 寄存器传递? 当前理解是 Host 提供稳定的 GM 参数区地址,每次 AIV 写入本次输入/输出 tensor 地址、长度等,再 trigger,CCU 读取后发布 consumed;并非 launch 时固定每次操作的 tensor 地址。请确认这一理解,并评估能否用 HcommCcuVariableAlloc / HcommCcuVariableGetAddr 预留、映射 CCU XN 参数寄存器,由 AIV 每次写入地址/长度后再触发,CCU 绑定并读取同一批 Variable。这不同于 Host launch 时通过 LoadArg 初始化寄存器;需要验证目标 SDK 下 AIV 的访问能力、写入与 trigger 的顺序、参数消费及覆盖保护,不能仅凭地址查询接口认定已支持。相关接口见 HCOMM 源码 和 Variable 资源预约说明。若首版仍选 GM,请说明寄存器路径的限制或尚缺的验证。

    也请将最终结论同步到正文和开发计划,避免 Event 与 GM sequence、stream 结束与 EXITED 两套契约并存。

  10. ChaoZheng109 commented on Nov 10, 2026

    @ChaoZheng109
    CollaboratorAuthor

    @YunjiQin @sunkaixuan2018 补充明确实现顺序:第一步只实现三 Event 的正常交互与 defer wait 接入;第二步再增加 workspace 中的提交占用状态和非法重叠提交报错。第二步不作为第一步合入的前置条件。 请确认以下接口与职责边界。

    第一步:Event 正常执行协议

    每个独立 mission 使用三个独立硬件 Event,各先使用 bit0:

    Event 发布方 消费方 含义
    ready CCU AICPU 观察并清零 必要初始化完成,允许首次提交
    trigger AIV CCU EventWait 消费清位 请求参数已发布,可开始执行
    done CCU AICPU 观察并清零 本次通信及必要同步完成

    simpler 只保证卡内 READY。 本地 AICPU 确认本轮所需 CCU missions 的 ready Event 后放行 AIV;不增加 runtime 跨 rank READY 屏障。通信算法所需的跨 rank 初始化握手、同步与执行顺序,由用户提供的 CCU kernel 保证。

    三方 Event 操作的硬件证据见前面的实验评论。AICPU/AIV 的外部整体清零已经验证;按 bit 选择性清零尚未验证成功,因此不把独立握手信号合并到一个 Event。算法内部搬运/跨 rank 同步事件另行分配和计入容量。

    这里不引入 consumed、busy/owner 或 GM ready/done 状态机,也不增加 recycle AIV。首版由用户为同一 mission 的提交任务建立依赖,依赖等待整个异步任务完成,而不是只等 AIV 返回;下一次参数写入也必须受该依赖约束。

    执行流程:

    Host 准备事件和描述,在安全执行边界初始化本轮状态
      -> Host launch 本轮本卡 CCU missions
      -> 各 CCU mission 完成必要初始化,发布 ready
      -> 本地 AICPU 确认本轮所需 missions ready、清零并确认生效
      -> 放行本卡 AIV
    
    AIV 登记 done 完成条件
      -> 写本次参数并保证可见
      -> 置位 trigger
      -> AIV 返回,任务进入现有 defer wait 生命周期
    
    CCU EventWait(trigger)
      -> 读取参数
      -> 执行用户通信
      -> 完成必要搬运及跨 rank 同步
      -> 发布 done
    
    已有运行时确认普通子任务执行完成且异步条件满足
      -> CCU 完成适配清零 done,并确认生效
      -> 退休完成条件、完成任务、释放依赖
      -> 下一次 AIV 才能写参数并触发
    

    参数槽及参数指向的数据保活到实际完成;不因 AIV 返回就复用。任务完成继续复用公共调度机制,不为 CCU 另建 AIV FIN 检查。正常 mission 退出由 Host 查询/同步所属 stream 并检查错误,不要求用户发布 EXITED。超时不是停止证明,相关资源停止未确认时不得回收或重置。

    第一步不承诺可靠检测用户漏依赖导致的重叠提交。 仅回读 trigger/done 不能可靠判断占用,也不能解决两个 AIV 同时检查再置位的竞争。超时诊断不等于准确的提交冲突检测。

    资源入口:CCU workspace

    以下范围与参数边界按与 PyPTO #3281 对比后的结论更新。

    第一版一个 L3 只有一个通信域。 用户通过 L2 callable 提供 CCU kernel 列表,各 L2 worker 准备自己的本地注册与 launch 资源。用户提供完整的等待触发、执行、循环和退出逻辑,simpler 不生成常驻循环或通信算法。

    第一版默认一个 kernel 对应一个 mission,ccu_id 是所属 L2 callable 的 CCU kernel 列表索引,同时用于选择对应的本地 mission。不要求用户提供额外的 mission 实例表,也不另行暴露 mission_index。多实例配置与多通信域分组不属于第一版范围,不依赖 #2929。

    Event 与必要参数承载区的实际地址由 simpler 准备,通过 CommContext.workspaces[CCU] 的地址/大小描述提供设备端 CCU workspace 入口,不在 CommContext 顶层继续追加 CCU 专属字段,也不由 orch 逐项塞进用户 AIV 业务 args。

    当前 L2 callable 的 comm_ctx
      -> workspaces[CCU] = {addr, size}
           -> CCU workspace
                -> missions[ccu_id]
                     ready / trigger / done 的映射地址和 mask
                     参数承载区地址、容量等控制信息
    

    ccu_id 的作用域是所属 L2 callable,不是整个 L3 的全局编号。workspace 查找必须关联当前 L2 callable 的资源表,不能把不同 callable 的相同索引混为一组资源。硬件 mission ID、SDK handle、stream 由 simpler/HCOMM 管理。编译时固定的 ccu_id 可固化在 AIV wrapper 中,只有动态选择时才需要随 args 传递;用户不需要手写 Event 地址。

    AIV kernel 编号与 ccu_id 相互独立,不要求一一绑定。 同一个 AIV 可以提交多个不同 mission,也可以根据业务参数动态选择;不同 AIV 可以选择同一个 mission,但仍须满足前述串行提交约束。不要求用户声明 AIV→CCU 绑定表,也不要求 AIV wrapper 与 CCU kernel 列表由同一个生成过程产生。调用方遵守 callable-local ccu_id 的选择约定,runtime 按该列表顺序发布对应资源,不按 SDK 注册顺序或硬件 mission ID 重新编号。

    simpler 不分析 AIV 控制流来推断它会选择谁、触发几次,也不分析 CCU 内部的通信、循环和退出逻辑;它负责资源配置、交接 ABI、提交校验、完成登记和生命周期管理。

    参照 URMA,workspace 字段应以设备侧的实际用途为依据,明确谁读、谁写及使用阶段:

    内容 设备侧消费者与用途
    布局版本、结构大小 提交/完成辅助接口校验描述格式
    mission 数量、描述表入口 AIV 解析 ccu_id 并检查范围
    参数区地址、容量及必要对齐信息 AIV 校验并发布参数;CCU 按交接 ABI 读取
    ready Event 地址/mask 本地 AICPU 检查就绪并清位
    trigger Event 地址/mask AIV 触发所选 mission
    done Event 地址/mask AICPU 检查完成并清位

    仅供 Host 使用的 module owner、注册缓存、SDK handle、stream 和析构信息保留在 Host 管理对象中。身份、generation、地址/token 等其他字段,也应按实际设备校验、诊断或访问用途决定是否发布;仅供注册或 Host launch 消费的信息不必复制到设备 workspace。workspace 可以引用其他设备存储,不要求所有资源物理上位于同一块内存。

    当前检查到的 ISA 统一 workspace 尚无 CCU 分支,HCOMM 提供的是实例/资源池、注册和 Event 分配映射原语。因此描述表及设备查找接口属于需要补齐的适配能力,不是已有接口。

    workspace 准备控制资源、控制参数和必要的参数承载空间;tensor 地址、大小、本轮标量等业务参数仍随 AIV args 传入,可以采用 PyPTO 提出的 CcuCallArgs 组织本次调用,不要求用户在创建通信域时预先配置每轮 tensor 参数。

    AIV args:tensor 地址、大小、本轮标量等
      -> AIV 构造 CcuCallArgs
      -> submit(comm_ctx, ccu_id, call_args)
           -> 检查 ccu_id 与参数范围,解析对应 mission 描述
           -> 登记本任务的 done 完成条件
           -> 将本次参数发布到 CCU 可读取的位置,保证可见
           -> 写对应 mission 的 trigger Event
      -> CCU 读取本次参数并执行
    

    这里 submit 是接口语义示意,不是已实现的 API 名称。底层 ISA CkeTrigger(ckeSlotVA, mask, ubScratch) 只发送触发信号,不携带 kernel 参数,ubScratch 也不是参数载荷。参数发布与触发由提交接口封装;传递的是地址、大小和标量等描述,不复制 tensor 数据。参数承载区及所引用的数据在实际完成前保持有效,不能被下一次请求提前覆盖。

    同一 AIV 选择两个独立 mission 的示意如下;两份参数按各自 kernel 的约定组织,不传硬件 mission ID 或由用户维护的 operation_sequence:

    // 示意接口,名称和具体 ABI 尚未定案。
    submit_ccu(async_ctx, comm_ctx, 0, params_a);
    submit_ccu(async_ctx, comm_ctx, 2, params_b);

    两次提交分别登记完成条件。该 AIV 所属任务需等待普通执行和全部已登记异步操作完成,才能释放下游依赖;不同 mission 的完成顺序不由这两条提交语句保证。上述 0、2 也可以来自 AIV args。

    Host launch 提供本轮执行所需的初始信息,例如参数承载区地址和必要 token;每次业务参数仍由 AIV 发布。CCU 按注册/launch 的交接 ABI 取得所需资源,不要求用户 CCU kernel 解析整个 workspace。

    CcuCallArgs 布局、参数发布/读取方式,以及用户 CCU kernel 如何取得 Event 和参数资源,仍需明确具体 ABI 并验证。CcuCallArgs 描述本次调用,workspace 提供对应 mission 的控制资源及参数承载,两者不是替代关系。

    第一步的 workspace 只需提供正常执行所需描述;下面的原子占用状态留到第二步增加。

    通信域准备与 CCU 注册、launch 分离

    结合 PR #2986 的职责划分讨论,明确以下准备与执行边界。

    建域时通过 workspace_engines 声明 CCU 后端需求。runtime 为域内合法窗口取得、交换并保存各 rank 的 CCU 地址、范围和 token,发布设备可消费的访问描述。建域不启动 mission,也不要求业务编排额外传入 ccu_callable、ccu_group_id 或 SDK/ISA build ID;构建兼容性由产物元数据与 runtime 校验。

    Worker.register(ChipCallable) 登记 CCU 定义;实际依赖域资源的 HCOMM 注册,在 callable 与通信域关联后完成,并可缓存。第一版每个本地 rank 建立到域内其他所有 rank 的 channel,由 runtime 提供按 peer rank 索引的 channel 表,用户 kernel 选择实际使用的连接,不要求预先声明 peer 子集。连接资源不足时明确失败,不静默缩减连接范围。

    窗口访问描述与 channel 分别管理。CCU 使用对应窗口的地址/token 和相应 channel 执行通信,不将 AIV 对端映射 VA、URMA 注册描述与 CCU 地址/token 混为同一种表示。真实域窗口与这些接口的兼容性仍需完成集成验证。

    每次 L2 run 根据该次 ChipCallable 准备或复用注册资源,launch 该 callable 内的 CCU missions,不因共享通信域而启动其他 callable 的 missions。callable/domain 关联由 runtime 管理,不要求调用方传额外的 CCU handle 清单。

    第二步:提交占用保护与 AIV 报错

    在 workspace 为每个 mission 增加独立、正确对齐的 owner 状态:FREE 或本次提交的唯一标识。不同 AIV 通过同一 L2 callable 的 comm_ctx 和同一 ccu_id 查到同一状态。只读描述与高频可变状态分开布局,用户 CCU kernel 不读取、不维护 owner。

    AIV 提交辅助接口必须覆盖参数发布过程,按下面的顺序执行:

    检查 ccu_id、参数范围等
      -> 为本次提交准备可用的异步完成/错误记录
      -> 原子申请 owner(FREE -> 本次提交标识)
           成功:登记成功提交信息,写参数,保证可见,置位 trigger
           失败:记录 CCU_SUBMIT_CONFLICT,不写参数、不触发 CCU
      -> AIV 返回
    

    原子申请必须发生在写共享参数槽之前。仅在裸 trigger 接口入口检查不够,因为调用者可能已经污染上一请求的参数。由统一提交接口包住 CcuCallArgs 的参数发布;若提供 try_begin/publish 两阶段接口,也必须强制申请成功后才能写参数和提交。

    两个 AIV 真正重叠时,只有一个能获得提交资格,另一个报错,不排队、不自动串行化。该机制检测的是实际重叠提交,不能保证检测所有缺失的依赖边:漏依赖但恰好没有重叠,不一定报错。

    原子机制由 ISA/platform 封装;现有 Event 的普通读后置位不能代替原子检查并占用。具体原子类型、提交标识编码和 AIV/AICPU 跨执行单元可见性需要实现与硬件验证,不能把它列为已有能力。

    错误检查只进入 defer wait 路径

    不在每个普通任务的 FIN 路径增加 CCU 状态检查。 正常 FIN 路径继续使用已有异步条件收集机制。CCU 专用的提交错误判断放在 CCU completion 的 poll 中。

    提交占用失败的 AIV 也必须登记属于本任务的 CCU 错误完成记录;不能仅设置一个私有错误后返回,否则可能走普通完成路径或等待永远不会出现的 done。

    AIV 提交成功 -> 本任务的 CCU completion 记录
    AIV 提交失败 -> 本任务的 CCU error completion 记录
                             |
                             v
                     已有 FIN 收集机制
                             |
                             v
                     CCU defer-wait poll
                       ├─ 提交错误:FAILED,进入运行失败处理
                       └─ 成功提交:检查 done
    

    记录应保留所属 L2 callable、ccu_id、本任务及观察到的占用者等定位信息。错误属于失败任务自己的记录,不写入正在执行的 mission 参数区,也不能覆盖已有 owner。失败记录的 retire 不得清除别人的 Event 或释放别人的占用。

    若连异步记录都无法登记,沿用现有登记失败处理;不为本功能增加一项所有普通任务都执行的检查。

    第二步正常回收与失败收尾

    正常路径复用当前 defer wait 对普通执行完成的保证:

    本任务普通执行已结束,done 满足
      -> 校验 owner 属于本次提交
      -> 清 done,确认生效
      -> 释放本任务的 owner
      -> 退休完成条件、释放依赖
    

    释放 owner 与依赖必须晚于 done 清位,避免旧任务回收掉新任务的完成信号。owner 校验失败应报协议错误,而不是清理未知所有者的资源。

    申请成功但 trigger 前失败,需要处理本任务已登记记录并安全释放自己的占用;trigger 后失败、超时或停止范围不明时,不能直接释放 owner 允许重用,应停止后续提交并进入既定失败收尾。AICPU 报错不等于可以立即释放仍被 CCU 访问的内存。

    准备流水化与跨 run 可变状态管理(两步均适用)

    沿用现有 L2 执行模型:准备阶段可以流水化,设备执行串行。 mission 可变状态的安全复用由 runtime 负责,不要求用户增加跨 run 依赖,也不笼统禁止多个 run 的准备与执行重叠。

    模块、注册结果、channel、窗口凭据及控制资源可以缓存。下一轮 prepare 可以准备独立的 launch 参数和资源引用,但不能提前清除上一轮的 Event、重置 owner(第二步引入),或覆盖上一轮仍在使用的参数槽。需要提前上传的本轮参数,应使用独立存储。

    prepare B 可以与 run A 重叠
                     |
    run A:普通设备工作结束、异步完成记录退休
                     |
           本轮所有 CCU streams 确认结束
                     |
           runtime 允许复用执行资源
                     |
    run B:初始化可变状态 -> launch CCU -> 卡内 READY -> 执行
    

    CCU mission 的结束必须纳入 L2 run 的执行事务;单次操作的 done 不能替代整个 mission 的 stream 完成。同一 stream 的顺序也不能替代对 Host 状态写入及不同 stream 的协调。

    如果上一轮超时或无法确认停止,下一轮即使已 prepare,也不得 launch 或重置相关资源,应进入既定失败收尾。实现时需要验证准备流水化不会污染上一轮状态,以及 CCU 完成确实参与现有 run 切换条件。

    分步验收

    第一步验收:workspace/描述发布、首次 ready、AIV 触发、CCU 最终完成、defer wait 清位后释放依赖,连续串行请求、跨 run 安全复用以及错误收尾。已有 SDK 探针不代替完整 simpler 集成验收。 增加身份与选择覆盖:AIV 编号与 ccu_id 不同仍能正确触发;同一 AIV 提交两个独立 mission,全部完成后才释放任务依赖;两个 callable 均使用 ccu_id=0 时不混用资源。

    第二步验收:双 AIV 同时申请时恰好一个成功;失败者不覆盖参数、不触发;错误通过 CCU defer wait 进入失败处理;不同 mission 不误报;提交前回滚、owner 校验与跨 run 隔离正确。普通任务不新增 CCU 专用检查。

  11. ChaoZheng109 commented on Nov 10, 2026

    @ChaoZheng109
    CollaboratorAuthor

    补充与 PyPTO #3281 方案对比后,我们在 simpler 侧明确的差异与接口边界。本条仅补充第一版的范围、注册和参数触发;生命周期、Event 协议、串行责任和分阶段错误检测沿用本 issue 的后续方案评论。

    1. 第一版范围与注册

    • 一个 L3 只有一个通信域,暂不考虑多通信域分组与选择,不依赖 Add: configure A5 URMA jetties through workspace engines #2929。此前讨论的按通信域配置 kernel group 不作为第一版要求。
    • 用户通过 L2 callable 提供 CCU kernel 列表,各 L2 worker 准备自己的本地注册和 launch 资源。
    • 用户提供完整 CCU mission 逻辑,包括等待触发、执行、循环及退出。simpler 负责注册和 launch,不负责将单次算法体包装成常驻循环,也不承担这部分 codegen。PyPTO 产物需要明确包含这些逻辑。
    • 第一版默认一个 kernel 对应一个 mission,不要求额外的多实例声明表。因此 PyPTO 提出的 ccu_id 可以直接作为所属 L2 callable 的 CCU kernel 列表索引,并对应本地 mission。
    • AIV 通过 comm_ctx + ccu_id 从 CCU workspace 查找该 mission 的控制资源。用户不需要传硬件 mission ID,也不需要在 AIV kernel 中手写 ckeSlotVA 或其他 Event 地址。编译时确定的 ccu_id 可以直接放在 AIV wrapper 中,只有动态选择时才需要随 args 传入。

    2. 参数接口与触发

    可以采用 PyPTO 提出的 CcuCallArgs 来组织本次调用参数,接口流程如下(submit 为示意名称,具体 ABI 待对齐):

    AIV args:tensor 地址、大小、本轮标量等
        |
        v
    AIV 构造 CcuCallArgs
        |
        v
    submit(comm_ctx, ccu_id, call_args)
        |-- 发布本次参数,并保证 CCU 可见
        `-- 调用 ISA trigger,通知 CCU 执行
    
    • workspace 准备的是控制资源、控制参数,以及 simpler 内部管理的必要参数承载区;用户的 tensor、通信地址及本轮动态参数仍随 AIV args 传入,不要求在创建通信域时预先配置每轮 tensor 参数。
    • “提交时传参数”是封装后的 submit 接口语义。底层 ISA CkeTrigger(ckeSlotVA, mask, ubScratch) 本身只发送触发信号,不携带 kernel 参数,ubScratch 也不是参数载荷。submit 内部需要先完成参数发布及可见性保证,再写 trigger Event。
    • 传递的是 tensor 地址、大小、标量等参数,不复制 tensor 数据。参数承载区在该次 CCU 执行完成前不能被下一次请求覆盖。
    • CcuCallArgs 的具体布局、参数发布/读取方式,以及用户 CCU kernel 如何取得参数和控制资源,仍需共同明确 ABI。采用这个参数组织接口不意味着这些底层细节已实现或验证完成。

    因此,kernel 与 mission 的多实例映射不再作为第一版差异;当前需要对齐的是:上层交付完整 mission、ccu_id 到 workspace 资源的查找约定,以及 CcuCallArgs 到 CCU 参数读取的提交 ABI。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions