news 2026/9/19 23:54:11

CANN Runtime Device管理接口全解析:设备设置、查询、P2P交互与资源限制实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CANN Runtime Device管理接口全解析:设备设置、查询、P2P交互与资源限制实战指南

CANN Runtime Device管理接口全解析:设备设置、查询、P2P交互与资源限制实战指南

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

导读

Device(设备)管理是 CANN Runtime 编程模型的入口与基石:任何算子下发、内存分配、Stream 编排都建立在一个可用的 Device 之上。本文基于 CANN Runtime 设备管理接口文档,系统梳理约 40 个aclrt*设备管理接口的分类、语义、参数与约束,并结合开源仓库中的头文件声明、示例工程与枚举定义,帮助读者掌握设备生命周期管理(Set/Reset)、设备信息查询、Device 间 P2P 数据交互、溢出状态检测、设备 ID 映射(用户/逻辑/物理)以及 Device 资源限制配置等核心能力,可直接指导多卡训练、容器化部署与故障定位场景下的编程实践。


一、接口全景:Device 管理能力地图

Device 管理接口全部以aclrt前缀命名,声明于 acl_rt.h。按照功能可划分为以下七大类:

功能类别代表接口核心用途
设备生命周期aclrtSetDevice/aclrtResetDevice/aclrtResetDeviceForce指定运算 Device、释放 Device 资源
设备状态查询aclrtGetDevice/aclrtGetDeviceCount/aclrtQueryDeviceStatus/aclrtGetRunMode/aclrtGetSocName/aclrtDeviceGetUuid获取当前 Device、可用数量、运行模式、芯片版本等
设备性能与利用率aclrtGetDeviceUtilizationRate/aclrtGetDeviceInfo/aclrtGetDevicesTopo/aclrtDeviceGetStreamPriorityRange/aclrtGetDeviceCapability查询 Cube/Vector 利用率、设备属性、拓扑关系、Stream 优先级范围、特性支持
P2P 数据交互aclrtDeviceCanAccessPeer/aclrtDeviceEnablePeerAccess/aclrtDeviceDisablePeerAccess/aclrtDevicePeerAccessStatusDevice 间数据交互的查询、开启、关闭
溢出检测与同步aclrtGetOverflowStatus/aclrtResetOverflowStatus/aclrtSynchronizeDevice/aclrtSynchronizeDeviceWithTimeout获取/清除溢出状态、设备级同步
设备 ID 映射aclrtGetLogicDevIdByUserDevId等 6 个转换接口用户设备 ID、逻辑设备 ID、物理设备 ID 之间互转
资源限制与高级能力aclrtDeviceSetLimit/aclrtDeviceGetLimit/aclrtDeviceL2CacheFlush/aclrtDeviceGetHostAtomicCapabilities/aclrtDeviceGetP2PAtomicCapabilities/aclrtDeviceGetPCIBusId/aclrtDeviceGetByPCIBusId/aclrtDeviceGetBareTgid/aclrtRegDeviceStateCallback/aclrtSetTsDevice/aclrtSetDeviceSatMode/aclrtGetDeviceSatMode资源限制、L2 Cache 清空、原子操作能力、PCI Bus ID、进程 ID、状态回调等

通用返回值约定:除aclrtGetSocName外,所有接口均返回aclError类型,返回 0 表示成功,返回其他值表示失败,错误码定义请参见 aclError。各接口参数中用到的枚举、结构体类型,可在 25-02_Enumerations.md 与 25-04_Structs.md 中查询。


二、设备生命周期管理:Set 与 Reset

设备生命周期管理是整个 Runtime 编程的"入口"和"出口",几乎所有业务代码都以aclrtSetDevice开始、以aclrtResetDevice/aclrtResetDeviceForce结束。仓库示例 0_device_normal/main.cpp 展示了这一标准流程:

CHECK_ERROR(aclInit(nullptr)); CHECK_ERROR(aclrtSetDevice(deviceId)); // 指定运算 Device,隐式创建默认 Context/Stream // ... 业务处理(分配内存、下发算子、同步)... CHECK_ERROR(aclrtSynchronizeDevice()); CHECK_ERROR(aclrtDestroyStream(stream)); CHECK_ERROR(aclrtResetDeviceForce(deviceId)); // 复位 Device,释放资源 CHECK_ERROR(aclFinalize());

2.1 aclrtSetDevice:指定运算 Device

