Skip to main content

pyACL初始化与去初始化

pyACL初始化与去初始化

关于pyACL初始化与去初始化的接口调用流程,请参见pyACL接口调用流程

基本原理

您必须调用acl.init接口初始化pyACL,配置文件内容为JSON格式。

如果当前的默认配置已满足需求,无需修改,acl.init接口中可不传入参数,或者可将配置文件配置为空JSON串(即配置文件中只有{})。在acl.init接口中不传入参数,示例如下:

ret = acl.init()

有初始化就有去初始化,在确定完成了pyACL的所有调用之后,或者进程退出之前,需调用acl.finalize接口实现pyACL去初始化

示例代码

您可以从样例介绍中获取完整样例代码。

调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝运行,仅供参考。

<br> 1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br>10<br>11<br>python<br>import acl<br># ......<br># 初始化基本配置。<br># 此处的“..”表示相对路径,相对可执行文件所在的目录。<br>acl_config_path = "../src/acl.json"<br>ret = acl.init(acl_config_path)<br># ......<br># 去初始化。<br>ret = acl.finalize()<br># ......<br>

父主题: 开发基础推理应用

运行管理资源申请与释放

开发应用时,应用程序中必须包含运行管理资源申请的代码逻辑,关于运行管理资源申请的接口调用流程,请先参见pyACL接口调用流程了解整体流程,再查看本节中的资源申请、释放流程说明。

基本原理

您需要按顺序依次申请如下运行管理资源:Device、Context、Stream,确保可以使用这些资源执行运算、管理任务。所有数据处理都结束后,需要按顺序依次释放运行管理资源:Stream、Context、Device。

您需要按照Device、Context、Stream的顺序依次申请。其中,创建Context、Stream的方式分为隐式创建和显式创建,其适用场景有所不同:

  • 隐式创建Context和Stream:适合简单、无复杂交互逻辑的应用,但缺点在于,在多线程编程中,每个线程都使用默认Context或默认Stream,默认Stream中任务的执行顺序取决于操作系统线程调度的顺序。

  • 显式创建Context和Stream:推荐显式,适合大型、复杂交互逻辑的应用,且便于提高程序的可读性、可维护性。

  • 关于单进程、单线程、单Stream场景如下所示:

    • 单进程:一个应用程序对应一个进程。

    • 单线程:不创建多个线程时,默认只有一个线程。

    • 单Stream:整个开发的过程中使用同一个Stream。

      对于同一个Stream中的异步任务,pyACL会按照应用程序中任务的顺序执行任务,确保异步任务执行的顺序。

  • 关于多线程、多Stream的场景请参见Stream管理

运行管理资源申请流程

图1 运行管理资源申请流程

关键接口的说明如下:

  1. 申请运行管理资源时,需按顺序依次申请:Device、Context、Stream。

  2. (可选)调用acl.rt.get_run_mode接口获取软件栈的运行模式,根据运行模式来判断后续的内存申请接口调用逻辑。

    如果查询结果为ACL_HOST,则数据传输时涉及申请Host上的内存。

    如果查询结果为ACL_DEVICE,则数据传输时仅需申请Device上的内存。

    数据传输的详细介绍请参见数据传输

运行管理资源释放流程

图2 运行管理资源释放流程

关键接口的说明如下:

示例代码

您可以从样例介绍中获取完整样例代码。

调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝运行,仅供参考。

<br> 1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br>10<br>11<br>12<br>13<br>14<br>15<br>16<br>17<br>18<br>19<br>20<br>21<br>22<br>23<br>24<br>python<br>import acl<br>#......<br># ======运行管理资源申请======<br># 1.指定运算的Device。<br>ret = acl.rt.set_device(device_id)<br># 2.显式创建一个Context,用于管理Stream对象。<br>context, ret = acl.rt.create_context(device_id)<br># 3.显式创建一个Stream。<br>#用于维护一些异步操作的执行顺序,确保按照应用程序中的代码调用顺序执行任务。<br>stream, ret = acl.rt.create_stream()<br># ======运行管理资源申请======<br>#......<br># ======运行管理资源释放======<br>ret = acl.rt.destroy_stream(stream)<br>ret = acl.rt.destroy_context(context)<br>ret = acl.rt.reset_device(device_id)<br># ======运行管理资源释放======<br>#......<br>

