Skip to main content

关于Stream间任务的同步等待

关于Event的同步等待

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

<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>python<br>import acl<br># ......<br># 创建一个Event。<br>event, ret = acl.rt.create_event()<br># 创建一个Stream。<br>stream, ret = acl.rt.create_stream()<br># stream末尾添加了一个event。<br>ret = acl.rt.record_event(event, stream)<br># 阻塞应用程序运行,等待event发生,也就是stream执行完成。<br># stream完成后产生event,唤醒执行应用程序的控制流,开始执行程序。<br>ret = acl.rt.synchronize_event(event)<br># 显式销毁资源。<br>ret = acl.rt.destroy_stream(stream)<br>ret = acl.rt.destroy_event(event)<br># ......<br>

父主题: 同步等待

关于Stream内任务的同步等待

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

import acl
## ......

## 显式创建一个Stream。
stream, ret = acl.rt.create_stream()

## 调用触发任务的接口,传入stream参数。
ret = acl.rt.memcpy_async(dev_ptr, dev_size, host_ptr, host_size, ACL_MEMCPY_HOST_TO_DEVICE, stream)
## 调用acl.rt.synchronize_stream接口,阻塞应用程序运行,直到指定Stream中的所有任务都完成。
ret = acl.rt.synchronize_stream(stream)

## Stream使用结束后,显式销毁Stream。
ret = acl.rt.destroy_stream(stream)
## ......

父主题: 同步等待

关于Stream间任务的同步等待

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

import acl
## ......
## 创建一个Event。
event, ret = acl.rt.create_event()

## 创建两个Stream。
s1, ret = acl.rt.create_stream()
s2, ret = acl.rt.create_stream()

## 在s1末尾添加了一个event。
ret = acl.rt.record_event(event, s1)

## 阻塞s2运行,直到指定Event发生,也就是s1执行完成。
## s1完成后,唤醒s2,继续执行s2的任务。
ret = acl.rt.stream_wait_event(s2, event)

## 显式销毁资源。
ret = acl.rt.destroy_stream(s2)
ret = acl.rt.destroy_stream(s1)
ret = acl.rt.destroy_event(event)
## ......

父主题: 同步等待

关于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>python<br>import acl<br># ......<br>device_id = 0<br># 指定Device。<br>ret = acl.rt.set_device(device_id)<br># 创建context。<br>context, ret = acl.rt.create_context(device_id)<br># 创建stream。<br>stream, ret = acl.rt.create_stream()<br># 阻塞应用程序运行,直到正在运算中的Device完成运算。<br>ret = acl.rt.synchronize_device()<br># 资源销毁。<br>ret = acl.rt.synchronize_stream(stream)<br>ret = acl.rt.destroy_context(context)<br>ret = acl.rt.reset_device(device_id)<br>

父主题: 同步等待

AI Core异常信息获取

基本原理

使用场景****举例:执行整网模型推理时(不支持动态Shape场景),如果产生AI Core报错,可以调用本接口获取报错算子的描述信息,再做进一步错误排查。

推荐的接口调用顺序如下:

  1. 定义并实现异常回调函数fn(aclrtExceptionInfoCallback类型),回调函数原型请参见acl.rt.set_exception_info_callback

    实现回调函数的关键步骤如下:

    1. 在异常回调函数fn内调用acl.rt.get_device_id_from_exception_infoacl.rt.get_stream_id_from_exception_infoacl.rt.get_task_id_from_exception_info接口分别获取Device ID、Stream ID、Task ID。

    2. 在异常回调函数fn内调用acl.mdl.create_and_get_op_desc接口获取算子的描述信息。

    3. 在异常回调函数fn内调用acl.get_tensor_desc_by_index接口获取指定算子输入/输出的Tensor描述。

    4. 在异常回调函数fn内如下接口获取Tensor描述中的数据,进行进一步分析。

      例如,调用acl.get_tensor_desc_address接口获取Tensor数据的内存地址(用户可从该内存地址中获取Tensor数据)、调用acl.get_tensor_desc_type接口获取Tensor描述中的数据类型、调用acl.get_tensor_desc_format接口获取Tensor描述中的Format、调用acl.get_tensor_desc_num_dims接口获取Tensor描述中的Shape维度个数、调用acl.get_tensor_desc_dim_v2接口获取Shape中指定维度的大小。

  2. 调用acl.rt.set_exception_info_callback接口设置异常回调函数。

  3. 执行模型推理。

    如果存在AI Core报错,则触发回调函数fn,获取算子的信息,进行进一步分析。

示例代码

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