aclError aclrtSetDevice(int32_t deviceId)
  • 功能:指定当前线程中用于运算的 Device。多 Device 场景下可在进程中通过该接口切换到其它 Device;不同线程可指定同一个 Device 用于运算。
  • 默认 Context 机制:调用本接口会隐式创建默认 Context,其中包含一个默认 Stream。在同一个进程的多个线程中,如果通过aclrtSetDevice指定相同的 Device,这些线程将共享同一个默认 Context。这正是多线程编程中 1_device_multi_thread/main.cpp 无需显式创建 Context 即可并发使用同一 Device 的底层原因。
  • 参数deviceId为 Device ID,取值范围为[0, 可用的Device数量-1],可用数量通过aclrtGetDeviceCount获取。
  • 约束:IPV350 上不支持默认 Context 和默认 Stream,不能依赖本接口隐式创建的资源。

2.2 aclrtResetDevice:引用计数式复位

aclError aclrtResetDevice(int32_t deviceId)
  • 释放默认 Context、默认 Stream 以及默认 Context 下创建的所有 Stream;若任务还未完成,系统会等待任务完成后再释放。
  • 引用计数语义(关键):本接口内部涉及引用计数实现,建议与aclrtSetDevice配对使用aclrtSetDevice每调用一次引用计数加一,aclrtResetDevice每调用一次引用计数减一,计数减到 0 时才真正释放 Device 资源。若多次调用aclrtSetDevice而不调用 Reset,进程退出时也会自动释放本进程使用的 Device 资源。
  • 复位前资源释放顺序:若要复位的 Device 上存在显式创建的 Context、Stream、Event,建议按如下顺序调用,否则可能导致业务异常:
aclrtDestroyEvent(释放Event) --> aclrtDestroyStream(释放显式Stream) --> aclrtDestroyContext(释放显式Context) --> aclrtResetDevice

2.3 aclrtResetDeviceForce:强制复位

aclError aclrtResetDeviceForce(int32_t deviceId)
  • 释放的资源范围与aclrtResetDevice相同(默认 Context、默认 Stream 及其下所有 Stream)。
  • 不要求配对:本接口可与aclrtSetDevice配对使用,也可不配对。不配对时,针对同一个 Device,调用一次或多次aclrtSetDevice后,仅需调用一次aclrtResetDeviceForce即可释放资源:
// 与 aclrtSetDevice 接口配对使用: aclrtSetDevice(1) -> aclrtResetDeviceForce(1) -> aclrtSetDevice(1) -> aclrtResetDeviceForce(1) // 与 aclrtSetDevice 接口不配对使用: aclrtSetDevice(1) -> aclrtSetDevice(1) -> aclrtResetDeviceForce(1)
  • 多线程约束:多线程场景下,针对同一个 Device,如果每个线程都各自调用 Set 和 ResetForce,后执行的 ResetForce 会因为资源已被先执行的线程释放而报错。正确方式是仅在最后一个线程执行结束时调用一次aclrtResetDeviceForce
时间线 -----------------------------------------------------------------------------> 线程1:aclrtSetDevice(1) 线程2:aclrtSetDevice(1) aclrtResetDeviceForce(1)
  • 混用规则:两个 Reset 接口可以混用,但调用次数与顺序有严格限制。正确方式是两个 Reset 接口分别与 Set 配对,且aclrtResetDeviceForceaclrtResetDevice之后;错误方式包括引用计数减到 0 后再调用任一 Reset 接口,或 ResetForce 先于 ResetDevice 调用:
# 混用时的正确方式: aclrtSetDevice(1) -> aclrtResetDevice(1) -> aclrtSetDevice(1) -> aclrtResetDeviceForce(1) aclrtSetDevice(1) -> aclrtSetDevice(1) -> aclrtResetDevice(1) -> aclrtResetDeviceForce(1) # 混用时的错误方式: aclrtSetDevice(1) -> aclrtSetDevice(1) -> aclrtResetDevice(1)-->aclrtResetDevice(1)-->aclrtResetDeviceForce(1) aclrtSetDevice(1) -> aclrtSetDevice(1) -> aclrtResetDevice(1)-->aclrtResetDeviceForce(1)-->aclrtResetDeviceForce(1) aclrtSetDevice(1) -> aclrtSetDevice(1) -> aclrtResetDeviceForce(1)-->aclrtResetDevice(1)

三、设备信息查询:从数量到能力的全方位探测

3.1 aclrtGetDeviceCount 与 aclrtGetDevice

