CANN Runtime 多线程 Device 管理实战:样例 1_device_multi_thread 从编译运行到接口原理
2026/9/18 18:24:43 网站建设 项目流程

CANN Runtime 多线程 Device 管理实战:样例 1_device_multi_thread 从编译运行到接口原理

【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime

本篇技术指南围绕 CANN Runtime 仓库中的样例 1_device_multi_thread 展开,讲解多线程场景下 Device 管理的完整流程:主线程如何指定 Device 并设置 Device 资源限制,工作线程如何查询 Device 属性、下发核函数任务并最终释放资源。读完本文,你可以掌握aclrtSetDeviceaclrtSetDeviceResLimit等 Device 管理接口的正确调用方式,以及该样例的编译运行方法和预期输出,用于在自己的多核函数、多线程推理/训练框架中做 Device 资源隔离与属性查询。

样例概述与产品支持

该样例演示多线程场景下的 Device 管理流程(Multi-thread Device Management Flow),其核心行为是:

  • 主线程:指定用于计算的 Device(aclrtSetDevice(0)),并设置 Device 资源限制(aclrtSetDeviceResLimit,将 Vector Core 数量限制为 1);
  • 工作线程:创建 Stream 后,查询 Device 数量、运行模式、资源限制等信息,然后下发核函数任务(向量加法),并同步等待任务完成、校验结果;
  • 收尾:工作线程释放 Device、Host 内存与 Stream 资源,主线程调用aclFinalize完成去初始化。

样例支持的产品如下:

产品是否支持
Ascend 950PR/Ascend 950DT支持
Atlas A3 训练系列产品/Atlas A3 推理系列产品支持
Atlas A2 训练系列产品/Atlas A2 推理系列产品支持

样例目录结构与关键文件:

  • main.cpp:样例主逻辑,包含主线程与工作线程的全部 Runtime API 调用;
  • run.sh:一键编译运行脚本,内部完成 CMake 配置、构建与执行;
  • CMakeLists.txt:CMake 工程文件,负责编译 AscendC 核函数库与主程序。

编译与运行

运行前需要一台已安装 CANN 软件、且能访问昇腾 AI 处理器的环境。

第 1 步:下载样例代码到安装 CANN 的环境,切换到样例目录。

cd ${git_clone_path}/example/1_basic_features/device/1_device_multi_thread

第 2 步:设置环境变量。

# ${install_root} 替换为 CANN 安装根目录,默认安装在 /usr/local/Ascend 目录 source ${install_root}/cann/set_env.sh # 设置 SOC_VERSION 和 ASCENDC_CMAKE_DIR # -SOC_VERSION: 昇腾 AI 处理器型号,如 Ascend910_9362、Ascend910B2 等 # -ASCENDC_CMAKE_DIR: 样例涉及调用 AscendC 算子,需配置 AscendC 编译器 ascendc.cmake 路径, # 例如 /usr/local/Ascend/cann/x86_64-linux/tikcpp/ascendc_kernel_cmake source ${git_clone_path}/example/set_sample_env.sh

其中 set_sample_env.sh 会协助用户自动识别SOC_VERSIONASCENDC_CMAKE_DIR:从源码结构看,它首先通过example/tools/get_soc_version下编译出的小型辅助二进制调用aclrtGetSocName取得处理器版本字符串,再按主机架构(x86_64/aarch64)在 CANN 安装目录下探测tikcpp/ascendc_kernel_cmake目录并导出SOC_VERSIONASCENDC_CMAKE_DIRASCEND_HOME_PATH等变量,免去手工填写型号。

第 3 步:执行运行脚本。

bash run.sh

run.sh 的关键逻辑是:先检查ASCEND_HOME_PATH是否已设置(未设置则提示先 source CANN 的set_env.sh),然后依次执行cmake -B build -DASCEND_CANN_PACKAGE_PATH=...cmake --build build -jcmake --install build,最后运行./build/main并将输出同时写入output_msg.txt

CMakeLists.txt 中,SOC_VERSIONASCENDC_CMAKE_DIR直接取自环境变量,工程要求 CMake 最低版本 3.16.0,并包含 CANN 头文件目录与库目录;ascendc_library负责编译 kernel_add.cpp 生成静态核函数库kernels,主程序main链接kernelspthread(多线程所需)。

多线程执行流程与源码走读

样例代码 main.cpp 分为三个部分:

主线程:指定 Device 并设置资源限制

main函数中的调用顺序(对应 main.cpp):

CHECK_ERROR(aclInit(nullptr)); // 初始化 CANN Runtime CHECK_ERROR(aclrtSetDevice(0)); // 指定 Device 0 用于计算 CHECK_ERROR(aclrtSetDeviceResLimit(0, ACL_RT_DEV_RES_VECTOR_CORE, 1)); // 限制 Vector Core 数量为 1 std::thread t1(RunThread); // 启动工作线程 t1.join(); CHECK_ERROR(aclFinalize()); // 去初始化

