pyACL接口调用流程
基本概念
表1 概念介绍
| 概念 | 描述 |
|---|---|
| 同步/异步 | 本文中提及的同步、异步是站在调用者和执行者的角度,在当前场景下,若在Host调用接口后不等待Device执行完成再返回,则表示Host的调度是异步的;若在Host调用接口后需等待Device执行完成再返回,则表示Host的调度是同步的。 |
| 进程/线程 | 本文中提及的进程、线程,若无特别注明,则表示Host上的进程、线程。 |
| Host | Host指与Device相连接的X86服务器、ARM服务器,会利用Device提供的NN(Neural-Network )计算能力,完成业务。 |
| Device | Device指安装了昇腾AI处理器的硬件设备,利用PCIe接口与Host侧连接,为Host提供NN计算能力。若存在多个Device,多个Device之间的内存资源不能共享。 |
| Context | Context作为一个容器,管理了所有对象(包括Stream、Event、设备内存等)的生命周期。不同Context的Stream、不同Context的Event是完全隔离的,无法建立同步等待关系。 Context分为两种: - 默认Context:调用acl.rt.set_device接口指定用于运算的Device时,系统会自动隐式创建一个默认Context,一个Device对应一个默认Context,默认Context不能通过acl.rt.destroy_context接口来释放。 - 显式创建的Context:推荐,在进程或线程中调用acl.rt.create_context接口显式创建一个Context。 |
| Stream | Stream用于维护一些异步操作的执行顺序,确保按照应用程序中的代码调用顺序在Device上执行。 基于Stream的kernel执行和数据传输能够实现Host运算操作、Host与Device间的数据传输、Device内的运算并行。 Stream分两种: - 默认Stream:调用acl.rt.set_device接口指定用于运算的Device时,系统会自动隐式创建一个默认Stream,一个Device对应一个默认Stream,默认Stream不能通过acl.rt.destroy_stream接口来释放。 - 显式创建的Stream:推荐,在进程或线程中调用acl.rt.create_stream接口显式创建一个Stream。 |
| Event | 支持调用pyACL接口同步Stream之间的任务,包括同步Host与Device之间的任务、同一个Device上的多个任务。 例如,若stream2的任务依赖stream1的任务,想保证stream1中的任务先完成,这时可创建一个Event,并将Event插入到stream1,在执行stream2的任务前,先同步等待Event完成。 |
| AIPP | AIPP(Artificial Intelligence Pre-Processing)用于在AI Core上完成图像预处理,包括色域转换(转换图像格式)、图像归一化(减均值/乘系数)和抠图(指定抠图起始点,抠出神经网络需要大小的图片)等。 AIPP区分为静态AIPP和动态AIPP。您只能选择静态AIPP或动态AIPP其中一种方式来处理图片,不能同时配置静态AIPP和动态AIPP两种方式。 - 静态AIPP:模型转换时设置AIPP模式为静态,同时设置AIPP参数,模型生成后,AIPP参数值被保存在离线模型(*.om)中,每次模型推理过程采用固定的AIPP预处理参数(无法修改)。 如果使用静态AIPP方式,多Batch情况下共用同一份AIPP参数。 - 动态AIPP:模型转换时仅设置AIPP模式为动态,每次模型推理前,根据需求,在执行模型前设置动态AIPP参数值,然后在模型执行时可使用不同的AIPP参数。 如果使用动态AIPP方式,多Batch可使用不同的AIPP参数。 |
| 动态batch/动态分辨率 | 在某些场景下,模型每次输入的batch size或分辨率是不固定的,如检测出目标后再执行目标识别网络,由于目标个数不固定导致目标识别网络输入batch size不固定。 - 动态batch:用户执行推理时,其batch size是动态可变的。 - 动态分辨率:用户执行推理时,每张图片的分辨率H*W是动态可变的。 |
| 动态维度(ND格式) | 为了支持Transformer等网络在输入格式的维度不确定的场景,需要支持ND格式下任意维度的动态设置。 ND表示支持任意格式,当前N ≤ 4。 |
| 通道 | 在RGB色彩模式下,图像通道就是指单独的红色R、绿色G、蓝色B部分。也就是说,一幅完整的图像,是由红色、绿色、蓝色三个通道组成的,它们共同作用产生了完整的图像。同样在HSV色系中指的是色调H、饱和度S、亮度V三个通道。 |
| RC模式 | 以昇腾 AI 处理器的PCIe的工作模式进行区分,如果PCIe工作在主模式,可以扩展外设,则称为RC模式。 |
Device、Context、Stream之间的关系
图1 Device、Context、Stream之间的关系

