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.start和acl.prof.stop接口之间调用acl.prof.create_stamp、acl.prof.push、acl.prof.pop、acl.prof.range_start、acl.prof.range_stop、acl.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示例代码
调用接口后,需增加异常处理的分支,示例代码中不一一列举。以下是关键步骤的代码示例,不可以直接拷贝运行,仅供参考。
示例中,运行管理资源申请与释放请参见运行管理资源申请流程与运行管理资源释放流程,模型加载的接口调用流程请参见接口调用流程,模型推理的接口调用流程、准备模型推理的输入/输出数据的接口调用流程请参见准备模型执行的输入/输出数据结构。
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
import acl import numpy as np # ...... # 1.申请运行管理资源。 # ...... # 2.模型加载,加载成功后,返回标识模型的model_id。 # ...... # 3.创建aclmdlDataset类型的数据,用于描述模型的输入数据input、输出数据output。 # ...... # 4.profiling初始化。 # 设置数据落盘路径。 PROF_INIT_PATH='...' ret = acl.prof.init(PROF_INIT_PATH) # 5.进行profiling配置。 device_list = [0] ACL_PROF_ACL_API = 0x0001 ACL_PROF_TASK_TIME = 0x0002 ACL_PROF_AICORE_METRICS = 0x0004 ACL_PROF_AICPU_TRACE = 0x0008 ACL_PROF_SYS_HARDWARE_MEM_FREQ = 3 # 创建配置类型指针地址。 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_L2CACHE | ACL_PROF_HCCL_TRACE) mem_freq = "15" ret = acl.prof.set_config(ACL_PROF_SYS_HARDWARE_MEM_FREQ, mem_freq) ret = acl.prof.start(prof_config) # 6.执行模型。 ret = acl.mdl.execute(model_id, input, output) # 7.处理模型推理结果。 # ...... # 8.释放描述模型输入/输出信息、内存等资源,卸载模型。 # ...... # 9.关闭profiling配置, 释放配置资源, 释放profiling组件资源。 ret = acl.prof.stop(prof_config) ret = acl.prof.destroy_config(prof_config) ret = acl.prof.finalize() # 10.释放运行管理资源 # ...... |
Profiling pyACL API for Extension示例代码
调用接口后,需增加异常处理的分支,示例代码中不一一列举。以下是关键步骤的代码示例,不可以直接拷贝运行,仅供参考。
示例中,运行管理资源申请与释放请参见运行管理资源申请流程与运行管理资源释放流程,模型加载的接口调用流程请参见接口调用流程,模型推理的接口调用流程、准备模型推理的输入/输出数据的接口调用流程请参见准备模型执行的输入/输出数据结构。
示例一(acl.prof.mark示例):
# 包括采集项mac_fp16_ratio、mac_int8_ratio、vec_fp32_ratio、vec_fp16_ratio、 # vec_int32_ratio、vec_misc_ratio ACL_AICORE_ARITHMETIC_UTILIZATION = 0 # profiling data type config ACL_PROF_ACL_API = 0x00000001 ACL_PROF_TASK_TIME = 0x00000002 ACL_PROF_MSPROFTX = 0x00000080 # profiling config type ACL_PROF_SYS_HARDWARE_MEM_FREQ = 3 # AscendCL初始化 # 申请运行管理资源 # profiling初始化, 设置数据落盘路径 prof_path = "..." ret = acl.prof.init(PROF_INIT_PATH) assert ret == 0 device_list = [0] prof_config = acl.prof.create_config(device_list, ACL_AICORE_ARITHMETIC_UTILIZATION, 0, ACL_PROF_ACL_API | ACL_PROF_TASK_TIME | ACL_PROF_MSPROFTX) assert prof_config != 0 mem_freq = "15" ret = acl.prof.set_config(ACL_PROF_SYS_HARDWARE_MEM_FREQ, mem_freq) self.assertEqual(ret, 0) ret = acl.prof.start(prof_config) assert ret == 0 # 模型加载,加载成功后,返回标识模型的model_id stamp = acl.prof.create_stamp() assert stamp != 0 load_msg = "model_load_mark" ret = acl.prof.set_stamp_trace_message(stamp, load_msg, len(load_msg)) assert ret == 0 ret = acl.prof.mark(stamp) # 标记模型加载事件 assert ret == 0 acl.prof.destroy_stamp(stamp) # 创建aclmdlDataset类型的数据,用于描述模型的输入数据input、输出数据output # 执行模型 stamp = acl.prof.create_stamp() assert stamp != 0 exec_msg = "model_exec_mark" ret = acl.prof.set_stamp_trace_message(stamp, exec_msg, len(exec_msg)) assert ret == 0 ret = acl.prof.mark(stamp) # 标记模型执行事件 assert ret == 0 acl.prof.destroy_stamp(stamp) ret = acl.mdl.execute(model_id, dataset_input, dataset_output) assert ret == 0 ret = acl.prof.stop(prof_config) assert ret == 0 ret = acl.prof.finalize() assert ret == 0 ret = acl.prof.destroy_config(prof_config) assert ret == 0 # 释放运行管理资源 # AscendCL去初始化
示例二(acl.prof.mark_ex示例,在模型执行前后打点)
# 包括采集项mac_fp16_ratio、mac_int8_ratio、vec_fp32_ratio、vec_fp16_ratio、 # vec_int32_ratio、vec_misc_ratio ACL_AICORE_ARITHMETIC_UTILIZATION = 0 # 获取用户和上层框架程序输出的性能数据 ACL_PROF_MSPROFTX = 0x00000080 # AscendCL初始化 # 申请运行管理资源 prof_path = "..." ret = acl.prof.init(PROF_INIT_PATH) assert ret == 0 device_list = [0] prof_config = acl.prof.create_config(device_list, ACL_AICORE_ARITHMETIC_UTILIZATION, 0, ACL_PROF_MSPROFTX) assert prof_config != 0 ret = acl.prof.start(prof_config) assert ret == 0 ret = acl.prof.mark_ex("model execute start", stream) assert ret == 0 # 执行模型 ret = acl.prof.mark_ex("model execute stop", stream) assert ret == 0 ret = acl.prof.stop(prof_config) assert ret == 0 ret = acl.prof.finalize() assert ret == 0 ret = acl.prof.destroy_config(prof_config) assert ret == 0 # 释放运行管理资源 # AscendCL去初始化
示例三(acl.prof.push/acl.prof.pop示例,适用于单线程):
# 包括采集项mac_fp16_ratio、mac_int8_ratio、vec_fp32_ratio、vec_fp16_ratio、 # vec_int32_ratio、vec_misc_ratio ACL_AICORE_ARITHMETIC_UTILIZATION = 0 # profiling data type config ACL_PROF_ACL_API = 0x00000001 ACL_PROF_TASK_TIME = 0x00000002 # profiling config type ACL_PROF_SYS_HARDWARE_MEM_FREQ = 3 # AscendCL初始化 # 申请运行管理资源 # profiling初始化, 设置数据落盘路径 prof_path = "..." ret = acl.prof.init(PROF_INIT_PATH) assert ret == 0 device_list = [0] prof_config = acl.prof.create_config(device_list, ACL_AICORE_ARITHMETIC_UTILIZATION, 0, ACL_PROF_ACL_API | ACL_PROF_TASK_TIME) assert prof_config != 0 mem_freq = "15" ret = acl.prof.set_config(ACL_PROF_SYS_HARDWARE_MEM_FREQ, mem_freq) self.assertEqual(ret, 0) ret = acl.prof.start(prof_config) assert ret == 0 # 模型加载,加载成功后,返回标识模型的modelId # 创建aclmdlDataset类型的数据,用于描述模型的输入数据input、输出数据output # 执行模型(模型仅在单线程执行) stamp = acl.prof.create_stamp() assert stamp != 0 exec_msg = "acl.mdl.execute_duration" ret = acl.prof.set_stamp_trace_message(stamp, exec_msg, len(exec_msg)) assert ret == 0 ret = acl.prof.push(stamp) assert ret == 0 ret = acl.mdl.execute(model_id, dataset_input, dataset_output) assert ret == 0 ret = acl.prof.pop(stamp) assert ret == 0 acl.prof.destroy_stamp(stamp) # 处理模型推理结果 ret = acl.prof.stop(prof_config) assert ret == 0 ret = acl.prof.finalize() assert ret == 0 ret = acl.prof.destroy_config(prof_config) assert ret == 0 # 释放运行管理资源 # AscendCL去初始化
示例四(acl.prof.range_start/acl.prof.range_stop示例,适用于单线程或跨线程):
# 包括采集项mac_fp16_ratio、mac_int8_ratio、vec_fp32_ratio、vec_fp16_ratio、 # vec_int32_ratio、vec_misc_ratio ACL_AICORE_ARITHMETIC_UTILIZATION = 0 # profiling data type config ACL_PROF_ACL_API = 0x00000001 ACL_PROF_TASK_TIME = 0x00000002 # profiling config type ACL_PROF_SYS_HARDWARE_MEM_FREQ = 3 # AscendCL初始化 # 申请运行管理资源 # profiling初始化, 设置数据落盘路径 prof_path = "..." ret = acl.prof.init(PROF_INIT_PATH) assert ret == 0 device_list = [0] prof_config = acl.prof.create_config(device_list, ACL_AICORE_ARITHMETIC_UTILIZATION, 0, ACL_PROF_ACL_API | ACL_PROF_TASK_TIME) assert prof_config != 0 mem_freq = "15" ret = acl.prof.set_config(ACL_PROF_SYS_HARDWARE_MEM_FREQ, mem_freq) self.assertEqual(ret, 0) ret = acl.prof.start(prof_config) assert ret == 0 # 模型加载,加载成功后,返回标识模型的modelId # 创建aclmdlDataset类型的数据,用于描述模型的输入数据input、输出数据output # 执行模型(模型在跨线程执行) stamp = acl.prof.create_stamp() assert stamp != 0 exec_msg = "acl.mdl.execute_duration" ret = acl.prof.set_stamp_trace_message(stamp, exec_msg, len(exec_msg)) assert ret == 0 range_id, ret = acl.prof.range_start(stamp) assert ret == 0 ret = acl.mdl.execute(model_id, dataset_input, dataset_output) assert ret == 0 ret = acl.prof.range_stop(range_id) assert ret == 0 acl.prof.destroy_stamp(stamp) # 处理模型推理结果 ret = acl.prof.stop(prof_config) assert ret == 0 ret = acl.prof.finalize() assert ret == 0 ret = acl.prof.destroy_config(prof_config) assert ret == 0 # 释放运行管理资源 # AscendCL去初始化
Profiling pyACL API for Subscription示例代码
调用接口后,需增加异常处理的分支,示例代码中不一一列举。以下是关键步骤的代码示例,不可以直接拷贝运行,仅供参考。
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
import acl import numpy as np # ...... # 1.申请运行管理资源。 # ...... # 2.模型加载,加载成功后,返回标识模型的model_id。 # ...... # 3.创建aclmdlDataset类型的数据,用于描述模型的输入数据input、输出数据output。 # ...... # 4.创建管道,用于读取以及写入模型订阅的数据。 r, w = os.pipe() # 5.创建模型订阅的配置并且进行模型订阅。 ACL_AICORE_NONE = 0xFF subscribe_config = acl.prof.create_subscribe_config(1, ACL_AICORE_NONE, w) # 模型订阅需要传入模型的model_id。 ret = acl.prof.model_subscribe(model_id, subscribe_config) # 6.实现管道读取订阅数据的函数。 # 6.1 自定义函数,实现从用户内存中读取订阅数据的函数。 def get_model_info(data, data_len): # 获取算子信息个数。 op_number, ret = acl.prof.get_op_num(data, data_len) # 遍历用户内存的算子信息。 for i in range(op_number): # 获取算子的模型id。 model_id = acl.prof.get_model_id(data, data_len, i) # 获取算子的类型名称。 op_type, ret = acl.prof.get_op_type(data, data_len, i, 65) # 获取算子的名称。 op_name, ret = acl.prof.get_op_name(data, data_len, i, 275) # 获取算子的执行开始时间。 op_start = acl.prof.get_op_start(data, data_len, i) # 获取算子的执行结束时间。 op_end = acl.prof.get_op_end(data, data_len, i) # 获取算子执行的耗时时间。 op_duration = acl.prof.get_op_duration(data, data_len, i) # 6.2 自定义函数,实现从管道中读取数据到用户内存的函数。 def prof_data_read(args): fd, ctx = args ret = acl.rt.set_context(ctx) # 获取单位算子信息的大小(Byte)。 buffer_size, ret = acl.prof.get_op_desc_size() # 设置每次从管道中读取的算子信息个数。 N = 10 # 计算存储算子信息的内存的大小。 data_len = buffer_size * N # 从管道中读取数据到申请的内存中,读取到的实际数据大小可能小于buffer_size * N,如果管道中没有数据,默认会阻塞直到读取到数据为止。 while True: data = os.read(fd, data_len) if len(data) == 0: break np_data = np.array(data) bytes_data = np_data.tobytes() np_data_ptr = acl.util.bytes_to_ptr(bytes_data) size = np_data.itemsize * np_data.size # 调用6.1实现的函数解析内存中的数据。 get_model_info(np_data_ptr, size) # 7.启动线程读取管道数据并解析。 thr_id, ret = acl.util.start_thread(prof_data_read, [r, context]) # 8.执行模型。 ret = acl.mdl.execute(model_id, input, output) # 9.处理模型推理结果。 # ...... # 10.释放描述模型输入/输出信息、内存等资源,卸载模型。 # ...... # 11.取消订阅,释放订阅相关资源。 ret = acl.prof.model_unsubscribe(model_id) ret = acl.util.stop_thread(thr_id) os.close(r) ret = acl.prof.destroy_subscribe_config(subscribe_config) # 12.释放运行管理资源。 # ...... |