使用MSPTI采集

MSPTI(MindStudio Profiling Tool Interface,MindStudio Profiling工具接口)可以构建针对NPU应用程序的工具,用于分析应用程序的Tracing和Profiling数据。

开发者通过使用MSPTI提供的API开发Profiling分析工具,深入了解NPU的运行状态。

MSPTI工具为通用场景工具,使用MSPTI API开发的Profiling分析工具可以在各种框架的推理或训练场景生效。

支持的型号

Atlas 200/500 A2推理产品

Atlas A2训练系列产品/Atlas 800I A2推理产品

前提条件

MSPTI工具接口介绍

MSPTI工具当前提供如下类型的API:

具体接口如下:

详细接口介绍请参见MSPTI API参考

表1 Activity 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不会被遗漏。

表2 Callback API

接口

说明

Function类型

msptiSubscribe

通过该接口向MSPTI注册回调函数。

msptiUnsubscribe

向MSPTI注销当前订阅者。

msptiEnableCallback

为特定domainCallbackId的订阅者开启或关闭回调。

msptiEnableDomain

为特定domain的订阅者开启或关闭所有回调。

Typedef类型

msptiCallbackFunc

回调函数类型。

msptiCallbackId

API回调时的ID。

msptiSubscriberHandle

订阅者的句柄。

Enumeration类型

msptiCallbackDomain

相关API函数或CANN驱动程序活动的回调点。

msptiApiCallbackSite

指定API调用中发出回调的点。

msptiCallbackIdRuntime

Runtime API函数的索引定义。

msptiCallbackIdHccl

HCCL API函数的索引的简要定义。

Data Structure类型

msptiCallbackData

用于指定传递到回调函数的数据。

表3 Result Codes

接口

说明

Enumeration类型

msptiResult

MSPTI返回的错误和结果代码。

使用示例

Activity API

// MSPTI
#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;
	// MSPTI
	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;
}
Callback API
#include <iostream>
#include <vector>
#include "acl/acl.h"
#include "aclnnop/aclnn_add.h"

// MSPTI
#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;
}