示例中,运行管理资源申请与释放请参见运行管理资源申请与释放,模型加载的接口调用流程请参见接口调用流程,模型推理的接口调用流程、准备模型推理的输入/输出数据的接口调用流程请参见准备模型执行的输入/输出数据结构

<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>python<br>import acl<br>import numpy as np<br># ......<br># 1.申请运行管理资源,包括设置用于计算的Device、创建Context、创建Stream。<br># ......<br># 2.模型加载,加载成功后,返回标识模型的model_id。<br># ......<br># 3.创建aclmdlDataset类型的数据,用于描述模型的输入数据input、输出数据output。<br># ......<br># 4.实现异常回调函数。<br>def exception_callback(info):<br> stream_id = acl.rt.get_stream_id_from_exception_info(info)<br> thread_id = acl.rt.get_thread_id_from_exception_info(info)<br> device_id = acl.rt.get_device_id_from_exception_info(info)<br> task_id = acl.rt.get_task_id_from_exception_info(info)<br> # 用户可以将获取的算子信息写入到文件,或者另起线程侦听异常回调,当发生异常回调时触发线程处理函数,在线程处理函数中将算子信息打屏。<br> op_name, input_desc, num_inputs, output_desc, num_outputs, ret = \<br> acl.mdl.create_and_get_op_desc(device_id, stream_id, task_id, 256)<br> # 可以调用acl tensor的相关接口,获取算子的相关信息,用户可以根据自己需要调用。<br> for i in range(num_inputs):<br> desc = acl.get_tensor_desc_by_index(input_desc, i)<br> address = acl.get_tensor_desc_address(desc)<br> num_dims = acl.get_tensor_desc_num_dims(desc)<br> dim_0, ret = acl.get_tensor_desc_dim_v2(desc, 0)<br> for i in range(num_outputs):<br> desc = acl.get_tensor_desc_by_index(output_desc, i)<br> address = acl.get_tensor_desc_address(desc)<br> num_dims = acl.get_tensor_desc_num_dims(desc)<br> dim_0, ret = acl.get_tensor_desc_dim_v2(desc, 0)<br> acl.destroy_tensor_desc(input_desc)<br> acl.destroy_tensor_desc(output_desc)<br># 5.设置异常回调。<br>ret = acl.rt.set_exception_info_callback(exception_callback)<br># 6.执行模型。<br>ret = acl.mdl.execute(model_id, input, output)<br># 7.处理模型推理结果。<br># ......<br># 8.释放描述模型输入/输出信息、内存等资源,卸载模型。<br># ......<br># 9.释放运行管理资源。<br># ......<br>

父主题: 扩展更多特性

Profiling性能数据采集

基本原理

该章节下的接口用于Profiling采集性能数据,实现方式支持以下三种:

Profiling pyACL API(通过Profiling pyACL API采集并落盘性能数据):实现将采集到的Profiling数据写入文件,再使用Profiling工具解析该文件(请参见《性能分析工具使用指南》下的“数据解析与导出”),并展示性能分析数据。

包括以下两种接口调用方式:

  • acl.prof.init接口、acl.prof.start接口、acl.prof.stop接口、acl.prof.finalize接口配合使用,实现该方式的性能数据采集。该方式可获取pyACL的接口性能数据、AI Core上算子的执行时间、AI Core性能指标数据等。目前这些接口为进程级控制,表示在进程内任意线程调用该接口,其它线程都会生效。

    一个进程内,可以根据需求多次调用这些接口,基于不同的Profiling采集配置,采集数据。

  • 调用acl.init接口,在pyACL初始化阶段,通过*.json 文件传入要采集的Profiling数据。该方式可获取pyACL的接口性能数据、AI Core上算子的执行时间、AI Core性能指标数据等。

    一个进程内,只能调用一次acl.init接口,如果要修改Profiling采集配置,需修改*.json文件中的配置。详细使用说明请参见acl.init接口处的说明,不在本章节描述。

Profiling pyACL API for Extension(Profiling pyACL API扩展接口):当用户需要定位应用程序或上层框架程序的性能瓶颈时,可在Profiling采集进程内(acl.prof.start接口、acl.prof.stop接口之间)调用Profiling pyACL API扩展接口(统称为msproftx功能),开启记录应用程序执行期间特定事件发生的时间跨度,并将数据写入Profiling数据文件,再使用Profiling工具解析该文件,并导出展示性能分析数据。

Profiling工具解析导出操作请参见《性能分析工具使用指南》下的“Profiling数据解析”和“Profiling数据导出”。

一个进程内,可以根据需求多次调用这些接口。