- Device,用于指定计算设备。
- Device的生命周期源于首次调用acl.rt.set_device接口。
- 每次调用acl.rt.set_device接口,系统会进行引用计数加1;调用acl.rt.reset_device接口,系统会进行引用计数减1。
- 当引用计数减为零时,在本进程中Device上的资源不可用。
- Context,在Device下,一个Context一定属于一个唯一的Device。
-
Context分隐式创建和显式创建。
-
隐式创建的Context(即默认Context),生命周期始于调用acl.rt.set_device接口,终结于调用acl.rt.reset_device接口使引用计数为零时。
隐式Context只会被创建一次,调用acl.rt.set_device接口重复指定同一个Device,只增加隐式创建的Context的引用计数。
-
显式创建的Context,生命周期始于调用acl.rt.create_context接口,终结于调用acl.rt.destroy_context接口。
-
若在某一进程内创建多个Context(Context的数量与Stream相关,Stream数量有限制,请参见acl.rt.create_stream),当前线程在同一时刻内只能使用其中一个Context,建议通过acl.rt.set_context接口明确指定当前线程的Context,增加程序的可维护性**。**
-
进程内的Context是共享的,可以通过acl.rt.set_context进行切换。
-
- Stream,是Device上的执行流,在同一个Stream中的任务执行严格保序。
- Stream分隐式创建和显式创建。
- 每个Context都会包含一个默认Stream,属于隐式创建,隐式创建的Stream生命周期同归属的Context。
- 用户可以显式创建Stream,显式创建的Stream生命周期始于调用acl.rt.create_stream,终结于调用acl.rt.destroy_stream接口。显式创建的Stream归属的Context被销毁或生命周期结束后,会影响该Stream的使用,虽然此时Stream没有被销毁,但不可再用。
- Task/Kernel,是Device上真正的任务执行体。
线程、Context、Stream之间的关系
-
一个用户线程一定会绑定一个Context,所有Device的资源使用或调度,都必须基于Context。
-
一个线程中当前会有一个唯一的Context在用,Context中已经关联了本线程要使用的Device。
-
可以通过acl.rt.set_context进行Device的快速切换。示例代码如下,仅供参考,不可以直接拷贝运行:
…ctx1, ret = acl.rt.create_context(0) #使用acl.rt.create_context接口通过传入Device Id创建Context。stream, ret = acl.rt.create_stream()ret = acl.op.execute_v2(op_type, input_desc, inputs, output_desc, outputs, attr, stream)ctx2, ret = acl.rt.create_context(1)# 在当前线程中,创建ctx2后,当前线程对应的Context切换为ctx2,对应在Device 1进行后续的计算任务,本例中将在Device 1上进行op2的执行调用。stream2, ret = acl.rt.create_stream()ret = acl.op.execute_v2(op_type2, input_desc, inputs, output_desc, outputs, attr, stream2)ret = acl.rt.set_context(ctx1);# 在当前线程中,通过Context切换,使后续计算任务在对应的Device 0上进行。ret = acl.op.execute_v2(op3,...,s1)… -
一个线程中可以创建多个Stream,不同的Stream上计算任务是可以并行执行,多线程场景下,也可以每个线程创建一个Stream,线程之间的Stream在Device上相互独立,每个Stream内部的任务是按照Stream下发的顺序执行。
-
多线程的调度依赖于运行应用的操作系统调度,多Stream调度Device侧,由Device上调度组件进行调度。
一个进程内多个线程间的Context迁移
-
一个进程中可以创建多个Context,但一个线程同一时刻只能使用一个Context。
-
线程中创建的多个Context,线程缺省使用最后一次创建的Context。
-
进程内创建的多个Context,可以通过acl.rt.set_context设置当前需要使用的Context。
图2 接口调用流程

