运行管理资源申请与释放
本节介绍运行管理资源包括哪些、如何申请&释放这些资源,并给出示例代码。
开发应用时,应用程序中必须包含运行管理资源申请的代码逻辑,关于运行管理资源申请的接口调用流程,请先参见AscendCL接口调用流程了解整体流程,再查看本节中的资源申请&释放流程说明、示例代码。
基本原理
您需要按顺序依次申请Device、Stream等运行管理资源,确保可以使用这些资源执行运算、管理任务。所有数据处理都结束后,需要按顺序依次释放Stream、Device等运行管理资源。
其中,创建Stream的方式分为隐式创建和显式创建,其适用场景有所不同:
- 隐式创建Stream:适合简单、无复杂交互逻辑的应用,但缺点在于,在多线程编程中,每个线程都使用默认Stream,默认Stream中任务的执行顺序取决于操作系统线程调度的顺序。
- 显式创建Stream:推荐显式,适合大型、复杂交互逻辑的应用,且便于提高程序的可读性、可维护性。
关于单进程、单线程、单Stream场景如下所示:
- 关于多线程、多Stream的场景请参见Stream管理。
运行管理资源申请流程
图1 运行管理资源申请流程

申请运行管理资源时,需按顺序依次申请:Device、Stream:
- 调用aclrtSetDevice接口指定用于运算的Device(也支持在AscendCL初始化时配置默认计算设备,请参见aclInit接口处的说明),同时该接口也会隐式创建默认Context、默认Stream,但:
- 一个Device对应一个默认Context,默认Context无需显式调用接口释放,会在调用aclrtResetDevice接口释放资源时一并释放。
- 一个Device对应一个默认Stream,默认Stream无需显式调用接口释放,会在调用aclrtResetDevice接口释放资源时一并释放。
- 若使用默认Stream作为接口入参时,直接传NULL;若不使用默认Stream,可调用aclrtCreateStream接口显式创建Stream。
- (可选)调用aclrtGetRunMode接口获取软件栈的运行模式,根据运行模式来判断后续的内存申请接口调用逻辑。
如果查询结果为ACL_HOST,则数据传输时涉及申请Host上的内存。
如果查询结果为ACL_DEVICE,则数据传输时仅需申请Device上的内存。
数据传输的详细介绍请参见数据传输。
运行管理资源释放流程
图2 运行管理资源释放流程

释放运行管理资源时,需按顺序依次释放:Stream、Device。
- 若调用aclrtCreateStream接口显式创建Stream,需调用aclrtDestroyStream接口释放Stream;否则,无需调用aclrtDestroyStream接口。
- 调用aclrtResetDevice接口释放Device上的资源,同时该接口也会隐式释放默认Context、默认Stream,无需额外单独释放默认Context、默认Stream。
示例代码
您可以从基于ResNet-50网络实现图片分类(同步推理)中获取完整样例代码。
调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝编译运行,仅供参考。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
// 初始化变量
int32_t deviceId=0 ;
aclrtStream stream;
extern bool g_isDevice;
// =====运行管理资源申请=====
// 指定运算的Device
aclError ret = aclrtSetDevice(deviceId);
// 显式创建一个Stream
// 用于维护一些异步操作的执行顺序,确保按照应用程序中的代码调用顺序执行任务
ret = aclrtCreateStream(&stream);
// 获取当前AI软件栈的运行模式,根据不同的运行模式,后续的接口调用方式不同
aclrtRunMode runMode;
ret = aclrtGetRunMode(&runMode);
g_isDevice = (runMode == ACL_DEVICE);
// =====运行管理资源申请=====
// ......
// =====运行管理资源释放=====
ret = aclrtDestroyStream(stream);
ret = aclrtResetDevice(deviceId);
// =====运行管理资源释放=====
// ......
|
父主题: 运行时管理