ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

CANN Runtime Label 机制实战:基于 0_simple_label 示例掌握 Label 创建、LabelList 组装与按索引跳转

CANN Runtime Label 机制实战:基于 0_simple_label 示例掌握 Label 创建、LabelList 组装与按索引跳转 CANN Runtime Label 机制实战基于 0_simple_label 示例掌握 Label 创建、LabelList 组装与按索引跳转【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtimeLabel 是 CANN Runtime 中用于实现 Stream 级控制流的关键机制通过在持久化 Stream 上设置标签Label、把多个标签组装成标签列表LabelList再根据 Device 内存中的分支索引执行跳转Switch即可在一个模型运行实例Model RI内部实现动态分支选择。本文以开源仓库 example/2_advanced_features/label 目录下的0_simple_label示例为主线逐行剖析 Label 从创建、组装、设置到按索引跳转的完整流程并结合 src/acl/aclrt_impl/label.cpp 与 docs/zh/api_ref/10_label_management.md 的接口定义与实现帮助你理解 Label 的底层调用链与约束条件最终能够在自己的项目中独立编写基于 Label 的分支执行程序。一、Label 机制解决什么问题在多分支计算场景如动态形状推理、模型内条件路由中开发者往往希望同一套预编排任务中根据运行期的输入选择不同执行路径。CANN Runtime 提供的 Label 管理能力正是面向这一需求Label标签在持久化 Stream 上标记的跳转点用于把任务切分成可寻址的区间LabelList标签列表将多个 Label 组装成一个有序集合供跳转接口按索引定位按索引跳转根据 Device 内存中 uint32 类型的分支索引把执行流从当前 Stream 切换到指定 Label 所在的 Stream 位置同时当前 Stream 上的任务停止执行。从 Model 模块的设计文档 docs/zh/design/modules/model/model.md 可以看到其架构定位Model 作为任务容器、Stream 作为任务队列、Label 实现控制流Model 分配 Label IDStream 记录跳转点并通过 headStreams 机制标记入口 Stream在 Execute 时从这里激活执行。也就是说Label 跳转是模型运行实例内部任务编排能力的一部分这正是示例中 Label 操作必须绑定在模型运行实例上的原因。二、示例概览与目录结构label 目录专注于 Label 的创建、组装与 Stream 内跳转能力当前包含一个示例示例说明0_simple_label演示 Label 创建、LabelList 组装、在绑定到模型运行实例的持久化 Stream 上设置 Label以及依据 Device 内存中的分支索引执行 Label 跳转该示例的运行结果会打印模型运行实例构建、执行与资源释放完成的日志。产品支持情况依据示例文档与 API 参考文档Label 管理接口在以下产品上受支持产品是否支持Ascend 950PR/Ascend 950DT是Atlas A3 训练系列产品/Atlas A3 推理系列产品是Atlas A2 训练系列产品/Atlas A2 推理系列产品是Atlas 200I/500 A2 推理产品是Atlas 推理系列产品是Atlas 训练系列产品是IPV350不支持三、核心 API 与底层实现调用链示例涉及的全部 Label 管理接口声明在 include/external/acl/acl_rt.h类型定义见 include/external/acl/acl_base_rt.haclrtLabel、aclrtLabelList均为void*句柄。其实现位于 src/acl/aclrt_impl/label.cpp每个对外接口最终都透传到 RTS 层。3.1 aclrtCreateLabel / aclrtDestroyLabel创建与销毁标签aclError aclrtCreateLabel(aclrtLabel *label); // 输出创建的标签 aclError aclrtDestroyLabel(aclrtLabel label); // 输入要销毁的标签功能说明创建/销毁标签。每个进程最多创建 65535 个标签见 docs/zh/api_ref/10_label_management.md实现路径aclrtCreateLabelImpl内部调用rtsLabelCreateaclrtDestroyLabelImpl内部调用rtsLabelDestroy见 src/acl/aclrt_impl/label.cpp。底层运行时通过LabelAllocator管理标签 ID 资源实现位于 src/runtime/core/src/launch/label.cc初始化时预分配 64 个标签 IDRT_MAX_LABEL_INIT_NUM 64按需追加新 ID相关常量定义于 src/runtime/core/inc/spec/base_info.hppRT_MAX_LABEL_NUM 1024U、RT_MAX_LABEL_INIT_NUM 64U。3.2 aclrtSetLabel在 Stream 上设置标签aclError aclrtSetLabel(aclrtLabel label, aclrtStream stream);功能说明在指定 Stream 上设置标签标记该位置为可跳转点关键约束stream只支持通过aclmdlRIBindStream接口绑定过模型运行实例的 Stream且从源码看在较新的 Tsch 版本上设置标签前必须先调用aclrtCreateLabelList创建标签列表否则会返回RT_ERROR_LABEL_PHY_ADDR_NULL错误码 EE1018参见 src/runtime/core/src/launch/label.cc实现路径aclrtSetLabelImpl内部调用rtsLabelSet见 src/acl/aclrt_impl/label.cpp。3.3 aclrtCreateLabelList / aclrtDestroyLabelList组装与释放标签列表aclError aclrtCreateLabelList(aclrtLabel *labels, size_t num, aclrtLabelList *labelList); aclError aclrtDestroyLabelList(aclrtLabelList labelList);功能说明将labels数组中的标签须由aclrtCreateLabel创建按顺序组装为标签列表num为标签数组长度取值 (0, 65535]实现路径aclrtCreateLabelListImpl调用rtsLabelSwitchListCreateaclrtDestroyLabelListImpl调用rtsLabelSwitchListDestroy见 src/acl/aclrt_impl/label.cpp。3.4 aclrtSwitchLabelByIndex按索引执行跳转异步aclError aclrtSwitchLabelByIndex(void *ptr, uint32_t maxValue, aclrtLabelList labelList, aclrtStream stream);功能说明根据标签索引跳转到对应标签位置执行该标签所在 Stream 上的任务同时当前 Stream 上的任务停止执行。该接口为异步接口参数语义详见 docs/zh/api_ref/10_label_management.mdptr存放目标标签索引值的Device 内存地址索引值数据类型为 uint32、长度 4 字节索引从 0 开始当目标标签索引大于 labelList 数组的最大索引时跳转到最大标签maxValue标签列表中的标签个数labelList由aclrtCreateLabelList创建的标签列表stream执行跳转任务的 Stream实现路径aclrtSwitchLabelByIndexImpl对ptr、labelList、stream逐一做空指针校验后调用rtsLabelSwitchByIndex见 src/acl/aclrt_impl/label.cpp。所有 Label 相关接口均通过ACL_PROFILING_REG注册到性能分析框架可在 src/acl/aclrt_impl/toolchain/profiling_manager.cpp 中看到完整的接口名映射便于在 profiling 数据中定位 Label 操作耗时。四、示例代码逐步解析示例主程序位于 example/2_advanced_features/label/0_simple_label/main.cpp核心流程如下。4.1 常量与句柄声明const int32_t deviceId 0; const uint32_t branchIndex 1; // 本次演示选择的分支索引 const uint32_t labelCount 2; // 创建 2 个标签 const uint32_t headStreamFlag 0x00000000U; // aclmdlRIBindStream 的 flag aclrtContext context nullptr; aclrtStream labelStream nullptr; // 持久化 Stream用于承载 Label 任务 aclrtStream executeStream nullptr; // 执行流用于异步执行模型运行实例 aclrtLabel labels[labelCount] {nullptr, nullptr}; aclrtLabelList labelList nullptr; uint32_t* branchIndexDevice nullptr; // Device 侧分支索引 aclmdlRI modelRI nullptr;示例使用一组布尔标志跟踪每一步资源是否创建成功确保出错时能按依赖关系逆序释放RAII 风格的 C 接口封装模式。4.2 初始化、选 Device 与建流CHECK_ERROR(aclInit(nullptr)); // 初始化 ACL CHECK_ERROR(aclrtSetDevice(deviceId)); // 指定计算 Device CHECK_ERROR(aclrtCreateContext(context, deviceId)); // 创建 Context // 创建持久化 Stream用于下发 Label 相关任务 CHECK_ERROR(aclrtCreateStreamWithConfig(labelStream, 0x00U, ACL_STREAM_PERSISTENT)); // 创建普通执行流用于异步执行模型运行实例 CHECK_ERROR(aclrtCreateStream(executeStream));其中ACL_STREAM_PERSISTENT0x00000004U定义于 include/external/acl/acl_rt.h表示创建持久化 Stream。Label 跳转点需要记录在稳定的 Stream 上因此示例用带配置的aclrtCreateStreamWithConfig创建持久化流这是后续aclrtSetLabel与aclrtSwitchLabelByIndex的载体。4.3 构建模型运行实例并绑定持久化 StreamCHECK_ERROR(aclmdlRIBuildBegin(modelRI, 0x00U)); // 开始构建模型运行实例 CHECK_ERROR(aclmdlRIBindStream(modelRI, labelStream, headStreamFlag)); // 绑定持久化流aclmdlRIBuildBegin(modelRI, flag)开始构建一个模型运行实例flag为保留参数、须为 0见 include/external/acl/acl_rt.haclmdlRIBindStream(modelRI, stream, flag)将模型运行实例与 Stream 绑定flag取值可为ACL_MODEL_STREAM_FLAG_HEAD或ACL_MODEL_STREAM_FLAG_DEFAULT示例传0x00000000U即默认标记。绑定之后该 Stream 才具备承载 Label 跳转任务的条件——这与 3.2 节中aclrtSetLabel的约束相互印证。4.4 准备 Device 侧分支索引CHECK_ERROR(aclrtMalloc(reinterpret_castvoid**(branchIndexDevice), sizeof(branchIndex), ACL_MEM_MALLOC_HUGE_FIRST)); CHECK_ERROR(aclrtMemcpy(branchIndexDevice, sizeof(branchIndex), branchIndex, sizeof(branchIndex), ACL_MEMCPY_HOST_TO_DEVICE));aclrtSwitchLabelByIndex的第一个参数要求是 Device 内存地址uint32、4 字节。示例先以ACL_MEM_MALLOC_HUGE_FIRST策略分配 4 字节 Device 内存再用ACL_MEMCPY_HOST_TO_DEVICE把主机侧的branchIndex 1拷贝到 Device。这样跳转决策完全由 Device 侧数据驱动适合在真实场景中由算子/DMA 动态改写分支值。4.5 创建标签并组装 LabelListfor (uint32_t index 0; index labelCount; index) { CHECK_ERROR(aclrtCreateLabel(labels[index])); // 创建 label 0 和 label 1 } CHECK_ERROR(aclrtCreateLabelList(labels, labelCount, labelList)); // 组装成标签列表先逐个创建 2 个标签再按顺序组装为包含 2 个标签的 LabelList。标签的排列顺序即跳转索引的映射顺序索引 0 →labels[0]索引 1 →labels[1]。4.6 下发跳转任务与标签设置构建期编排// 在模型 RI 绑定的持久化 Stream 上先记录“按索引跳转”任务 CHECK_ERROR(aclrtSwitchLabelByIndex(branchIndexDevice, labelCount, labelList, labelStream)); // 再设置各标签作为跳转目标点 for (uint32_t index 0; index labelCount; index) { CHECK_ERROR(aclrtSetLabel(labels[index], labelStream)); }这一段是本示例的核心逻辑aclrtSwitchLabelByIndex读取 Device 内存中的分支索引值为 1运行时执行时会跳转到labelList[1]对应的标签位置执行该标签之后的任务同时当前跳转发起Stream 上的后续任务停止执行aclrtSetLabel在持久化 Stream 上依次标记labels[0]、labels[1]作为可跳转目标点。注意跳转任务与标签设置在同一个持久化 Stream上按序下发跳转语义由运行时依据任务顺序解析这是 Label 控制流与普通任务编排的本质区别。4.7 结束构建并异步执行CHECK_ERROR(aclmdlRIEndTask(modelRI, labelStream)); // 标记该 Stream 上下发任务结束 CHECK_ERROR(aclmdlRIBuildEnd(modelRI, nullptr)); // 结束模型运行实例构建 CHECK_ERROR(aclmdlRIExecuteAsync(modelRI, executeStream)); // 异步执行 CHECK_ERROR(aclrtSynchronizeStream(executeStream)); // 阻塞等待执行完成aclmdlRIEndTask在 Stream 上标记任务下发结束见 include/external/acl/acl_rt.haclmdlRIBuildEnd完成模型构建内部 LoadComplete之后 RI 即可执行aclmdlRIExecuteAsync(modelRI, executeStream)在独立的执行流上异步激活模型运行实例执行入口由 headStream 机制决定参考 docs/zh/design/modules/model/model.md 中 headStreams 标记入口 Stream 的设计随后用aclrtSynchronizeStream(executeStream)等待全部任务完成。4.8 逆序资源清理程序结束前按“后创建先释放”的顺序回收资源见 main.cppaclmdlRIUnbindStream(modelRI, labelStream); // 解绑持久化流 aclmdlRIDestroy(modelRI); // 销毁模型运行实例 aclrtDestroyLabelList(labelList); // 释放标签列表 aclrtDestroyLabel(labels[1]); aclrtDestroyLabel(labels[0]); // 销毁标签 aclrtFree(branchIndexDevice); // 释放 Device 分支索引内存 aclrtDestroyStream(executeStream); // 销毁执行流 aclrtDestroyStream(labelStream); // 销毁持久化流 aclrtDestroyContext(context); // 销毁 Context aclrtResetDeviceForce(deviceId); // 强制复位 Device 并回收资源 aclFinalize(); // 去初始化每一步都用UpdateFinalResultOnError汇总错误码保证任何一步失败时其余资源仍能按序回收避免资源泄漏。五、构建与运行5.1 运行前准备环境安装、环境变量配置与通用运行说明参见 example/README_en.md。可以先执行source cann_path/set_env.sh设置 CANN 环境变量若未预先设置run.sh 会自动依次探测ASCEND_INSTALL_PATH、ASCEND_HOME_PATH、$HOME/Ascend/cann、/usr/local/Ascend/cann、/opt/Ascend/cann。5.2 编译运行进入示例目录后执行bash run.shrun.sh 的核心动作见 run.shsource示例公共环境解析脚本 example/common/resolve_cann_env.sh 并调用resolve_cann_env创建build目录执行 CMake 配置-DASCEND_CANN_PACKAGE_PATH${ASCEND_INSTALL_PATH}make -j$(nproc)编译直接运行生成的./build/main。5.3 CMake 构建配置说明CMakeLists.txt 要点项目名Runtime_Label_Simple_Sample最低 CMake 版本 3.16.0头文件路径包含${ASCEND_CANN_PACKAGE_PATH}/include及示例公共目录../../..以引入 utils.h 中的CHECK_ERROR/INFO_LOG宏编译选项-O2 -stdc17 -D_GLIBCXX_USE_CXX11_ABI0 -Wall -Werror链接${ASCEND_CANN_PACKAGE_PATH}/lib64/libacl_rt.so仅依赖运行时库不依赖其他组件。5.4 预期运行输出[INFO] ACL initialized. [INFO] Device 0 selected. [INFO] Context created on device 0. [INFO] Persistent label stream created. [INFO] Execute stream created. [INFO] Model runtime instance build started. [INFO] Persistent label stream bound to the model runtime instance. [INFO] Allocated device memory for branch index. [INFO] Copied branch index 1 from host to device. [INFO] Created label 0. [INFO] Created label 1. [INFO] Created label list with 2 labels. [INFO] Submitted switch-label task with branch index 1. [INFO] Set label 0 on the persistent stream. [INFO] Set label 1 on the persistent stream. [INFO] Model runtime instance build finished. [INFO] Switch label executed successfully with branch index 1. [INFO] Run the simple_label sample successfully.日志清晰地呈现了“初始化 → 建流 → 构建并绑定 RI → 准备分支索引 → 创建 Label/组装 LabelList → 编排跳转任务 → 执行跳转 → 成功结束”的完整生命周期。若任一步骤失败程序会以对应aclError错误码提示失败接口并继续逆序清理已占用资源。六、关键约束与使用建议进程级标签上限每个进程最多创建 65535 个标签aclrtCreateLabelList的num取值范围为 (0, 65535]。底层 LabelAllocator 默认预分配 64 个标签 ID 并按需扩容见 src/runtime/core/src/launch/label.cc大部分场景无需关心但极端多分支场景需注意总量控制Stream 必须绑定模型运行实例aclrtSetLabel只支持已通过aclmdlRIBindStream绑定的 Stream且跳转任务也必须在同一个模型运行实例上下文中编排这决定了 Label 能力本质上是“模型运行实例内的控制流”分支索引位于 Device 内存aclrtSwitchLabelByIndex读取的是 Device 地址上的 uint32 值跳转前务必确保索引已通过aclrtMemcpyH2D或算子写入索引从 0 开始超出 LabelList 最大索引时会跳转到最大标签异步语义aclrtSwitchLabelByIndex与aclmdlRIExecuteAsync均为异步接口务必通过aclrtSynchronizeStream或事件机制等待完成再读取结果或释放资源维测辅助Label 全链路接口均接入 profiling 上报见 src/acl/aclrt_impl/toolchain/profiling_manager.cpp定位跳转性能问题时可直接在 profiling 数据中检索对应接口名。七、延伸阅读10_label_management.mdLabel 全部 6 个接口的完整参数与返回值说明15_model_running_instance_management.md模型运行实例的构建、绑定、执行与销毁接口docs/zh/design/modules/model/model.mdModel 模块架构理解 Label 在任务容器中的控制流定位include/external/acl/acl_rt.hLabel 与模型运行实例接口的官方头文件声明src/acl/aclrt_impl/label.cppLabel 接口的 ACL 层实现与 RTS 调用链同目录下的其他进阶示例example/2_advanced_features/label/0_simple_label/README_en.md 及 example/2_advanced_features 下的模型运行实例model_ri、条件执行cond_model等示例可对照理解 RI 任务编排的更多玩法。【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表