aclError aclrtGetDeviceCount(uint32_t *count) // 获取可用 Device 数量 aclError aclrtGetDevice(int32_t *deviceId) // 获取当前正在使用的 Device ID
  • aclrtGetDeviceCount是几乎所有 Device 管理接口的前置查询:aclrtSetDeviceaclrtGetDeviceUtilizationRateaclrtQueryDeviceStatus、P2P 系列接口等都以它返回的数量确定 Device ID 的取值范围[0, count-1]。在 2_device_P2P/main.cpp 中,示例先查询数量并判断deviceCount >= 2才继续执行 P2P 流程,否则直接跳过,这是多卡程序的标准防御写法。
  • aclrtGetDevice用于获取当前正在使用的 Device ID。约束:如果没有提前调用aclrtSetDevice指定计算设备,调用本接口会返回错误。

3.2 aclrtGetRunMode:判断 AI 软件栈运行模式

aclError aclrtGetRunMode(aclrtRunMode *runMode)
  • 返回当前 AI 软件栈的运行模式,类型为 aclrtRunMode 枚举。仓库中该枚举定义了两个取值:ACL_HOST表示 AI 软件栈运行在 Host 侧,ACL_DEVICE表示 AI 软件栈运行在 Device 的 Control CPU 或板端环境上。从枚举注释可以看到,ACL_DEVICE选项在 Ascend 950PR/Ascend 950DT、Atlas A3 系列、Atlas A2 系列产品上均不支持。
  • 典型用途:应用据此判断自身是运行在 Host 侧还是 Device 侧,从而决定内存分配策略(Host 内存 vs Device 内存)和同步方式。

3.3 aclrtQueryDeviceStatus:设备健康状态探测

aclError aclrtQueryDeviceStatus(int32_t deviceId, aclrtDeviceStatus *deviceStatus)
  • 查询 Device 是"正常可用"还是"异常不可用"。deviceStatus类型为 aclrtDeviceStatus 枚举,定义于 25-02_Enumerations.md。该接口适合在训练/推理任务启动前做设备健康检查,规避把任务下发到异常 Device 上。
  • 注意:IPV350 不支持该接口。

3.4 aclrtGetSocName:查询 AI 处理器版本

const char *aclrtGetSocName()
  • 返回当前运行环境 AI 处理器版本名称的字符串指针,可用于软件栈根据 SoC 名称做差异化路径分发。返回值有两点特殊语义:
    • 获取失败时返回空指针;
    • 若运行环境上 Device 数量大于 1,固定返回 Device 0 的版本名称。

3.5 aclrtGetDeviceUtilizationRate:Cube/Vector 利用率查询

aclError aclrtGetDeviceUtilizationRate(int32_t deviceId, aclrtUtilizationInfo *utilizationInfo)
  • 查询 Device 上 Cube、Vector、AI CPU 等的利用率,结果写入 aclrtUtilizationInfo 结构体。以下约束务必注意:
    • 查询 Vector 利用率时若结果为 -1,表示 Vector 不存在;
    • 当前版本不支持查询 Device 内存利用率,查询得到的结果为 -1;
    • 开启 Profiling 功能时,不支持调用本接口,返回值无实际意义;
    • Atlas A2 训练/推理系列、Atlas 训练系列、Atlas 推理系列产品在昇腾虚拟化实例场景下同样不支持本接口。

3.6 aclrtGetDeviceInfo:设备属性查询

aclError aclrtGetDeviceInfo(uint32_t deviceId, aclrtDevAttr attr, int64_t *value)
  • 按属性项查询指定 Device 的信息。属性类型aclrtDevAttr定义于 25-02_Enumerations.md,从仓库枚举可以看到至少包括:ACL_DEVICE_INFO_AI_CORE_NUM(AI Core 数量)、ACL_DEVICE_INFO_VECTOR_CORE_NUM(Vector Core 数量)、ACL_DEVICE_INFO_L2_SIZE(L2 Buffer 大小,单位 Byte)等。程序据此可动态适配不同算力的芯片。

3.7 aclrtGetDeviceCapability 与 aclrtGetDevicesTopo

aclError aclrtGetDeviceCapability(int32_t deviceId, aclrtDevFeatureType devFeatureType, int32_t *value) aclError aclrtGetDevicesTopo(uint32_t deviceId, uint32_t otherDeviceId, uint64_t *value)
  • aclrtGetDeviceCapability查询指定 Device 是否支持某特性,输出值取ACL_DEV_FEATURE_SUPPORT(1)ACL_DEV_FEATURE_NOT_SUPPORT(0)。这两个宏在 acl_rt.h 中定义为0x000000010x00000000,与文档描述一致。
  • aclrtGetDevicesTopo获取两个 Device 之间的网络拓扑关系。拓扑值通过位掩码宏表达,全部定义于 acl_rt.h:
宏定义含义
ACL_RT_DEVS_TOPOLOGY_HCCS0x01ULL通过 HCCS(Huawei Cache Coherence System,华为缓存一致性系统)连接
ACL_RT_DEVS_TOPOLOGY_PIX0x02ULL通过同一个 PCIe Switch 连接
ACL_RT_DEVS_TOPOLOGY_PIB0x04ULL预留值,暂不支持
ACL_RT_DEVS_TOPOLOGY_PHB0x08ULL通过 PCIe Host Bridge 连接
ACL_RT_DEVS_TOPOLOGY_SYS0x10ULL通过 SMP(对称多处理)连接,NUMA 节点间互连
ACL_RT_DEVS_TOPOLOGY_SIO0x20ULL片内连接,两个 DIE 之间通过该方式连接
ACL_RT_DEVS_TOPOLOGY_HCCS_SW0x40ULL通过 HCCS Switch 连接
  • 约束:aclrtGetDevicesTopo不支持在 Atlas 200I/500 A2 推理产品的 Ascend RC 形态下调用;IPV350 不支持。

3.8 其他查询类接口速览

  • aclrtDeviceGetStreamPriorityRange(int32_t *leastPriority, int32_t *greatestPriority):查询硬件支持的 Stream 最低、最高优先级,创建带优先级的 Stream 前先查询取值范围。
  • aclrtDeviceGetUuid(int32_t deviceId, aclrtUuid *uuid):获取 Device 的唯一标识 UUID,用于跨进程/跨机识别同一物理设备。产品支持上,仅 Ascend 950 系列、Atlas A3 系列、Atlas A2 系列支持。
  • aclrtDeviceGetPCIBusId/aclrtDeviceGetByPCIBusId:Device ID 与 PCI Bus ID(格式domain:bus:device.function,如0000:3d:00.0)之间的双向转换。len缓冲区长度必须大于等于 13(12 个字符加结尾\0)。约束:虚拟机/容器场景返回虚拟化层分配的虚拟 PCI Bus ID,仅保证当前虚拟机/容器内合法唯一;非 PCIe 互连形态(如 HCCS、Unified Bus)的设备返回ACL_ERROR_RT_FEATURE_NOT_SUPPORT
  • aclrtDeviceGetBareTgid(int32_t *pid):获取当前进程 ID。接口内部已适配物理机、虚拟机场景,在需要配合 aclrtMemExportToShareableHandle 做物理内存共享时,务必使用本接口获取进程 ID 而非自行取 pid,否则可能导致后续使用异常。

四、Device 间 P2P 数据交互

CANN Runtime 支持同一主机内多个 Device 之间的直接数据交互(P2P),无需经过 Host 中转。仓库示例 2_device_P2P/main.cpp 完整演示了"查询支持 → 双向开启 → 跨设备拷贝 → 关闭"的全流程,是学习 P2P 编程的最佳入口。

4.1 交互流程与四个核心接口

aclError aclrtDeviceCanAccessPeer(int32_t *canAccessPeer, int32_t deviceId, int32_t peerDeviceId) aclError aclrtDeviceEnablePeerAccess(int32_t peerDeviceId, uint32_t flags) aclError aclrtDeviceDisablePeerAccess(int32_t peerDeviceId) aclError aclrtDevicePeerAccessStatus(int32_t deviceId, int32_t peerDeviceId, int32_t *status)

标准流程(与示例代码对应):

uint32_t deviceCount = 0; CHECK_ERROR(aclrtGetDeviceCount(&deviceCount)); // 先确认至少 2 个 Device CHECK_ERROR(aclrtSetDevice(0)); int32_t canAccessPeer = 0; CHECK_ERROR(aclrtDeviceCanAccessPeer(&canAccessPeer, 0, 1)); // 查询 0 能否访问 1 if (canAccessPeer == 1) { CHECK_ERROR(aclrtDeviceEnablePeerAccess(1, 0)); // 开启 Device0 -> Device1 方向 // 在 Device 0 上申请并初始化 P2P 内存 CHECK_ERROR(aclrtMalloc(&dev0, memSize, ACL_MEM_MALLOC_HUGE_FIRST_P2P)); // 切换到 Device 1 CHECK_ERROR(aclrtSetDevice(1)); CHECK_ERROR(aclrtDeviceEnablePeerAccess(0, 0)); // 开启 Device1 -> Device0 方向 CHECK_ERROR(aclrtMalloc(&dev1, memSize, ACL_MEM_MALLOC_HUGE_FIRST_P2P)); // Device 间直接拷贝(不经过 Host) CHECK_ERROR(aclrtMemcpy(dev1, memSize, dev0, memSize, ACL_MEMCPY_DEVICE_TO_DEVICE)); CHECK_ERROR(aclrtSynchronizeDevice()); // 关闭双向交互并释放资源 CHECK_ERROR(aclrtDeviceDisablePeerAccess(0)); CHECK_ERROR(aclrtResetDeviceForce(1)); CHECK_ERROR(aclrtSetDevice(0)); CHECK_ERROR(aclrtDeviceDisablePeerAccess(1)); CHECK_ERROR(aclrtResetDeviceForce(0)); }