父主题: 开发基础推理应用

接口调用流程

数据传输的关键接口调用流程如下:

  1. 申请内存

  2. 将数据读入内存

    由用户自行管理数据读入内存的实现逻辑。

  3. 通过内存复制实现数据传输

    数据传输可以通过内存复制的方式实现,分为同步内存复制异步内存复制

    :::note 说明 Ascend RC场景下,不涉及Host上的内存申请、Host内的数据传输、Host与Device之间的数据传输。

    如果当前版本支持多种运行形态,在这种场景下,若想实现相同的应用程序可支持在多种形态下运行,申请内存的方式不同,会影响数据传输时调用的接口:

    • 若应用程序中区分申请Host内存或Device内存的接口,例如使用acl.rt.malloc_host接口申请Host内存、使用acl.rt.malloc接口申请Device内存时:

      需先调用acl.rt.get_run_mode接口获取软件栈的运行模式。

      • 当查询结果为ACL_HOST = 1,则数据传输时涉及申请Host上的内存。
      • 当查询结果为ACL_DEVICE = 0 ,则数据传输时不涉及申请Host上的内存,仅需申请Device上的内存。

      该种方式多一些代码逻辑的判断,不需要由用户处理Device上的内存对齐。在Device上运行应用的场景,该种方式少一些内存复制的步骤,性能较好。

    • 若应用程序中不区分申请Host内存或Device内存的接口,统一使用acl.rt.malloc_host接口(该接口支持申请Host或Device内存),pyACL内部会根据软件栈的运行模式自行判断运行时申请的是Host内存还是Device内存:

      无需调用acl.rt.get_run_mode接口获取软件栈的运行模式。该种方式代码逻辑相比前一种简单,但需由用户处理Device上的内存对齐。 :::

父主题: 数据传输

Device内的数据传输

同步内存复制

调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝运行,仅供参考,示例代码如下:

import acl
## ......

## 1.申请内存。
size = 1 * 1024 * 1024
dev_ptr_a, ret = acl.rt.malloc(size, ACL_MEM_MALLOC_NORMAL_ONLY)
dev_ptr_b, ret = acl.rt.malloc(size, ACL_MEM_MALLOC_NORMAL_ONLY)

## 2.申请内存后,可向内存中读入数据,该自定义函数read_file由用户实现。
read_file(fileName, dev_ptr_a, size)

## 3.同步内存复制。
## 同步内存复制,dev_ptr_a表示Device上源内存地址的指针地址,dev_ptr_b表示Device上目的内存地址的指针地址,size表示内存大小。
## ACL_MEMCPY_DEVICE_TO_DEVICE = 3。
ret = acl.rt.memcpy(dev_ptr_b, size, dev_ptr_a, size, ACL_MEMCPY_DEVICE_TO_DEVICE)

## 4.使用完内存中的数据后,需及时释放资源。
ret = acl.rt.free(dev_ptr_a)
ret = acl.rt.free(dev_ptr_b)

## ......

异步内存复制

调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝运行,仅供参考,示例代码如下:

import acl
## ......

## 1.申请内存。
size = 1 * 1024 * 1024
dev_ptr_a, ret = acl.rt.malloc(size, ACL_MEM_MALLOC_NORMAL_ONLY)
dev_ptr_b, ret = acl.rt.malloc(size, ACL_MEM_MALLOC_NORMAL_ONLY)

## 2.申请内存后,可向内存中读入数据,该自定义函数read_file由用户实现。
read_file(fileName, dev_ptr_a, size)

