FEATURED · 精选文章

CANN Runtime CntNotify(计数型通知)管理接口详解:创建、记录、等待与销毁全指南

发布时间 / 2026/9/20 1:40:01
来源 / 创域科博编辑部
栏目 / 资讯中心
CANN Runtime CntNotify(计数型通知)管理接口详解:创建、记录、等待与销毁全指南 CANNAscend人工智能任务调度【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址https://gitcode.com/cann/runtime点击查看免费下载导读本文聚焦 CANN Runtime 提供的 CntNotify计数型通知管理接口系统讲解aclrtCntNotifyCreate、aclrtCntNotifyRecord、aclrtCntNotifyWaitWithTimeout、aclrtCntNotifyReset、aclrtCntNotifyGetId、aclrtCntNotifyDestroy六个接口的声明、参数、行为模式与适用场景并深入仓库源码揭示其底层实现链路ACL 封装层 → RTS 运行时 API →CountNotify内核对象。读完本文你将掌握如何利用计数值实现多 Stream 之间、乃至 Device 之间的复杂同步等待逻辑并理解 CntNotify 与传统 Notify 在计数能力上的本质差异。适用前提本组接口目前仅在Ascend 950PR / Ascend 950DT产品上支持其余 Atlas 系列产品与 IPV350 均不支持开发前请先确认目标硬件平台。一、CntNotify 概述与 Notify 的本质区别CntNotifyCount Notify计数型通知是 CANN Runtime 中用于任务同步的通知原语。官方文档docs/zh/api_ref/09_cntNotify_management.md明确指出CntNotify 通常也用于 Device 与 Device 之间的状态/动作通信通知但它是利用计数值实现任务间的同步。它与普通 Notify 的核心区别在于计数值能力对比项NotifyCntNotify计数值范围仅支持1支持[1 ~ uint32_t 最大值]同步粒度单一信号量置位/等待可基于数值比较、位运算实现多条件同步典型场景Event/Notify 置位等待多 Stream 计数同步、Device 间状态通知由于计数值可以累加、覆盖、按位运算CntNotify 天然适合“等待 N 次事件完成后再继续”这类需要计数语义的场景而不仅仅是一次性的信号通知。从类型定义看aclrtCntNotify与aclrtNotify、aclrtStream一样是不透明句柄见 docs/zh/api_ref/25-05_Typedefs.md 与 include/external/acl/acl_base_rt.htypedef void* aclrtCntNotify;开发者无需关心句柄内部结构只需通过本组管理接口完成创建、记录、等待、复位、查询与销毁。二、产品支持情况务必先确认平台以下产品支持情况直接引用官方文档docs/zh/api_ref/09_cntNotify_management.md与源码中 arch5162 等平台的接口裁剪定义src/runtime/cmake/arch5162_unsupported_acl_api.def产品CntNotify 支持情况Ascend 950PR / Ascend 950DT✅ 支持Atlas A3 训练系列产品 / Atlas A3 推理系列产品❌ 不支持Atlas A2 训练系列产品 / Atlas A2 推理系列产品❌ 不支持Atlas 200I/500 A2 推理产品❌ 不支持Atlas 推理系列产品❌ 不支持Atlas 训练系列产品❌ 不支持IPV350❌ 不支持也就是说CntNotify 目前是 Ascend 950 系列专属能力。在非 950 平台上调用这些接口将返回失败代码中需要做好平台兼容判断或错误处理。三、CntNotify 相关的枚举与结构体在讲解接口前先掌握两个关键枚举定义于 include/external/acl/acl_rt.h文档说明见 docs/zh/api_ref/25-02_Enumerations.md和两个结构体定义见 docs/zh/api_ref/25-04_Structs.md。3.1 Record 行为模式aclrtCntNotifyRecordModetypedef enum { ACL_RT_CNT_NOTIFY_RECORD_SET_VALUE_MODE 0, // 覆盖模式CntNotify计数值 value ACL_RT_CNT_NOTIFY_RECORD_ADD_MODE 1, // 累加模式CntNotify计数值 当前值 value ACL_RT_CNT_NOTIFY_RECORD_BIT_OR_MODE 2, // bit或模式CntNotify计数值 当前值 | value ACL_RT_CNT_NOTIFY_RECORD_BIT_AND_MODE 4, // bit与模式CntNotify计数值 当前值 value } aclrtCntNotifyRecordMode;SET_VALUE覆盖直接将计数值写为value适合对 CntNotify 重新初始化。ADD累加每次 Record 使计数值增加value是实现“N 次事件计数”的常用模式。BIT_OR / BIT_AND位运算按位写入或清除位可与下方 Wait 的位掩码模式配合实现多信号位同步。3.2 Wait 行为模式aclrtCntNotifyWaitModetypedef enum { ACL_RT_CNT_NOTIFY_WAIT_LESS_MODE 0, // 当前计数值 value则解除Wait ACL_RT_CNT_NOTIFY_WAIT_EQUAL_MODE 1, // 当前计数值 value则解除Wait ACL_RT_CNT_NOTIFY_WAIT_BIGGER_MODE 2, // 当前计数值 value则解除Wait ACL_RT_CNT_NOTIFY_WAIT_BIGGER_OR_EQUAL_MODE 3, // 当前计数值 value则解除Wait ACL_RT_CNT_NOTIFY_WAIT_EQUAL_WITH_BITMASK_MODE 4, // 当前计数值 value value则解除Wait } aclrtCntNotifyWaitMode;五种模式覆盖了数值比较小于、等于、大于、大于等于与位掩码匹配配合 Record 的不同写入模式可构造出非常灵活的同步条件。3.3 结构体aclrtCntNotifyRecordInfo与aclrtCntNotifyWaitInfotypedef struct { aclrtCntNotifyRecordMode mode; // Record的行为模式 uint32_t value; } aclrtCntNotifyRecordInfo;typedef struct { aclrtCntNotifyWaitMode mode; // Wait的行为模式 uint32_t value; uint32_t timeout; // 超时时间单位是秒其中0表示永久等待 uint8_t isClear; // wait解除阻塞后是否将CntNotify的计数值自动清空为0取值1表示清空0表示不清空 uint8_t rev[3]; // 预留字节 } aclrtCntNotifyWaitInfo;几个关键点的使用提示timeout单位为秒0表示永久等待。这是aclrtCntNotifyWaitWithTimeout名称中 WithTimeout 的由来也是防止同步条件永远不满足时死等的关键防护。isClear解除等待后是否自动清零计数值。多轮复用同一个 CntNotify 时建议置1避免上一轮的计数残留影响下一轮同步。rev[3]预留字段固定填 0 即可。四、接口详解六大管理接口以下六个接口按“创建 → 记录 → 等待 → 复位 → 查询 → 销毁”的生命周期顺序展开。所有接口的返回值约定一致返回 0 表示成功返回其他值表示失败具体错误码含义请参见 aclError。4.1 aclrtCntNotifyCreate创建 CntNotifyaclError aclrtCntNotifyCreate(aclrtCntNotify *cntNotify, uint64_t flag)功能说明创建 CntNotify。flag 为预留参数当前必须固定配置为 0。这一点在底层实现中也有强校验——在 src/runtime/api/api_david.cc 中rtCntNotifyCreateServer对flags ! 0ULL的情况直接返回RT_ERROR_INVALID_VALUECOND_RETURN_EXT_ERRCODE_AND_MSG_OUTER_WITH_PARAM(flags ! 0ULL, RT_ERROR_INVALID_VALUE, flags, 0);也就是说flag传非 0 值会直接报参数非法。参数说明参数名输入/输出说明cntNotify输出CntNotify 的指针类型为 aclrtCntNotify。创建成功后句柄由运行时分配并写出。flag输入预留参数当前固定配置为 0。源码佐证ACL 层封装见 src/acl/aclrt_impl/notify.cpp内部通过rtCntNotifyCreateServer下发到 RuntimeRuntime 层再依据当前 Device 创建CountNotify内核对象并通过driver_-NotifyIdAlloc(...)向驱动申请物理 notify ID见 src/runtime/feature/cntnotify/count_notify.cc。若申请不到 notify 资源会携带错误码EE1023“Too many CntNotify objects are created”即创建的 CntNotify 数量过多导致资源耗尽可参考 docs/zh/FAQ/EE1023资源不足问题.md 排查。4.2 aclrtCntNotifyRecord在指定 Stream 上记录 CntNotify异步aclError aclrtCntNotifyRecord(aclrtCntNotify cntNotify, aclrtStream stream, aclrtCntNotifyRecordInfo *info)功能说明在指定 Stream 上记录一个 CntNotify异步接口。aclrtCntNotifyRecord与aclrtCntNotifyWaitWithTimeout配合使用时主要用于多 Stream 之间同步等待的场景。参数说明参数名输入/输出说明cntNotify输入需记录的 CntNotify类型见 aclrtCntNotify。stream输入指定 Stream类型见 aclrtStream。使用默认 Stream 时填NULL。多 Stream 同步等待场景下例如 Stream2 等 Stream1此处配置为Stream1即“记录发生在哪个 Stream 上”。info输入控制 Record 的行为模式见 aclrtCntNotifyRecordInfo。源码佐证在 src/runtime/feature/cntnotify/count_notify.cc 中CountNotify::Record在指定 Stream 上分配TS_TASK_TYPE_NOTIFY_RECORD类型的任务调用NotifyRecordTaskInit初始化后经DavidSendTask异步下发。注意实现中info指针不能为NULLACL 层通过ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(info)做了非空校验见 src/acl/aclrt_impl/notify.cpp传空指针会直接报输入参数错误。4.3 aclrtCntNotifyWaitWithTimeout阻塞 Stream 等待 CntNotify 完成异步aclError aclrtCntNotifyWaitWithTimeout(aclrtCntNotify cntNotify, aclrtStream stream, aclrtCntNotifyWaitInfo *info)功能说明阻塞指定 Stream 的运行直到指定的 CntNotify 满足等待条件异步接口阻塞的是 Stream 上的后续任务而非调用线程。参数说明参数名输入/输出说明cntNotify输入需等待的 CntNotify类型见 aclrtCntNotify。stream输入指定 Stream类型见 aclrtStream。使用默认 Stream 时填NULL。多 Stream 同步等待场景下例如 Stream2 等 Stream1此处配置为Stream2即“哪个 Stream 被阻塞等待”。info输入控制 Wait 的行为模式见 aclrtCntNotifyWaitInfo。使用要点等待条件由info-modeinfo-value共同决定小于/等于/大于/大于等于/位掩码匹配。info-timeout单位秒0表示永久等待建议生产环境配置合理超时值避免条件永不满足时任务永久挂起。info-isClear决定解除等待后是否自动清零多轮复用场景建议置1。该接口同样对info做非空校验见 src/acl/aclrt_impl/notify.cpp。4.4 aclrtCntNotifyReset复位 CntNotify异步aclError aclrtCntNotifyReset(aclrtCntNotify cntNotify, aclrtStream stream)功能说明复位一个 CntNotify将其计数值清空为 0异步接口。参数说明参数名输入/输出说明cntNotify输入待复位的 CntNotify类型见 aclrtCntNotify。stream输入指定 Stream类型见 aclrtStream。使用默认 Stream 时填NULL。使用要点与WaitInfo.isClear的“等待解除后自动清零”不同Reset是显式、主动的复位动作适用于在同步周期开始时将计数值归零、重新开始一轮计数。多轮流水线场景建议在每轮开始前调用 Reset确保计数起点一致。4.5 aclrtCntNotifyGetId获取 CntNotify 的 IDaclError aclrtCntNotifyGetId(aclrtCntNotify cntNotify, uint32_t *notifyId)功能说明获取 CntNotify 的 ID。该 ID 可用于日志打点、profiling 关联、跨模块传递标识等场景。参数说明参数名输入/输出说明cntNotify输入待获取的 CntNotify类型见 aclrtCntNotify。notifyId输出CntNotify IDuint32 类型。源码佐证CountNotify内核对象持有notifyid_成员见 src/runtime/feature/cntnotify/count_notify.hppGetCntNotifyId()直接返回该 IDRuntime 层rtGetCntNotifyId通过Api::Instance()-GetCntNotifyId(...)实现见 src/runtime/api/api_david.cc。4.6 aclrtCntNotifyDestroy销毁 CntNotifyaclError aclrtCntNotifyDestroy(aclrtCntNotify cntNotify)功能说明销毁 CntNotify释放其占用的驱动 notify 资源。参数说明参数名输入/输出说明cntNotify输入待销毁的 CntNotify类型见 aclrtCntNotify。使用要点销毁后该句柄不可再用于任何 Record/Wait 等操作。程序退出前应确保所有 CntNotify 均被销毁否则可能造成 notify 资源泄漏后续进程创建 CntNotify 时会因资源不足返回 EE1023 类错误。底层CountNotify析构时会将自身从当前 Device 的 CntNotify 列表移除并调用driver_-NotifyIdFree(...)归还 notify ID见 src/runtime/feature/cntnotify/count_notify.cc。五、典型用法多 Stream 计数同步官方文档明确指出Record 与 WaitWithTimeout 配合是“多 Stream 之间同步等待”的标准用法。下面给出“Stream1 上完成一次记录、Stream2 上等待其完成”的完整流程骨架aclrtCntNotify cntNotify nullptr; aclrtStream stream1 nullptr; // 记录方 aclrtStream stream2 nullptr; // 等待方 aclrtCntNotifyRecordInfo recInfo {}; aclrtCntNotifyWaitInfo waitInfo {}; // 1. 创建 CntNotifyflag 固定为 0 aclError ret aclrtCntNotifyCreate(cntNotify, 0); if (ret ! 0) { /* 处理错误 */ } // 2. 创建两个 Stream ret aclrtCreateStream(stream1); ret aclrtCreateStream(stream2); // 3. 在 Stream1 上记录一次计数累加模式每次 1 recInfo.mode ACL_RT_CNT_NOTIFY_RECORD_ADD_MODE; recInfo.value 1; ret aclrtCntNotifyRecord(cntNotify, stream1, recInfo); // 4. 在 Stream2 上等待计数值 1超时 10 秒解除后自动清零 waitInfo.mode ACL_RT_CNT_NOTIFY_WAIT_BIGGER_OR_EQUAL_MODE; waitInfo.value 1; waitInfo.timeout 10; // 0 表示永久等待 waitInfo.isClear 1; // 1 表示解除后清空计数值 ret aclrtCntNotifyWaitWithTimeout(cntNotify, stream2, waitInfo); // 5. 查询 ID用于日志/profiling 关联 uint32_t notifyId 0; ret aclrtCntNotifyGetId(cntNotify, notifyId); // 6. 复位并复用可选 ret aclrtCntNotifyReset(cntNotify, stream2); // 7. 销毁 ret aclrtCntNotifyDestroy(cntNotify);关键参数记忆法官方文档原话逻辑Record 的stream是“被记录事件发生的 Stream”——Stream2 等 Stream1 时填Stream1Wait 的stream是“被阻塞的 Stream”——Stream2 等 Stream1 时填Stream2使用默认 Stream 时stream均填NULL。如果需要对“N 个生产者 Stream 都完成一轮任务后再继续”可以让每个生产者 Stream 各执行一次ACL_RT_CNT_NOTIFY_RECORD_ADD_MODE的 Record等待方在目标 Stream 上使用BIGGER_OR_EQUAL模式等待计数值达到 N这正是普通 Notify 无法表达的计数同步语义。六、底层实现链路与测试验证6.1 调用链全景从调用方到内核对象的完整链路如下应用代码 │ aclrtCntNotifyCreate / Record / WaitWithTimeout / Reset / GetId / Destroy ▼ ACL 封装层src/acl/aclrt_impl/notify.cpp │ ACL_PROFILING_REG 注册 profiling 埋点 ACL_LOG_INFO 日志 │ 参数非空校验ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT ▼ RTS 运行时 API 层src/runtime/api/api_david.cc │ GLOBAL_STATE_WAIT_IF_LOCKED() 全局状态门控 │ RT_VALIDATE_AND_UNWRAP_OBJECT 句柄解包 ▼ CountNotify 内核对象src/runtime/feature/cntnotify/count_notify.cc │ Setup(): NotifyIdAlloc 申请驱动 notify ID │ Record(): 分配 TS_TASK_TYPE_NOTIFY_RECORD 任务并异步下发 │ Wait(): 分配 TS_TASK_TYPE_NOTIFY_WAIT 任务并异步下发 ▼ 驱动层NpuDriver::GetDevResAddress / NotifyIdAlloc / NotifyIdFree值得注意的细节所有接口都经过全局状态门控GLOBAL_STATE_WAIT_IF_LOCKED()保证运行时初始化/去初始化期间的调用安全。句柄解包校验RT_VALIDATE_AND_UNWRAP_OBJECT会将用户传入的aclrtCntNotify句柄安全转换为内部的CountNotify*非法句柄会直接报错而不是产生空指针崩溃。任务类型分离Record 与 Wait 分别对应TS_TASK_TYPE_NOTIFY_RECORD和TS_TASK_TYPE_NOTIFY_WAIT两种任务任务信息结构体定义于 src/runtime/core/inc/task/task_info_struct.hpp其中isCountNotify字段用于区分计数型通知与普通事件记录/等待。6.2 资源类型与计数值语义CountNotify::GetCntNotifyAddress见 src/runtime/feature/cntnotify/count_notify.cc揭示了内部资源划分根据通知类型映射到不同的驱动资源包括RT_RES_TYPE_STARS_CNT_NOTIFY_RECORD记录、RT_RES_TYPE_STARS_CNT_NOTIFY_ADD累加、RT_RES_TYPE_STARS_CNT_NOTIFY_BIT_WR位写、RT_RES_TYPE_STARS_CNT_NOTIFY_BIT_CLR位清分别对应覆盖、累加、bit 或、bit 与四种 Record 模式的底层硬件切片。6.3 测试用例验证仓库 UT 测试对六个接口均有覆盖见 tests/ut/acl/testcase/acl_runtime_unittest.cpp 与 tests/ut/acl/testcase/acl_runtime_unittest.cpp典型用例包括aclrtCntNotifyCreate/aclrtCntNotifyDestroy验证创建与销毁调用链及 mock 转发aclrtCntNotifyRecord以{ACL_RT_CNT_NOTIFY_RECORD_SET_VALUE_MODE, 0}构造 RecordInfo并验证info传nullptr时返回参数错误aclrtCntNotifyWaitWithTimeout以{ACL_RT_CNT_NOTIFY_WAIT_LESS_MODE, 0, 0, true, 0}永久等待 解除后清零构造 WaitInfo并覆盖空指针校验aclrtCntNotifyReset/aclrtCntNotifyGetId验证复位与 ID 查询含notifyId空指针校验。此外运行时侧在 950 平台测试中有专门的rt_utest_david_event.cc、rt_utest_david_stream.cc等用例见 tests/ut/runtime/runtime/test/platform/950/ 目录进一步印证该功能主要面向 David 架构950 系列实现与文档中“仅 Ascend 950 支持”的说明一致。七、使用建议与注意事项平台前置检查CntNotify 目前仅 Ascend 950PR/950DT 支持。在多平台复用的代码中建议先用平台查询接口确认设备能力再决定是否走 CntNotify 同步路径避免在其他 Atlas 产品上运行时失败。flag 必须为 0aclrtCntNotifyCreate的flag为预留参数传非 0 值会被底层直接判定为非法参数见 src/runtime/api/api_david.cc。info 不能为空Record 与 WaitWithTimeout 的info指针均做了非空校验使用前务必初始化结构体建议 {}清零。善用 timeout 与 isClearWait 的timeout建议配置有限值防止死等isClear在多轮复用场景置 1 可免去手动 Reset但也要注意“清零时机在解除等待之后”若后续还有依赖旧计数值的逻辑需谨慎。生命周期管理CntNotify 使用完毕后必须Destroy否则占用驱动 notify 资源持续创建会触发 EE1023 资源不足错误复用时注意在每轮同步周期开始前Reset归零计数值。异步语义Record、WaitWithTimeout、Reset 均为异步接口它们阻塞的是 Stream 上的任务调度而非调用线程理解这一点有助于写出不阻塞 Host 的高吞吐流水线。参考资源接口管理文档docs/zh/api_ref/09_cntNotify_management.md枚举定义docs/zh/api_ref/25-02_Enumerations.mdaclrtCntNotifyRecordMode、aclrtCntNotifyWaitMode结构体定义docs/zh/api_ref/25-04_Structs.mdaclrtCntNotifyRecordInfo、aclrtCntNotifyWaitInfo类型定义docs/zh/api_ref/25-05_Typedefs.mdaclrtCntNotify错误码说明docs/zh/api_ref/25-01_aclError.mdACL 头文件声明include/external/acl/acl_rt.hACL 封装实现src/acl/aclrt_impl/notify.cppRTS 运行时 APIsrc/runtime/api/api_david.cc内核对象实现src/runtime/feature/cntnotify/count_notify.cc 与 count_notify.hppUT 测试用例tests/ut/acl/testcase/acl_runtime_unittest.cpp赞分享CANNAscend人工智能任务调度【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址https://gitcode.com/cann/runtime点击查看免费下载相关推荐CANN Runtime Stream管理接口详解创建、同步、销毁与高级特性CANN Runtime Stream管理接口详解创建、同步、销毁与高级特性 CANNCompute Architecture for Neural NetCANNAscend人工智能任务调度CANN opbase 中 aclDestroyTensor 接口详解aclTensor 的创建与销毁生命周期管理CANN opbase 中 aclDestroyTensor 接口详解aclTensor 的创建与销毁生命周期管理 导读 在 CANN 算子库基础框架库 op人工智能算子库CANNAscendCANN Runtime Event管理接口完全指南创建、记录、同步、计时与IPC跨进程共享CANN Runtime Event管理接口完全指南创建、记录、同步、计时与IPC跨进程共享 Event事件是 CANN Runtime 中用于 任务同步CANNAscend人工智能任务调度创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