4.2 关键语义与约束

  • 单向性aclrtDeviceEnablePeerAccess开启的是单向数据交互。例如当前 Device ID 为 0,调用本接口指定 Device 1 后,仅 0→1 方向可行;若要启用 1→0 方向,需切换到 Device 1 后再次调用并指定 Device 0。
  • Device 级作用域:开启/关闭数据交互均为 Device 级操作。
  • flags参数:保留参数,当前必须设置为 0。
  • aclrtDevicePeerAccessStatus输出:0 表示未开启数据交互,1 表示已开启。若传入的 Device ID 超出[0, 可用的Device数量-1]区间,查询结果为 0 或直接返回ACL_ERROR_RT_PARAM_INVALID
  • 适用范围(来自文档约束):
    • 仅支持物理机和容器场景;
    • 仅支持同一个 PCIe Switch 内 Device 间数据交互(AI Server 场景跨 PCIe Switch 也支持);
    • 仅支持同一个物理机/容器内的 Device 间交互;
    • 仅支持同一个进程内、线程间的 Device 间交互,不支持跨进程;
    • Atlas 推理系列产品在 Control CPU 开放形态下(应用运行在 Device 的 Control CPU 上),P2P 系列接口不支持 Device 间数据交互;
    • Atlas 200I/500 A2 推理产品与 IPV350 不支持 P2P 系列接口。

五、溢出状态检测与设备同步

5.1 浮点溢出状态:Get 与 Reset

aclError aclrtGetOverflowStatus(void *outputAddr, size_t outputSize, aclrtStream stream) aclError aclrtResetOverflowStatus(aclrtStream stream)
  • aclrtGetOverflowStatus获取当前 Device 下所有 Stream上任务的溢出状态,并将状态值拷贝到用户申请的 Device 内存中。异步接口
    • outputAddr:用户申请的 Device 内存(例如通过aclrtMalloc申请);
    • outputSize:固定为 64 Byte;
    • stream:指定用于下发溢出状态查询任务的 Stream。
  • aclrtResetOverflowStatus清除当前 Device 下所有 Stream 上任务的溢出状态,同样为异步接口
  • 对于 Ascend 950PR/Ascend 950DT、Atlas A3 系列、Atlas A2 系列产品,查询/清除的溢出状态是进程级别的。
  • 结合 aclrtSetDeviceSatMode(设置浮点计算结果输出模式)与aclrtGetDeviceSatMode(查询当前模式)使用,可实现"饱和截断 vs 溢出报错"两种浮点行为的探测与恢复。aclrtSetDeviceSatMode设置成功后,仅对后续新创建的 Stream 生效,对已创建的 Stream 不生效。

5.2 设备级同步:SynchronizeDevice

aclError aclrtSynchronizeDevice(void) aclError aclrtSynchronizeDeviceWithTimeout(int32_t timeout)
  • aclrtSynchronizeDevice阻塞当前线程,直到与当前线程绑定的 Context 所对应的 Device 完成运算。
  • aclrtSynchronizeDeviceWithTimeout在基础上支持超时退出,适合应用异常时自行退出防挂死:
    • timeout = -1:永久等待,行为与aclrtSynchronizeDevice一致;
    • timeout > 0:具体的超时时间,单位毫秒;
    • 超时退出时返回ACL_ERROR_RT_STREAM_SYNC_TIMEOUT
  • 多 Device 场景下,等待的是当前 Context 对应的 Device,因此切换 Device 后要重新理解"当前"语义。

六、用户设备 ID、逻辑设备 ID、物理设备 ID 映射

容器与多卡场景下存在三种设备 ID,理解其映射关系是正确使用ASCEND_RT_VISIBLE_DEVICES环境变量的前提。

6.1 三种 ID 的定义与基本关系

  • 用户设备 ID(User Dev ID):应用层通过aclrtSetDevice传入的 Device ID。
  • 逻辑设备 ID(Logic Dev ID):Runtime 内部的设备索引。
  • 物理设备 ID(Phy Dev ID):物理机上真实的设备编号。

