跳到主要内容

多Stream接口调用流程

动态AIPP(多个动态AIPP输入)

基本原理

模型有多个动态AIPP输入时的推理基本流程与单个动态AIPP输入类似,请参见动态AIPP(单个动态AIPP输入)

多个动态AIPP输入与单个动态AIPP输入的不同点如下:

  • 需调用acl.mdl.get_aipp_type接口查询指定模型的指定输入是否有关联的动态AIPP输入,若有,则输出标识动态AIPP输入的index,该参数值可作为acl.mdl.set_aipp_by_input_index接口的入参之一,来设置对应输入上的动态AIPP参数值。
  • 为避免在错误的输入上设置动态AIPP参数,用户可调用acl.mdl.get_input_name_by_index接口先获取指定输入index的输入名称,根据输入名称所对应的index设置动态AIPP参数。

示例代码

调用接口后,需增加异常处理的分支,示例代码中不一一列举。以下是关键步骤的代码示例,不可以直接拷贝运行,仅供参考。

<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>25<br>26<br>27<br>28<br>29<br>30<br>31<br>32<br>33<br>34<br>35<br>36<br>37<br>38<br>39<br>40<br>41<br>42<br>43<br>44<br>45<br>46<br>47<br>48<br>49<br>50<br>51<br>52<br>53<br>54<br>55<br>56<br>57<br>58<br>59<br>60<br>61<br>62<br>python<br>import acl<br># ......<br>ACL_DATA_WITH_DYNAMIC_AIPP = 2<br>ACL_YUV420SP_U8 = 1<br># 1.模型加载,加载成功后,再设置动态AIPP参数值。<br># ......<br># 2.准备模型描述信息model_desc,准备模型的输入数据input_dataset和模型的输出数据output_dataset。<br># ......<br># 3.自定义函数,设置动态AIPP参数值。<br>def model_set_dynamic_aipp():<br> # 3.1 获取标识动态AIPP输入的index。<br> need_dynamic_aipp = []<br> input_num = acl.mdl.get_num_inputs(model_desc)<br> for index in range(input_num):<br> aipp_type, dynamic_attached_index, ret = acl.mdl.get_aipp_type(model_id, index)<br> if aipp_type == ACL_DATA_WITH_DYNAMIC_AIPP:<br> need_dynamic_aipp.append(index)<br> # 3.2 当前示例中以2个动态AIPP输入为例,用户可根据实际情况修改。<br> if len(need_dynamic_aipp) != 2:<br> return 1<br> # 创建第一个动态aipp配置参数。<br> batch_number_first = 1<br> aipp_dynamic_set_first = acl.mdl.create_aipp(batch_number_first)<br> ret = acl.mdl.set_aipp_src_image_size(aipp_dynamic_set_first, 256, 224)<br> ret = acl.mdl.set_aipp_input_format(aipp_dynamic_set_first, ACL_YUV420SP_U8)<br> ret = acl.mdl.set_aipp_csc_params(aipp_dynamic_set_first, 1, 256, 443, 0, 256, -86,<br> -178, 256, 0, 350, 0, 0, 0, 0, 128, 128)<br> ret = acl.mdl.set_aipp_rbuv_swap_switch(aipp_dynamic_set_first, 0)<br> ret = acl.mdl.set_aipp_dtc_pixel_mean(aipp_dynamic_set_first, 0, 0, 0, 0, 0)<br> ret = acl.mdl.set_aipp_dtc_pixel_min(aipp_dynamic_set_first, 0, 0, 0, 0, 0)<br> ret = acl.mdl.set_aipp_pixel_var_reci(aipp_dynamic_set_first, 1.0, 1.0, 1.0, 1.0, 0)<br> ret = acl.mdl.set_aipp_crop_params(aipp_dynamic_set_first, 1, 2, 2, 224, 224, 0)<br> # 设置模型推理时的动态aipp参数值。<br> ret = acl.mdl.set_aipp_by_input_index(model_id, input_dataset, need_dynamic_aipp[0],<br> aipp_dynamic_set_first)<br> ret = acl.mdl.destroy_aipp(aipp_dynamic_set_first)<br> # 创建第二个动态aipp配置参数。<br> batch_number_second = 2<br> aipp_dynamic_set_second = acl.mdl.create_aipp(batch_number_second)<br> ret = acl.mdl.set_aipp_src_image_size(aipp_dynamic_set_second, 224, 224)<br> # 此处可以继续调用其它AIPP参数设置接口。<br> # 设置模型推理时的动态aipp参数值。<br> ret = acl.mdl.set_aipp_by_input_index(model_id, input_dataset, need_dynamic_aipp[1],<br> aipp_dynamic_set_second)<br> ret = acl.mdl.destroy_aipp(aipp_dynamic_set_second)<br> return ret<br># 4.自定义函数,执行模型。<br>def ModelExecute(int index):<br> # 4.1 调用自定义函数,设置动态AIPP参数值。<br> ret = model_set_dynamic_aipp()<br> # 4.2 执行模型,modelId_表示加载成功的模型的ID,input_dataset和output_dataset分别表示模型的输入和输出。<br> ret = acl.mdl.execute(model_id, input_dataset, output_dataset)<br> # ......<br># 5.处理模型推理结果。<br># ......<br>