默认Context和默认Stream的使用场景
-
Device上执行操作下发前,必须有Context和Stream,这个Context、Stream可以显式创建,也可以隐式创建。隐式创建的Context、Stream就是默认Context、默认Stream。
默认Stream作为接口入参时,直接传0。
-
默认Context不允许用户执行acl.rt.get_context或acl.rt.set_context操作,也不允许执行acl.rt.destroy_context操作。
-
默认Context、默认Stream一般适用于简单应用,用户仅仅需要一个Device的计算场景下。多线程应用程序建议全部使用显式创建的Context和Stream。
示例代码如下,仅供参考,不可以直接拷贝运行:
## …
ret = acl.init(config_path)
ret = acl.rt.set_device(device_id)
## 已经创建了一个default ctx,在default ctx中创建了一个default stream,并且在当前线程可用。
## …
ret = acl.op.execute_v2(op1, input_desc, inputs, output_desc, outputs, attr, 0) # 最后一个0表示在default stream上执行算子op1。
ret = acl.op.execute_v2(op2, input_desc, inputs, output_desc, outputs, attr, 0) # 最后一个0表示在default stream上执行算子op2。
ret = acl.rt.synchronize_stream(0)
## 等待计算任务全部完成(op1、op2执行结束),用户根据需要获取计算任务的输出结果。
## …
ret = acl.rt.reset_device(device_id) # 释放计算设备0,对应的default ctx及default stream生命周期也终止。
多线程、多stream的性能说明
- 线程调度依赖运行的操作系统,Stream上下发了任务后,Stream的调度由Device的调度单元调度,但如果一个进程内的多Stream上的任务在Device存在资源争抢的时候,性能可能会比单Stream低。
- 当前昇腾AI处理器有不同的执行部件,如AI Core、AI CPU、Vector Core等,对应使用不同执行部件的任务,建议多Stream的创建按照算子执行引擎划分。
- 单线程多Stream与多线程多Stream(一个进程中可以包含多个线程,每个线程中一个Stream)性能上哪个更优,具体取决于应用本身的逻辑实现,一般来说前者性能略好,原因是相对后者,应用层少了线程调度开销。
父主题: 概述
pyACL接口调用流程
调用pyACL接口,可开发包含模型推理、媒体数据处理、单算子调用等功能的应用,这些功能可以独立存在,也可以组合存在。下图给出了使用pyACL接口开发AI应用的整体接口调用流程。
图1 接口调用流程图