## 3.异步内存复制。
## 异步内存复制,dev_ptr_a表示Device上源内存地址的指针地址,dev_ptr_b表示Device上目的内存地址的指针地址,size表示内存大小。
## ACL_MEMCPY_DEVICE_TO_DEVICE = 3。
stream = acl.rt_create_stream()
ret = acl.rt.memcpy_async(dev_ptr_b, size, dev_ptr_a, size, ACL_MEMCPY_DEVICE_TO_DEVICE, stream)
ret = acl.rt.synchronize_stream(stream)

## 4.使用完内存中的数据后,需及时释放资源。
ret = acl.rt.destroy_stream(stream)
ret = acl.rt.free(dev_ptr_a)
ret = acl.rt.free(dev_ptr_b)

## ......

父主题: 数据传输

模型加载

模型构建中的说明构建出模型后,需进行模型加载,为模型执行做准备。

接口调用流程

开发应用时,如果涉及整网模型推理,则应用程序中必须包含模型加载的代码逻辑,关于模型加载的接口调用流程,请先参见pyACL接口调用流程了解整体流程,再查看本节中的流程说明。

本节描述的是整网模型加载的接口调用流程,对于算子模型加载与执行的详细说明请参见单算子调用

pyACL提供两套模型加载的接口,用户可根据具体使用场景选择对应的模型加载接口:

  • 图1所示,根据不同的加载方式(从文件加载、从内存加载等)选择不同的接口,操作相对简单,但需要记住各种方式的加载接口
  • 图2所示,针对不同的加载方式(从文件加载、从内存加载等),只需****设置接口中的配置参数,适用各种加载方式,但****涉及多个接口配合使用,分别用于创建配置对象、设置对象中的属性值、加载模型。

图1 模型加载流程(通过不同接口区分加载方式)

图2 模型加载流程(通过接口中的配置参数区分加载方式)

关键接口的说明如下:

  • 在模型加载前,需要先构建出适配昇腾AI处理器的离线模型(*.om文件),构建方式请参见模型构建

  • 由****用户管理内存时,为确保内存不浪费,在申请工作内存、权值内存前,需要调用acl.mdl.query_size接口查询模型运行时所需工作内存、权值内存的大小

    如果模型输入数据的Shape不确定,则不能调用acl.mdl.query_size接口查询内存大小,在加载模型时,就无法由用户管理内存,因此需选择由系统管理内存的模型加载接口(例如,acl.mdl.load_from_fileacl.mdl.load_from_mem)。

  • 支持以下方式加载模型,模型加载成功后,返回标识模型的模型ID:

    • 通过不同接口区分加载方式,从使用的接口上区分从文件加载,还是从内存加载,以及内存是由系统内部管理,还是由用户管理。
      • acl.mdl.load_from_file从文件加载离线模型数据,由系统内部管理内存。
      • acl.mdl.load_from_mem从内存加载离线模型数据,由系统内部管理内存。
      • acl.mdl.load_from_file_with_mem从文件加载离线模型数据,由用户自行管理模型运行的内存(包括工作内存和权值内存,工作内存用于模型执行过程中的临时数据,权值内存用于存放权值数据)。
      • acl.mdl.load_from_mem_with_mem从内存加载离线模型数据,由用户自行管理模型运行的内存(包括工作内存和权值内存)。
    • 通过接口中的配置参数区分加载方式,使用acl.mdl.set_config_opt接口、acl.mdl.load_with_config接口时,是通过配置对象中的属性来区分,在加载模型时是从文件加载还是从内存加载,以及内存是由系统内部管理还是由用户管理。

示例代码

模型加载成功,会返回标识模型的ID,在模型执行时需要使用该ID。

您可以从样例介绍中获取完整样例代码。

调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝运行,仅供参考。

## 初始化变量。
model_path = "./model/resnet50.om"
## ......

## 加载离线模型文件(适配昇腾AI处理器的离线模型),由系统管理模型运行的内存(包括权值内存、工作内存)。
## 模型加载成功,返回标识模型的ID。
model_id, ret = acl.mdl.load_from_file(model_path)

## ......

父主题: 模型推理基本场景

在线提单