父主题: 模型动态AIPP推理

原理介绍

在pyACL中,Stream是一个任务队列,应用程序通过Stream来管理任务的并行,一个Stream内部的任务保序执行,即Stream根据发送过来的任务依次执行;不同Stream中的任务并行执行。一个默认Context下会挂一个默认Stream,如果不显式创建Stream,可使用默认Stream。默认Stream作为接口入参时,直接传0。

父主题: Stream管理

多Stream接口调用流程

开发应用时,如果涉及多Stream之间的任务等待,则应用程序中必须包含相关的代码逻辑,关于该场景的接口调用流程,请依次参见pyACL接口调用流程以及本节中的说明。

图1 同步等待流程_多Stream场景

多Stream之间任务的同步等待可以利用Event实现,调用acl.rt.stream_wait_event接口阻塞指定Stream的运行,直到指定的Event完成。需在调用acl.rt.stream_wait_event接口前,先调用acl.rt.record_event接口。调用示例请参见关于Stream间任务的同步等待

模型加载与执行的流程请参见开发基础推理应用

算子加载与执行的流程请参见单算子调用

父主题: Stream管理

单线程单Stream

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

<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>python<br>import acl<br># ......<br>ACL_MEMCPY_HOST_TO_DEVICE = 1<br># 显式创建一个Stream。<br>stream, ret = acl.rt.create_stream()<br># 调用触发任务的接口,传入stream参数。<br>ret = acl.rt.memcpy_async(dev_ptr, dev_size, host_ptr, host_size, ACL_MEMCPY_HOST_TO_DEVICE, stream)<br># 调用acl.rt.synchronize_stream接口,阻塞应用程序运行,直到指定Stream中的所有任务都完成。<br>ret = acl.rt.synchronize_stream(stream)<br># Stream使用结束后,显式销毁Stream。<br>ret = acl.rt.destroy_stream(stream)<br># ......<br>

父主题: Stream管理

单线程多Stream

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

import acl
## ......

device_id = 0
model_id_1 = 0
model_id_2 = 1

## 如果只创建了一个Context,线程默认将这个Context作为线程当前的Context。
## 如果是多个Context,则需要调用acl.rt.create_context接口设置当前线程的Context。
context, ret = acl.rt.create_context(device_id)

stream1, ret = acl.rt.create_stream()
## 调用触发任务的接口,例如异步模型推理,任务下发在stream1。
ret = acl.mdl.execute_async(model_id_1, dataset_in_1, dataset_out_1, stream1)

stream2, ret = acl.rt.create_stream()
## 调用触发任务的接口,例如异步模型推理, 任务下发在stream2。
ret = acl.mdl.execute_async(model_id_2, dataset_in_2, dataset_out_2, stream2)

## 流同步。
ret = acl.rt.synchronize_stream(stream1)
ret = acl.rt.synchronize_stream(stream2)

## 释放资源。
ret = acl.rt.destroy_stream(stream2)
ret = acl.rt.destroy_stream(stream1)
ret = acl.rt.destroy_context(context)

## ....

父主题: Stream管理

多线程多Stream

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

<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>def run_thread(stream):<br> device_id = 0<br> # 如果只创建了一个Context,线程默认将这个Context作为线程当前的Context。<br> # 如果是多个Context,则需要调用acl.rt.set_context接口设置当前线程的Context。<br> context, ret = acl.rt.create_context(device_id)<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> <br># 创建2个线程,每个线程对应一个Stream。<br>thread_id1, ret = acl.util.start_thread(run_thread, stream1)<br>thread_id2, ret = acl.util.start_thread(run_thread, stream2)<br># 显式调用join函数确保结束线程。<br>ret = acl.util.stop_thread(thread_id1)<br>ret = acl.util.stop_thread(thread_id2)<br>

父主题: Stream管理

在线提单