上图根据应用开发中的典型功能抽象出主要的接口调用流程,具体场景参考如下。
- 如果模型对输入图片的宽高要求与用户提供的源图不一致,则需要媒体数据处理,将源图裁剪成符合模型的要求。
- 如果需要实现模型推理的功能,则需要先加载模型,模型推理结束后,则需要卸载模型。
- 如果模型推理后,需要从推理结果中查找最大置信度的类别标识对图片分类,则需要数据后处理。
接口调用流程各步骤操作参见如下。
-
pyACL初始化。
调用acl.init接口实现初始化pyACL。
-
运行管理资源申请。
依次申请运行管理资源:Device、Context、Stream。
具体流程,请参见运行管理资源申请流程。
-
模型推理/单算子调用/媒体数据处理。
-
模型推理。
-
生成模型om文件:模型推理场景下,必须要有适配昇腾AI处理器的离线模型,需提前构建模型,请参见模型构建。
-
模型加载:模型推理前,需要先将对应的模型加载到系统中。
接口调用流程,请参见模型加载。
-
(可选)媒体数据处理:可实现JPEG图片解码、视频解码、抠图/图片缩放/格式转换、JPEG图片编码等功能。
接口调用流程,请参见媒体数据处理。
-
模型执行:使用模型实现图片分类、目标识别等功能。
接口调用流程,请参见模型执行。
-
(可选)数据后处理:处理模型推理的结果,此处根据用户的实际需求来处理推理结果,例如用户可以将获取到的推理结果写入文件、从推理结果中找到每张图片最大置信度的类别标识等。
-
模型卸载:调用acl.mdl.unload接口卸载模型。
-
-
算子调用。
如果AI应用中不仅仅包括模型推理,还有数学运算(例如BLAS基础线性代数运算)、数据类型转换等功能,也想使用昇腾的算力,直接通过pyACL接口加载并执行单个算子,省去模型构建、训练的过程,相对轻量级,又可以使用昇腾的算力。另外,自定义的算子,也可以通过单算子调用的方式来验证算子的功能。接口调用流程,请参见接口调用流程。
-
-
运行管理资源释放。
所有数据处理都结束后,需要依次释放运行管理资源:Stream、Context、Device。
具体流程,请参见运行管理资源释放流程。
-
pyACL去初始化。
调用acl.finalize接口实现pyACL去初始化。
:::note 说明
- 在应用开发过程中,各环节都涉及内存的申请与释放、数据传输(通过内存复制实现)、数据类型的创建与销毁,因此未在图中一一标识,关于内存申请与释放、内存复制的接口请参见内存管理。数据类型的创建与销毁的接口请参见数据类型及其操作接口。
- 关于日志的处理机制和日志级别设置等功能,请参见《日志参考》。
- pyACL部分功能可能会涉及到ATC工具来进行模型转换,请参见《ATC工具使用指南》。
- 生成pyACL中的“acl.so”依赖的Python版本范围为3.7.5~3.9.2。 :::
父主题: 概述
应用开发环境准备
部署开发环境和运行环境,请参见对应Atlas产品的描述。
-
部署开发环境后,才能获取调用接口所需的头文件、编译运行接口所需的库文件。
对于昇腾设备,已安装驱动、固件场景下,该环境可直接作为运行环境,执行编译生成的应用可执行文件。
-
部署运行环境后,才能在运行环境上执行编译生成的应用可执行文件。
:::note 说明
-
pyACL库文件路径:CANN软件安装后文件存储路径/lib64
需要根据运行环境的安装包,确定引用的组件目录,否则会导致运行报错。安装方案请参见。
安装CANN软件后,需要以CANN运行用户登录环境,执行source ${install_path}/set_env.sh命令设置环境变量,其中${install_path}为CANN软件的安装目录。
-
本文中的操作步骤需以运行用户登录开发环境或运行环境后再执行,请务必获取各组件的运行用户,以便后续操作时使用。 :::
-
-
(可选)通过环境变量“ASCEND_CACHE_PATH”、“ASCEND_WORK_PATH”设置pyACL应用运行过程中产生的文件的落盘路径,涉及ATC模型转换、AOE模型智能调优、性能数据采集、日志采集等功能,落盘文件包括知识库文件、调优结果文件、性能数据文件、日志文件等。
配置示例如下,详细配置说明请参见《环境变量参考》:
export ASCEND_CACHE_PATH=/repo/task001/cacheexport ASCEND_WORK_PATH=/repo/task001/172.16.1.12_01_03
pyACL的依赖
pyACL没有安装依赖,但是有运行依赖。详情请参见《CANN 软件安装指南》完成对开发环境和运行环境的部署。
安装后的环境变量设置
在安装完CANN软件包之后,请务必自行配置以下环境变量,否则,将无法正常使用“import acl”。
-
若环境中安装了cann-toolkit软件包:
# 以root用户安装toolkit包。. /usr/local/Ascend/ascend-toolkit/set_env.sh# 以非root用户安装toolkit包。. ${HOME}/Ascend/ascend-toolkit/set_env.sh -
若环境中安装了cann-nnrt软件包:
# 以root用户安装nnrt包。. /usr/local/Ascend/nnrt/set_env.sh# 以非root用户安装nnrt包。. ${HOME}/Ascend/nnrt/set_env.sh
设置完环境变量后,在Python脚本中加入“import acl”,就可以使用pyACL中的函数了。
其它
- 关于日志的处理机制和日志级别设置等功能,请参见《日志参考》。
- pyACL部分功能可能会涉及到ATC工具来进行模型转换,请参见《ATC工具使用指南》。
- 生成pyACL中的“acl.so”依赖的Python版本范围为3.7.5~3.9.2。
父主题: 概述
开发流程
图1 开发流程

