使用MSPTI采集
MSPTI(MindStudio Profiling Tool Interface,MindStudio Profiling工具接口)可以构建针对NPU应用程序的工具,用于分析应用程序的Tracing和Profiling数据。
开发者通过使用MSPTI提供的API开发Profiling分析工具,深入了解NPU的运行状态。
MSPTI为通用场景接口,使用MSPTI API开发的Profiling分析工具可以在各种框架的推理训练场景生效。
- Tracing:在MSPTI中Tracing是指CANN应用程序执行启动CANN活动的时间戳和附加信息的收集,如CANN API、Kernel、内存拷贝等。通过了解程序运行耗时,识别CANN代码的性能问题。可以使用Activity API和Callback API收集Tracing信息。
- Profiling:在MSPTI中Profiling是指单独收集一个或一组Kernel的NPU性能指标。
支持的型号
Atlas 200/500 A2推理产品
Atlas A2训练系列产品/Atlas 800I A2推理产品
前提条件
- 请确保完成使用前准备。
- 安装如下环境变量:
export LD_PRELOAD=CANN软件安装目录/ascend-toolkit/latest/lib64/libmspti.so
MSPTI工具接口介绍
MSPTI工具当前提供如下类型的API:
- Activity API:异步记录CANN活动,例如:CANN API、Kernel、内存拷贝等。
- Callback API:CANN事件回调机制,用于实时通知用户(订阅者)特定的CANN事件已执行,例如:CANN的runtime内存拷贝。
具体接口如下:
详细接口介绍请参见MSPTI API参考。
接口 |
说明 |
|---|---|
Function类型 |
|
msptiActivityRegisterCallbacks |
向MSPTI注册回调函数,用于Activity Buffer处理。 |
msptiActivityEnable |
用于使能指定Activity类型数据的采集。 |
msptiActivityDisable |
停止收集特定类型的Activity Record。 |
msptiActivityGetNextRecord |
迭代从Activity Buffer获取Activity Record数据。 |
msptiActivityFlushAll |
订阅者手动Flush Activity Buffer中记录的数据。 |
Typedef类型 |
|
msptiBuffersCallbackRequestFunc |
注册回调函数类型,由用户实现。 |
msptiBuffersCallbackCompleteFunc |
注册回调函数类型,由用户实现。 |
Enumeration类型 |
|
msptiActivityKind |
对所有能采集到的Activity数据进行分类。 |
msptiActivityFlag |
Activity Record的活动标记。 |
msptiActivitySourceKind |
标记Activity数据来源。 |
Data Structure类型 |
|
msptiActivity |
Activity Record的基础结构体。 |
msptiActivityApi |
Activity Record类型MSPTI_ACTIVITY_KIND_API对应的结构体。 |
msptiActivityMarker |
Activity Record类型MSPTI_ACTIVITY_KIND_MARKER对应的结构体。 |
msptiActivityKernel |
Activity Record类型MSPTI_ACTIVITY_KIND_KERNEL对应的结构体。 |
Activity Record:NPU的C数据结构报告。
Activity Buffer:用于缓存Activity Record数据,并将一个或多个Activity Record从MSPTI传输到客户端。用户根据业务需要提供空的Activity Buffer缓冲区,以确保Activity Record不会被遗漏。
接口 |
说明 |
|---|---|
Function类型 |
|
msptiSubscribe |
通过该接口向MSPTI注册回调函数。 |
msptiUnsubscribe |
向MSPTI注销当前订阅者。 |
msptiEnableCallback |
为特定domain和CallbackId的订阅者开启或关闭回调。 |
msptiEnableDomain |
为特定domain的订阅者开启或关闭所有回调。 |
Typedef类型 |
|
msptiCallbackFunc |
回调函数类型。 |
msptiCallbackId |
API回调时的ID。 |
msptiSubscriberHandle |
订阅者的句柄。 |
Enumeration类型 |
|
msptiCallbackDomain |
相关API函数或CANN驱动程序活动的回调点。 |
msptiApiCallbackSite |
指定API调用中发出回调的点。 |
msptiCallbackIdRuntime |
Runtime API函数的索引定义。 |
msptiCallbackIdHccl |
HCCL API函数的索引的简要定义。 |
Data Structure类型 |
|
msptiCallbackData |
用于指定传递到回调函数的数据。 |
接口 |
说明 |
|---|---|
Enumeration类型 |
|
msptiResult |
MSPTI返回的错误和结果代码。 |
使用示例
Activity API
#include "mspti.h"
void UserBufferRequest(uint8_t **buffer, size_t *size, size_t *maxNumRecords) {
constexpr uint32_t SIZE = 5 * 1024 * 1024;
uint8_t *pBuffer = (uint8_t *) malloc(SIZE + ALIGN_SIZE);
*buffer = ALIGN_BUFFER(pBuffer, ALIGN_SIZE);
*size = 5 * 1024 * 1024;
*maxNumRecords = 0;
}
void UserBufferComplete(uint8_t *buffer, size_t size, size_t validSize) {
if (validSize > 0) {
msptiActivity *pRecord = NULL;
msptiResult status = MSPTI_SUCCESS;
do {
status = msptiActivityGetNextRecord(buffer, validSize, &pRecord);
if (status == MSPTI_SUCCESS) {
if (pRecord->kind == MSPTI_ACTIVITY_KIND_MARKER) {
... 消费数据逻辑
}
} else if (status == MSPTI_ERROR_MAX_LIMIT_REACHED) {
break;
}
} while (1);
}
free(buffer);
}
int main() {
// 根据自己的实际device填写deviceId
int32_t deviceId = 1;
aclrtContext context;
aclrtStream stream;
msptiSubscriberHandle subscriber;
msptiSubscribe(&subscriber, nullptr, nullptr);
// 注册Request和Complete函数
msptiActivityRegisterCallbacks(UserBufferRequest, UserBufferComplete);
// 开启MARKER类型数据采集
msptiActivityEnable(MSPTI_ACTIVITY_KIND_MARKER);
auto ret = Init(deviceId, &context, &stream); // acl初始化
for (size_t i = 0; i < 3; ++i) {
mstxMarkA("AAA", stream);
}
aclFinalize();
msptiActivityDisable(MSPTI_ACTIVITY_KIND_MARKER);
// 刷新落盘
msptiActivityFlushAll(1);
msptiUnsubscribe(subscriber);
return 0;
}
#include <iostream>
#include <vector>
#include "acl/acl.h"
#include "aclnnop/aclnn_add.h"
#include "mspti.h"
int Init(int32_t deviceId, aclrtContext* context, aclrtStream* stream) {
// acl初始化
auto ret = aclrtSetDevice(deviceId);
ret = aclrtCreateContext(context, deviceId);
ret = aclrtSetCurrentContext(*context);
ret = aclrtCreateStream(stream);
ret = aclInit(nullptr);
return 0;
}
// 用户回调函数
void UserCallback(void *pUserData, msptiCallbackDomain domain, msptiCallbackId callbackId, const msptiCallbackData *pCallbackInfo) {
if (pCallbackInfo->callbackSite == MSPTI_API_ENTER) {
LOG_PRINT("Enter: %s\n", pCallbackInfo->functionName);
} else if (pCallbackInfo->callbackSite == MSPTI_API_EXIT) {
LOG_PRINT("Exit: %s\n", pCallbackInfo->functionName);
}
}
int main() {
// (固定写法)device/context/stream初始化
int32_t deviceId = 0;
aclrtContext context;
aclrtStream stream;
// 订阅MSPTI
msptiSubscriberHandle subscriber;
msptiSubscribe(&subscriber, UserCallback, nullptr);
// 开启MSPTI_CBID_RUNTIME_CONTEXT_CREATED_EX回调
msptiEnableCallback(1, subscriber, MSPTI_CB_DOMAIN_RUNTIME, MSPTI_CBID_RUNTIME_CONTEXT_CREATED_EX);
...
msptiEnableCallback(0, subscriber, MSPTI_CB_DOMAIN_RUNTIME, MSPTI_CBID_RUNTIME_CONTEXT_CREATED_EX);
auto ret = Init(deviceId, &context, &stream);
// 取消订阅
msptiUnsubscribe(subscriber);
return 0;
}