几个关键点:

  1. aclrtSetDevice必须在aclInit之后、任何 Device 相关操作之前调用,它把当前线程/进程绑定到 Device 0。样例中主线程先设置一次,工作线程内部(Init函数)再次调用aclrtSetDevice(0),保证工作线程也持有了 Device 上下文——这是多线程场景的典型做法:每个需要下发任务的线程都应确认 Device 已指定
  2. aclrtSetDeviceResLimit(0, ACL_RT_DEV_RES_VECTOR_CORE, 1)表示为当前进程设置 Device 0 的 Vector Core 数量上限为 1。资源类型来自头文件 acl_rt.h 中的枚举:
typedef enum { ACL_RT_DEV_RES_CUBE_CORE = 0, // Cube Core 数量限制 ACL_RT_DEV_RES_VECTOR_CORE, // Vector Core 数量限制 } aclrtDevResLimitType;

接口声明见 acl_rt.h:

ACL_FUNC_VISIBILITY aclError aclrtSetDeviceResLimit(int32_t deviceId, aclrtDevResLimitType type, uint32_t value);

该接口的作用是限制当前进程可使用的 AI 处理器计算核数量,常用于多进程共享一颗昇腾处理器时做资源配额(如把 24 个 Vector Core 中的 1 个分给某个进程)。设置后的效果会在后文工作线程的aclrtGetDeviceResLimit查询中验证,输出为VECTOR_CORE 1。 3.资源限制的生命周期:按 API 参考 的说明,设置后进程内对该 Device 的查询将返回该限制值;aclrtResetDeviceResLimit可将限制恢复为硬件默认配置。样例在工作线程末尾(aclrtFree之后、销毁 Stream 之前)调用了aclrtResetDeviceResLimit(0),演示了完整的“设置 → 查询使用 → 重置”闭环。

工作线程:查询 Device 信息

工作线程RunThread首先通过Init函数再次aclrtSetDevice(0)aclrtCreateStream创建 Stream,随后调用DeviceInfoQuery()依次查询(对应 main.cpp):

接口查询内容说明
aclrtGetSocName()昇腾 AI 处理器型号Ascend910_9362
aclrtGetDeviceCount(&deviceCount)可用 Device 数量Device ID 取值范围为[0, deviceCount-1]
aclrtQueryDeviceStatus(0, &deviceStatus)Device 状态正常状态下返回 0
aclrtGetRunMode(&runMode)运行模式0 为ACL_DEVICE(真机模式),1 为ACL_HOST(Host 仿真模式)
aclrtGetDeviceUtilizationRate(0, &utilizationInfo)模块利用率返回 Cube/Vector/AI CPU/内存四类利用率,utilizationExtend置空即可
aclrtDeviceGetStreamPriorityRange(&least, &greatest)Stream 优先级范围硬件支持的 Stream 优先级最小/最大值
aclrtGetDeviceInfo(0, ACL_DEV_ATTR_VECTOR_CORE_NUM, &vectorCoreNum)Device 属性此处查询 Vector Core 数量

这些接口覆盖了 Device 管理类别中“查询”方向的全部常用能力,与样例 README 中列出的 API 清单一致。值得注意的是aclrtGetRunMode:样例示例输出中显示RunMode is ACL_HOST,说明该示例输出是在 Host 侧仿真运行模式(ACL_HOST)下得到的,在真机(ACL_DEVICE)上该字段会不同。

工作线程:内存、数据搬运与核函数下发

查询完成后,工作线程执行一次完整的向量加法计算(对应 main.cpp):

  1. 内存分配aclrtMallocHost分配 3 块 Host 侧内存(hostSrcAhostSrcBhostDst);aclrtMalloc分配 3 块 Device 侧内存,标志位使用ACL_MEM_MALLOC_HUGE_FIRST(优先使用大块内存分配,减少碎片)。数据规模为TOTAL_SIZE = 1024个 float,即DATA_SIZE = 1024 * sizeof(float)字节。
  2. 数据初始化与 H2D 拷贝:将hostSrcA[i] = hostSrcB[i] = i,然后用aclrtMemcpy(..., ACL_MEMCPY_HOST_TO_DEVICE)把两个输入数组拷到 Device。
  3. 查询资源限制aclrtGetDeviceResLimit(0, ACL_RT_DEV_RES_VECTOR_CORE, &resLimitValue)取回主线程设置的 Vector Core 限制值(应为 1),并打印Get device resLimit success. VECTOR_CORE 1.
  4. 核函数下发AddDo(resLimitValue, stream, devSrcA, devSrcB, devDst, TOTAL_SIZE)将向量加法核函数提交到工作线程自己创建的 Stream 上。AddDo的声明见 kernel_add.h,其 AscendC 实现位于 kernel_add.cpp;aclrtSynchronizeStream(stream)阻塞等待 Stream 上任务全部完成。
  5. D2H 拷贝与校验aclrtMemcpy(..., ACL_MEMCPY_DEVICE_TO_HOST)取回结果,打印前 10 个元素并与期望值hostSrcA[i] + hostSrcB[i]对比。
  6. 资源释放aclrtResetDeviceResLimit(0)重置资源限制 →aclrtFree/aclrtFreeHost释放全部内存 →aclrtDestroyStream销毁 Stream →aclrtResetDeviceForce(0)强制复位 Device、回收该进程在 Device 上的所有剩余资源。aclrtResetDeviceForce属于较强的清理手段(回收 Device 资源),通常用于进程退出前的兜底清理。

多线程视角的要点

从源码结构看,该样例验证了两个多线程使用惯例:

  • Device 上下文是线程相关的:主线程调用aclrtSetDevice后,工作线程仍需在Init中再次调用aclrtSetDevice(0),两个线程各自持有 Device 0 的上下文,工作线程的 Stream、内存分配与核函数下发都发生在自己的工作线程上,互不干扰。
  • 资源限制是进程级的:主线程设置的aclrtSetDeviceResLimit对工作线程中同一 Device 的查询立即可见,这为“主控线程统一配额、业务线程执行任务”的框架化编程提供了依据。

涉及的 CANN Runtime API 一览

样例涉及的关键功能点及接口如下(与 README_en.md 一致):

  • 初始化aclInit初始化、aclFinalize去初始化;
  • Device 管理aclrtSetDevice指定计算 Device;aclrtGetSocName查询处理器型号;aclrtGetDeviceCount获取可用 Device 数量;aclrtQueryDeviceStatus查询 Device 状态;aclrtGetRunMode获取运行模式;aclrtGetDeviceUtilizationRate查询 Cube/Vector/AI CPU 等模块利用率;aclrtDeviceGetStreamPriorityRange查询硬件支持的 Stream 优先级范围;aclrtGetDeviceInfo获取 Device 属性信息;aclrtSetDeviceResLimit/aclrtGetDeviceResLimit/aclrtResetDeviceResLimit设置、获取、重置当前进程的 Device 资源限制;aclrtResetDeviceForce强制复位 Device 并回收资源;
  • Stream 管理aclrtCreateStream创建 Stream、aclrtSynchronizeStream阻塞等待 Stream 任务完成、aclrtDestroyStream销毁 Stream;
  • 内存管理aclrtMalloc申请 Device 内存、aclrtMallocHost申请 Host 内存、aclrtFree/aclrtFreeHost释放内存;
  • 数据传输aclrtMemcpy内存复制。

接口声明均可在 acl_rt.h 中查阅;资源限制相关接口的参数与产品支持矩阵参见 Runtime 配置 API 参考,Device 管理接口(如aclrtSetDeviceaclrtGetDeviceCount)参见 Device 管理 API 参考。

示例输出

运行bash run.sh后,标准输出形如(完整输出同时保存在样例目录的output_msg.txt中):

[INFO] Start to run device_multi_thread sample. [INFO] Current Ascend chipset platform is: Ascend910_9362. [INFO] Get device count success. deviceCount: 2. [INFO] Query device status success. deviceStatus: 0. [INFO] RunMode is ACL_HOST. [INFO] Get device resLimit success. VECTOR_CORE 1. [INFO] The results (first 10 elements) of the kernel function: [INFO] Result: hostDst[0]: 0.000000 Expected value: 0.000000 [INFO] Result: hostDst[1]: 2.000000 Expected value: 2.000000 ... [INFO] Result: hostDst[9]: 18.000000 Expected value: 18.000000 [INFO] Run the device_multi_thread sample successfully.

输出中的几个验证点:

  • deviceCount: 2表明当前环境可见 2 个 Device,具体数值随硬件配置变化;
  • RunMode is ACL_HOST表示当前处于 Host 仿真运行模式,真实 NPU 环境下将显示ACL_DEVICE
  • VECTOR_CORE 1与主线程aclrtSetDeviceResLimit(..., 1)的设置值一致,证明资源限制已生效;
  • 结果序列0, 2, 4, ..., 18符合srcA[i] + srcB[i] = i + i的期望值,说明核函数执行正确。

小结

该样例是理解 CANN Runtime 多线程 Device 管理的起点:主线程负责“选卡 + 配额”(aclrtSetDevice+aclrtSetDeviceResLimit),工作线程负责“查询 + 执行 + 清理”(Device 属性查询、Stream/内存管理、核函数下发与aclrtResetDeviceForce兜底)。如果你在多进程/多线程框架中需要限制某个进程占用的 Cube 或 Vector Core 数量、查询 Device 利用率与 Stream 优先级范围,可以直接参考 main.cpp 的调用顺序;同目录下的其他 Device 样例(device 目录 README)还覆盖了单 Device 常规使用、多 Device 与 P2P、设备身份映射等场景,可结合本样例的接口基础继续扩展。

【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询