基本规则:

  • 若未设置ASCEND_RT_VISIBLE_DEVICES环境变量,逻辑设备 ID 与用户设备 ID 相同;
  • 非容器场景下,物理设备 ID 与逻辑设备 ID 相同。

6.2 容器 + 环境变量的映射示例

文档以"容器场景且设置ASCEND_RT_VISIBLE_DEVICES环境变量"为例:通过环境变量设置的 Device ID 依次为1、2,对应的 Device 索引值依次为0、1;通过aclrtSetDevice设置的用户设备 ID 为0(即索引值 0),因此用户设备 ID=0 对应逻辑设备 ID=1;容器中的逻辑设备 ID=1 又映射到物理设备 ID=6,最终实际使用 ID 为 6 的物理设备进行计算。ASCEND_RT_VISIBLE_DEVICES的详细介绍可参考仓库中的 环境变量参考文档。

6.3 六个转换接口

接口功能
aclrtGetLogicDevIdByUserDevId(userDevid, logicDevId)用户设备 ID → 逻辑设备 ID
aclrtGetUserDevIdByLogicDevId(logicDevId, userDevid)逻辑设备 ID → 用户设备 ID
aclrtGetLogicDevIdByPhyDevId(phyDevId, logicDevId)物理设备 ID → 逻辑设备 ID
aclrtGetPhyDevIdByLogicDevId(logicDevId, phyDevId)逻辑设备 ID → 物理设备 ID
aclrtGetUserDevIdByPhyDevId(phyDevId, userDevId)物理设备 ID → 用户设备 ID
aclrtGetPhyDevIdByUserDevId(userDevId, phyDevId)用户设备 ID → 物理设备 ID

重要提示(来自文档)aclrtGetLogicDevIdByPhyDevIdaclrtGetPhyDevIdByLogicDevId两个接口中"逻辑设备 ID"的语义描述并不正确,其参数实际对应的是用户设备 ID。为修复该问题,Runtime 提供了aclrtGetUserDevIdByPhyDevIdaclrtGetPhyDevIdByUserDevId作为替代。新代码应优先使用语义正确的替代接口,避免因命名歧义引入设备选择错误。


七、Device 资源限制与高级能力

7.1 aclrtDeviceSetLimit / aclrtDeviceGetLimit:进程级资源限制

aclError aclrtDeviceSetLimit(aclrtDeviceLimit limit, size_t value) aclError aclrtDeviceGetLimit(aclrtDeviceLimit limit, size_t *value)
  • 用途:设置/获取当前进程的 Device 资源限制,例如 SIMT 算子栈空间、SIMT Printf 维测空间等。资源类型枚举 aclrtDeviceLimit 定义于 acl_rt.h,共 5 项:
typedef enum aclrtDeviceLimit { ACL_RT_DEV_LIMIT_SIMT_STACK_SIZE = 0, // SIMT 算子栈空间大小 ACL_RT_DEV_LIMIT_SIMT_DVG_WARP_STACK_SIZE = 1, // SIMT DVG WARP 栈空间大小 ACL_RT_DEV_LIMIT_SIMD_STACK_SIZE = 2, // SIMD 栈空间大小 ACL_RT_DEV_LIMIT_SIMD_PRINTF_FIFO_SIZE_PER_CORE = 3, // SIMD Printf 每 Core FIFO 大小 ACL_RT_DEV_LIMIT_SIMT_PRINTF_FIFO_SIZE = 4, // SIMT Printf FIFO 大小 } aclrtDeviceLimit;
  • 调用时机:建议在aclInit之后、aclrtSetDevice之前调用,确保资源限制生效。若多次调用aclrtSetDevice,需注意 Set/Reset 引用计数配对:引用计数减到 0 后,先重新调用aclrtDeviceSetLimit再调用aclrtSetDevice,配置才能生效:
aclInit --> aclrtDeviceSetLimit(第一次设置) --> aclrtSetDevice(配置生效) --> 业务处理 --> aclrtResetDevice(重置 Device 资源) --> aclrtDeviceSetLimit(第二次设置) --> aclrtSetDevice(配置生效)
  • 配置优先级:通过本接口或aclInit接口均可配置资源限制值,后配置的覆盖先配置的;本接口更灵活,便于运行时调整。
  • 作用域:配置作用于当前进程,所有 Device 共用同一套配置,无法为不同 Device 设置不同值。
  • Device 0 依赖:本接口内部固定使用 Device 0 进行设置。若设置了ASCEND_RT_VISIBLE_DEVICES且不包含 Device 0,则通过本接口或aclInit配置资源限制均会失败,因此使用该环境变量时需确保其值包含 Device 0。
  • aclrtDeviceGetLimit读取语义:读取的是进程内配置的瞬时值,不保证多线程并发安全。典型陷阱:先 Set 栈大小 A 并 SetDevice 生效后查询得 A;随后再 Set 为 B 但未重新 SetDevice,此时查询得 B,而实际生效的资源限制仍为 A。
  • 产品差异:Atlas A3 系列、Atlas A2 系列查询ACL_RT_DEV_LIMIT_SIMT_STACK_SIZEACL_RT_DEV_LIMIT_SIMT_DVG_WARP_STACK_SIZEACL_RT_DEV_LIMIT_SIMT_PRINTF_FIFO_SIZE时返回ACL_ERROR_RT_FEATURE_NOT_SUPPORT;Ascend 950 系列查询ACL_RT_DEV_LIMIT_SIMT_STACK_SIZE返回对齐后 ×32(每 warp 线程数)的值,如设置 256 查询返回 8192,查询ACL_RT_DEV_LIMIT_SIMT_DVG_WARP_STACK_SIZE返回对齐后的值(不乘线程数),如设置 512 查询返回 512。

7.2 其他高级能力接口

  • aclrtDeviceL2CacheFlush(void *rsv):清空当前 Device 的 L2 Cache,接口返回即表示清空完成;rsv预留参数当前必须传nullptr。约束:仅 Ascend 950 系列支持;昇腾虚拟化实例场景不支持;不建议高频调用(影响业务性能);若清空期间该 Device 上有并发业务执行,L2 Cache 可能被再次占用导致清空无效。
  • aclrtDeviceGetHostAtomicCapabilities(uint32_t *capabilities, const aclrtAtomicOperation *operations, uint32_t count, int32_t deviceId):查询指定 Device 与 Host 之间支持的原子操作详情。capabilities为位掩码数组,每一位代表对不同数据类型原子操作的支持情况(1 支持 / 0 不支持),count必须与两个数组长度一致,否则可能导致未定义行为。
  • aclrtDeviceGetP2PAtomicCapabilities(...):查询一个 AI Server 内两个 Device(srcDeviceIddstDeviceId)之间支持的原子操作详情,参数语义同 Host 版本。
  • aclrtRegDeviceStateCallback(const char *regName, aclrtDeviceStateCallback callback, void *args):注册 Device 状态回调,不支持重复注册。当 Device 状态变化时(如调用aclrtSetDeviceaclrtResetDevice等)Runtime 触发回调。regName注册名称需保持唯一且以\0结尾;callback为 NULL 表示取消注册。回调原型如下:
typedef enum { ACL_RT_DEVICE_STATE_SET_PRE = 0, // 调用 set 接口(如 aclrtSetDevice)之前 ACL_RT_DEVICE_STATE_SET_POST, // 调用 set 接口之后 ACL_RT_DEVICE_STATE_RESET_PRE, // 调用 reset 接口(如 aclrtResetDevice)之前 ACL_RT_DEVICE_STATE_RESET_POST, // 调用 reset 接口之后 } aclrtDeviceState; typedef void (*aclrtDeviceStateCallback)(uint32_t devId, aclrtDeviceState state, void* args);

该回调机制可用于上层框架(如训练调度器)感知设备被占用/释放的时机,实现资源感知的调度。

  • aclrtSetTsDevice(aclrtTsId tsId):设置本次计算使用的 Task Schedule。aclrtTsId定义如下;若 AI 处理器中只有 AI CORE Task Schedule 而没有 VECTOR Core Task Schedule,则设置无效,默认使用 AI CORE Task Schedule:
typedef enum aclrtTsId { ACL_TS_ID_AICORE = 0, // 使用 AI CORE Task Schedule ACL_TS_ID_AIVECTOR = 1, // 使用 VECTOR Core Task Schedule ACL_TS_ID_RESERVED = 2, } aclrtTsId;
  • aclrtSetDeviceSatMode/aclrtGetDeviceSatMode:设置/查询当前 Device 的浮点计算结果输出模式(配合溢出检测使用),详见第五节。

八、实战:多卡 P2P 与设备管理的推荐编码范式

综合上述接口,给出一个兼顾正确性与健壮性的 Device 管理编码范式,可直接迁移到多卡训练、集合通信等场景:

// 1. 初始化并获取设备数量 CHECK_ERROR(aclInit(nullptr)); uint32_t deviceCount = 0; CHECK_ERROR(aclrtGetDeviceCount(&deviceCount)); if (deviceCount < 2) { /* 提示设备不足并退出 */ } // 2. 按需查询设备健康状态与能力 aclrtDeviceStatus status; CHECK_ERROR(aclrtQueryDeviceStatus(0, &status)); if (status != /* 正常状态枚举 */) { /* 处理异常设备 */ } // 3. 每个工作线程指定自己的 Device(线程内 Set/Reset 严格配对) void worker(int32_t deviceId) { CHECK_ERROR(aclrtSetDevice(deviceId)); // ... 业务逻辑 ... CHECK_ERROR(aclrtSynchronizeDevice()); CHECK_ERROR(aclrtResetDeviceForce(deviceId)); // 或 ResetDevice 配对使用 } // 4. P2P 场景:先查询、再双向开启、最后按序关闭 int32_t canAccess = 0; CHECK_ERROR(aclrtDeviceCanAccessPeer(&canAccess, 0, 1)); if (canAccess == 1) { CHECK_ERROR(aclrtDeviceEnablePeerAccess(1, 0)); // 切换 Device 后开启反向 CHECK_ERROR(aclrtSetDevice(1)); CHECK_ERROR(aclrtDeviceEnablePeerAccess(0, 0)); // ... 跨设备 memcpy ... CHECK_ERROR(aclrtDeviceDisablePeerAccess(0)); CHECK_ERROR(aclrtResetDeviceForce(1)); CHECK_ERROR(aclrtSetDevice(0)); CHECK_ERROR(aclrtDeviceDisablePeerAccess(1)); } CHECK_ERROR(aclFinalize());

关于各接口具体支持的产品型号(Ascend 950PR/950DT、Atlas A3/A2 系列、Atlas 200I/500 A2、Atlas 推理/训练系列、IPV350 等),请以 04_device_management.md 中每个接口的"产品支持情况"小节为准——不同接口的支持矩阵差异较大(如 P2P 系列不支持 Atlas 200I/500 A2 与 IPV350,aclrtDeviceL2CacheFlush仅支持 Ascend 950 系列),编码前务必核对。


九、总结

CANN Runtime 的 Device 管理接口覆盖了从"选设备、用设备、还设备"的生命周期管理,到"设备数量/状态/能力/拓扑"的全面探测,再到 P2P 数据交互、溢出检测、ID 映射与资源限制等高级能力。掌握本组接口时需重点把握三条主线:

  1. 配对与计数aclrtSetDeviceaclrtResetDevice/aclrtResetDeviceForce的引用计数语义,是多线程、多卡程序避免资源泄漏与误释放的关键;
  2. 先查询后使用:设备数量、健康状态、P2P 支持、特性支持、拓扑关系都应先查询再使用,这是设备无关编程的基础;
  3. 语义边界:P2P 单向性、溢出状态的进程级语义、ID 映射接口的命名歧义、资源限制的 Device 0 依赖与"配置值≠生效值"陷阱,都是实践中容易踩坑的地方。

如需深入实践,可结合仓库示例 1_basic_features/device 下的0_device_normal1_device_multi_thread2_device_P2P3_device_identity_mapping等工程进行对照学习;各接口的完整枚举、结构体定义可查阅 25-02_Enumerations.md 与 25-04_Structs.md。

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

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/19 23:49:48

Meteor 1.10.2 迁移指南:Flow 语法移除与自定义 Babel 配置方案

后端前端开发工具移动开发 【免费下载链接】meteor Meteor, the JavaScript App Platform 项目地址&#xff1a; https://gitcode.com/gh_mirrors/me/meteor 点击查看 免费下载 本文基于 Meteor 官方迁移文档《Migrating to Meteor 1.10.2》展开&#xff0c;聚焦 1.10.2 版本中…

作者头像 李华
网站建设 2026/9/19 23:47:17

Doris数仓实战:表模型选型、导入链路与查询调优

简介&#xff1a;面向数据仓库工程师、实时计算与OLAP技术选型相关人员的实战型PDF&#xff0c;完整记录Doris在作业帮数仓中的落地过程。内容以真实业务为背景&#xff0c;覆盖传统数仓支持模式的痛点、技术选型对比&#xff08;Presto on ES、Druid、ES-SQL、Doris&#xff0…

作者头像 李华
网站建设 2026/9/19 23:45:41

序贯决策博弈:从博弈树到逆向归纳的工程落地

简介&#xff1a;本资源是《博弈论教程&#xff08;第三版&#xff09;》第四章配套教学PPT&#xff0c;聚焦序贯决策博弈核心内容&#xff0c;面向高校经济学、管理学及应用数学专业师生&#xff0c;以及对动态博弈建模有需求的研究者与从业者。课件系统讲解博弈树构建、策略与…

作者头像 李华