接口调用方式:在acl.prof.startacl.prof.stop接口之间调用acl.prof.create_stampacl.prof.pushacl.prof.popacl.prof.range_startacl.prof.range_stopacl.prof.destroy_stamp接口。该方式可获取应用程序执行期间特定时间发生的事件并记录事件发生的时间跨度。

一个进程内,可以根据需求多次调用这些接口。

Profiling pyACL API for Subscription(订阅算子信息的Profiling pyACL API):实现将采集到的Profiling数据解析后写入管道,由用户读入内存,再由用户调用pyACL的接口获取性能数据。

接口调用方式:acl.prof.model_subscribe接口、acl.prof.get*接口、acl.prof.model_unsubscribe接口配合使用,实现该方式的性能数据采集,当前支持获取网络模型中算子的性能数据,包括算子名称、算子类型名称、算子执行时间等。

Profiling pyACL API示例代码

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

示例中,运行管理资源申请与释放请参见运行管理资源申请流程运行管理资源释放流程,模型加载的接口调用流程请参见接口调用流程,模型推理的接口调用流程、准备模型推理的输入/输出数据的接口调用流程请参见准备模型执行的输入/输出数据结构

<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>python<br>import acl<br>import numpy as np<br># ......<br># 1.申请运行管理资源,包括设置用于计算的Device、创建Context、创建Stream。<br># ......<br># 2.模型加载,加载成功后,返回标识模型的model_id。<br># ......<br># 3.创建aclmdlDataset类型的数据,用于描述模型的输入数据input、输出数据output。<br># ......<br># 4.profiling初始化。<br># 设置数据落盘路径。<br>PROF_INIT_PATH='...'<br>ret = acl.prof.init(PROF_INIT_PATH)<br># 5.进行profiling配置。<br>device_list = [0]<br>ACL_PROF_ACL_API = 0x0001<br>ACL_PROF_TASK_TIME = 0x0002<br>ACL_PROF_AICORE_METRICS = 0x0004<br>ACL_PROF_AICPU_TRACE = 0x0008<br>ACL_PROF_SYS_HARDWARE_MEM_FREQ = 3<br># 创建配置类型指针地址。<br>prof_config = acl.prof.create_config(device_list, 0, 0, ACL_PROF_ACL_API | ACL_PROF_TASK_TIME | ACL_PROF_AICPU | ACL_PROF_AICORE_METRICS | ACL_PROF_HCCL_TRACE)<br>mem_freq = "15"<br>ret = acl.prof.set_config(ACL_PROF_SYS_HARDWARE_MEM_FREQ, mem_freq)<br>ret = acl.prof.start(prof_config)<br># 6.执行模型。<br>ret = acl.mdl.execute(model_id, input, output)<br># 7.处理模型推理结果。<br># ......<br># 8.释放描述模型输入/输出信息、内存等资源,卸载模型。<br># ......<br># 9.关闭profiling配置, 释放配置资源, 释放profiling组件资源。<br>ret = acl.prof.stop(prof_config)<br>ret = acl.prof.destroy_config(prof_config)<br>ret = acl.prof.finalize()<br># 10.释放运行管理资源<br># ......<br>

Profiling pyACL API for Extension示例代码

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

示例中,运行管理资源申请与释放请参见运行管理资源申请流程运行管理资源释放流程,模型加载的接口调用流程请参见接口调用流程,模型推理的接口调用流程、准备模型推理的输入/输出数据的接口调用流程请参见准备模型执行的输入/输出数据结构

for i in range(200000):
stamp = acl.prof.create_stamp()
if stamp == 0:
print("create stamp failed")
return FAILED

msg = "test msprof tx"
msg_len = len(msg)
ret = acl.prof.set_stamp_trace_message(stamp, msg, msg_len)
ret = acl.prof.mark(stamp)

ret = acl.prof.destroy_stamp(stamp)

for i in range(200000):
stamp = acl.prof.create_stamp()
if stamp == 0:
print("create stamp failed")
return FAILED

msg = "test msprof tx"
msg_len = len(msg)
ret = acl.prof.set_stamp_trace_message(stamp, msg, msg_len)

## acl.prof.push 和 acl.prof.pop 接口配对使用,完成单线程采集
ret = acl.prof.push(stamp)
ret = acl.prof.pop()

ret = acl.prof.destroy_stamp(stamp)

for i in range(200000):
stamp = acl.prof.create_stamp()
if stamp == 0:
print("create stamp failed")
return FAILED

msg = "test msprof tx"
msg_len = len(msg)
ret = acl.prof.set_stamp_trace_message(stamp, msg, msg_len)

