使用MSPTI采集
MSPTI(MindStudio Profiling Tool Interface,MindStudio Profiling工具接口)是MindStudio针对Ascend设备提出的一套Profiling API,用户可以通过MSPTI构建针对NPU应用程序的工具,用于分析应用程序的性能。
MSPTI为通用场景接口,使用MSPTI API开发的Profiling分析工具可以在各种框架的推理训练场景生效。
- Tracing:在MSPTI中Tracing是指CANN应用程序执行启动CANN活动的时间戳和附加信息的收集,如CANN API、Kernel、内存拷贝等。通过了解程序运行耗时,识别CANN代码的性能问题。可以使用Activity API和Callback API收集Tracing信息。
- Profiling:在MSPTI中Profiling是指单独收集一个或一组Kernel的NPU性能指标。
支持的型号
前提条件
- 请确保完成使用前准备。
- 设置如下环境变量:
export LD_PRELOAD=CANN软件安装目录/ascend-toolkit/latest/lib64/libmspti.so
MSPTI工具C API介绍
当前提供如下类型的API:
- Activity API:异步记录CANN活动,例如:CANN API、Kernel、内存拷贝等。
- Callback API:CANN事件回调机制,用于实时通知用户(订阅者)特定的CANN事件已执行,例如:CANN的runtime内存拷贝。
具体接口如下:
详细接口介绍请参见MSPTI C API参考。
接口 |
说明 |
---|---|
Function类型 |
|
msptiActivityRegisterCallbacks |
向MSPTI注册回调函数,用于Activity Buffer处理。 |
msptiActivityEnable |
用于使能指定Activity类型数据的采集。 |
msptiActivityDisable |
停止收集特定类型的Activity Record。 |
msptiActivityGetNextRecord |
依次从Activity Buffer获取Activity Record数据。 |
msptiActivityFlushAll |
订阅者手动Flush Activity Buffer中记录的数据。 |
Typedef类型 |
|
msptiBuffersCallbackRequestFunc |
向MSPTI注册回调函数,申请Activity Buffer的存储空间。 |
msptiBuffersCallbackCompleteFunc |
向MSPTI注册回调函数,释放Activity Buffer中的数据。 |
Enumeration类型 |
|
msptiActivityKind |
MSPTI支持的所有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的Profiling记录,使用结构体表示,如msptiActivityApi、msptiActivityMarker等。
Activity Buffer:用于缓存Activity Record数据,并将一个或多个Activity Record从MSPTI传输到客户端。用户根据业务需要提供空的Activity Buffer缓冲区,以确保Activity Record不会被遗漏。
接口 |
说明 |
---|---|
Function类型 |
|
msptiSubscribe |
通过该接口向MSPTI注册回调函数。 |
msptiUnsubscribe |
向MSPTI注销当前订阅者。 |
msptiEnableCallback |
为特定domain和CallbackId的订阅者开启或关闭回调。 |
msptiEnableDomain |
为特定domain的订阅者开启或关闭所有回调。 |
Typedef类型 |
|
msptiCallbackFunc |
回调函数类型。 |
msptiCallbackId |
注册的Callback调用点ID。 |
msptiSubscriberHandle |
订阅者的句柄。 |
Enumeration类型 |
|
msptiCallbackDomain |
相关API函数或CANN驱动程序活动的回调点。 |
msptiApiCallbackSite |
指定API调用中发出回调的点,如回调的开始和回调的结束。 |
msptiCallbackIdRuntime |
Runtime API函数的索引定义。 |
msptiCallbackIdHccl |
HCCL API函数的索引的简要定义。 |
Data Structure类型 |
|
msptiCallbackData |
用于指定传递到回调函数的数据。 |
接口 |
说明 |
---|---|
Enumeration类型 |
|
msptiResult |
MSPTI返回的错误和结果代码。 |
使用示例
Activity 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 49 50 51 52 | #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;
}
|
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 | #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;
}
|