-
准备环境,包括开发环境和运行环境。
-
创建代码目录。
在开发应用前,您需要先创建目录,存放代码文件、编译脚本、测试图片数据、模型文件等。如下仅是示例,可参考:
├App名称├── caffe_model # 该目录下存放模型转换相关的配置文件、模型文件。│ ├── xxx.cfg│ ├── xxx.prototxt├── data│ ├── xxx.jpg # 测试数据。│├── model│ ├── xxx.om # 转换后的模型文件。│├── xxx.py # python脚本。├── xxx.py -
开发应用。
-
pyACL初始化,请参见pyACL初始化与去初始化。
使用pyACL接口开发应用时,必须先调用acl.init接口进行pyACL初始化,否则可能会导致后续系统内部资源初始化出错,进而导致其它业务异常。
-
运行管理资源申请,请参见运行管理资源申请与释放。
-
数据传输,请参见数据传输。
-
执行模型推理。请参见模型推理基本场景。
模型推理结束后,需及时释放相关资源。
若需要处理模型推理的结果,还需要进行数据后处理,例如对于图片分类应用,通过数据后处理从推理结果中查找最大置信度的类别标识。
-
所有数据处理结束后,需及时释放运行管理资源,请参见运行管理资源申请与释放。
-
执行pyACL去初始化,请参见pyACL初始化与去初始化。
-
-
运行应用,包括模型转换、运行应用,请参见应用调试。
父主题: 开发基础推理应用
模型构建
对于开源框架的网络模型(如Caffe、TensorFlow等),不能直接在昇腾AI处理器上运行推理,需要先使用ATC(Ascend Tensor Compiler)工具将开源框架的网络模型转换为适配昇腾AI处理器的离线模型(*.om文件),模型转换的方法请参见《[转换模型](https://www.hiascend.com/document/detail/zh/Atlas200IDKA2DeveloperKit/23.0.RC2/Application Development Guide/tmuacop/tmuacop_0001.html)》。
父主题: 开发基础推理应用
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 运行管理资源申请流程

关键接口的说明如下:
-
申请运行管理资源时,需按顺序依次申请:Device、Context、Stream。
- 调用acl.rt.set_device接口显式指定用于运算的Device。
-
调用acl.rt.create_context接口显式创建Context,调用acl.rt.create_stream接口显式创建Stream。
-
如果不显式创建Context和Stream,您可以使用acl.rt.set_device接口隐式创建的默认Context和默认Stream,但默认Context和默认Stream存在如下限制:
- 一个Device对应一个默认Context,默认Context不能通过acl.rt.destroy_context接口来释放。
- 一个Device对应一个默认Stream,默认Stream不能通过acl.rt.destroy_stream接口来释放。默认Stream作为接口入参时,直接传0。
- 默认Context、默认Stream,是在调用acl.rt.reset_device接口后自动释放。
-
隐式****指定用于运算的Device。
调用acl.rt.create_context接口显式创建Context,调用acl.rt.create_stream接口显式创建Stream。系统在显式创建Context时,系统内部会调用acl.rt.set_device接口指定运行的Device,Device ID通过acl.rt.create_context接口传入。
-
- 调用acl.rt.set_device接口显式指定用于运算的Device。
-
(可选)调用acl.rt.get_run_mode接口获取软件栈的运行模式,根据运行模式来判断后续的内存申请接口调用逻辑。
如果查询结果为ACL_HOST,则数据传输时涉及申请Host上的内存。
如果查询结果为ACL_DEVICE,则数据传输时仅需申请Device上的内存。
数据传输的详细介绍请参见数据传输。
运行管理资源释放流程
图2 运行管理资源释放流程

关键接口的说明如下:
- 释放运行管理资源时,需按顺序依次释放:Stream、Context、Device。
- 显式创建Context和Stream时,需调用acl.rt.destroy_stream接口释放Stream,再调用acl.rt.destroy_context接口释放Context。若显式调用acl.rt.set_device接口指定运算的Device时,还需调用acl.rt.reset_device接口释放Device上的资源。
- 不显式创建Context和Stream时,仅需调用acl.rt.reset_device接口释放Device上的资源。
示例代码
您可以从样例介绍中获取完整样例代码。
调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝运行,仅供参考。
<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> |
|---|
父主题: 开发基础推理应用
在线提单