## acl.prof.range_start 和 acl.prof.range_stop 接口配对使用,可以完成多线程采集
range_id = 0
range_id, ret = acl.prof.range_start(stamp)
ret = acl.prof.range_stop(range_id)

ret = acl.prof.destroy_stamp(stamp)

Profiling pyACL API for Subscription示例代码

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

示例中,运行管理资源申请与释放请参见运行管理资源申请流程运行管理资源释放流程,模型加载的接口调用流程请参见接口调用流程,模型推理的接口调用流程、准备模型推理的输入/输出数据的接口调用流程请参见准备模型执行的输入/输出数据结构

<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>63<br>64<br>65<br>66<br>67<br>68<br>69<br>70<br>71<br>72<br>73<br>74<br>75<br>76<br>77<br>78<br>79<br>80<br>81<br>82<br>83<br>84<br>85<br>python<br>import acl<br>import numpy as np<br># ......<br># 1.申请运行管理资源,包括设置用于计算的Device、创建Context、创建Stream。<br># ......<br># 2.模型加载,加载成功后,返回标识模型的model_id。<br># ......<br># 3.创建aclmdlDataset类型的数据,用于描述模型的输入数据input、输出数据output。<br># ......<br># 4.创建管道,用于读取以及写入模型订阅的数据。<br>r, w = os.pipe()<br># 5.创建模型订阅的配置并且进行模型订阅。<br>ACL_AICORE_NONE = 0xFF<br>subscribe_config = acl.prof.create_subscribe_config(1, ACL_AICORE_NONE, w)<br># 模型订阅需要传入模型的model_id。<br>ret = acl.prof.model_subscribe(model_id, subscribe_config)<br># 6.实现管道读取订阅数据的函数。<br># 6.1 自定义函数,实现从用户内存中读取订阅数据的函数。<br>def get_model_info(data, data_len):<br> # 获取算子信息个数。<br> op_number, ret = acl.prof.get_op_num(data, data_len)<br> # 遍历用户内存的算子信息。<br> for i in range(op_number):<br> # 获取算子的模型id。<br> model_id = acl.prof.get_model_id(data, data_len, i)<br> # 获取算子的类型名称。<br> op_type, ret = acl.prof.get_op_type(data, data_len, i, 65)<br> # 获取算子的名称。<br> op_name, ret = acl.prof.get_op_name(data, data_len, i, 275)<br> # 获取算子的执行开始时间。<br> op_start = acl.prof.get_op_start(data, data_len, i)<br> # 获取算子的执行结束时间。<br> op_end = acl.prof.get_op_end(data, data_len, i)<br> # 获取算子执行的耗时时间。<br> op_duration = acl.prof.get_op_duration(data, data_len, i)<br># 6.2 自定义函数,实现从管道中读取数据到用户内存的函数。<br>def prof_data_read(args):<br> fd, ctx = args<br> ret = acl.rt.set_context(ctx)<br> # 获取单位算子信息的大小(Byte)。<br> buffer_size, ret = acl.prof.get_op_desc_size()<br> # 设置每次从管道中读取的算子信息个数。<br> N = 10<br> # 计算存储算子信息的内存的大小。<br> data_len = buffer_size * N<br> # 从管道中读取数据到申请的内存中,读取到的实际数据大小可能小于buffer_size * N,如果管道中没有数据,默认会阻塞直到读取到数据为止。<br> while True:<br> data = os.read(fd, data_len)<br> if len(data) == 0:<br> break<br> np_data = np.array(data)<br> <br> bytes_data = np_data.tobytes()<br> np_data_ptr = acl.util.bytes_to_ptr(bytes_data)<br> size = np_data.itemsize * np_data.size<br> # 调用6.1实现的函数解析内存中的数据。<br> get_model_info(np_data_ptr, size)<br># 7.启动线程读取管道数据并解析。<br>thr_id, ret = acl.util.start_thread(prof_data_read, [r, context])<br># 8.执行模型。<br>ret = acl.mdl.execute(model_id, input, output)<br># 9.处理模型推理结果。<br># ......<br># 10.释放描述模型输入/输出信息、内存等资源,卸载模型。<br># ......<br># 11.取消订阅,释放订阅相关资源。<br>ret = acl.prof.model_unsubscribe(model_id)<br>ret = acl.util.stop_thread(thr_id)<br>os.close(r)<br>ret = acl.prof.destroy_subscribe_config(subscribe_config)<br># 12.释放运行管理资源。<br># ......<br>

父主题: 扩展更多特性

在线提单