MI IPU API
REVISION HISTORY¶
Revision No. | Description |
Date |
---|---|---|
3.0 | 07/23/2021 | |
08/25/2021 | ||
11/30/2021 | ||
12/21/2021 | ||
01/20/2022 | ||
02/25/2022 | ||
06/01/2022 | ||
06/13/2022 | ||
08/15/2022 | ||
05/25/2023 | ||
09/26/2023 | ||
07/25/2024 | ||
04/16/2025 |
1. 概述¶
1.1. 模块说明¶
IPU是智能处理器,主要功能是在MI IPU模块驱动下实现AI模型的推演加速功能。
关键词说明:
-
IPU
智能处理器
-
Firmware
驱动IPU硬件的程序文件
-
Tensor
网络模型中的多维数据
-
Input Tensor
整个AI模型的输入Tensor
-
Output Tensor
整个AI 模型的输出Tensor
1.2. 基本结构¶
MI IPU具有多个channel,能够同时支持多个AI模型的推演。同时支持模块内部分配input/output tensor buffer,也支持直接使用前一级模块的output buffer 作为input tensor buffer。
从软件开发角度来看,应用程序通过MI IPU API调用IPU driver,进而通过IPU driver驱动IPU硬件,实现对AI模型的推理。

1.3. 功能介绍¶
MI IPU支持以下功能:
-
支持多线程、多进程执行模型推理
-
支持多通道
-
支持为模型自动分配buffer,同时也支持由用户来分配buffer
-
支持指定IPU推理任务的优先级
-
支持单次推理单张输入和单次推理多张输入
1.4. 应用场景¶
MI IPU具有以下应用场景:
- 机器人:应用于工业或服务机器人,实现环境感知、路径规划、任务执行等
- 智能IPC/NVR: 用于智能安防设备,结合人脸识别、行为分析、异常检测等功能,提升监控效果
- 会议系统:利用语音识别、人脸识别等技术优化会议体验
1.5. 芯片差异¶
本文档所描述芯片为Pcupid。各代芯片MI IPU模块的差异如下表所示。
Pudding | Tiramisu | Muffin | Mochi | Maruko | Opera | Souffle | Ifado | Iford | Pcupid | Ibopper | Ifackel | Jaguar1 | Ifliegen | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Channel Number | 48 | 48 | 48 | 48 | 48 | 48 | 48 | 8 | 48 | 48 | 48 | 48 | 48 | 48 |
Core Number | 1 | 1 | 2 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 2 | 1 | 2 |
注意:
- Ifackel与Ifliegen IPU的core0用于运行AI ISP模型,core1用于运行通用AI模型
- Muffin IPU的core0和core1都用于跑通用AI模型
1.6. 工作原理¶
用户在调用MI IPU模块进行模型推演前,首先需要使用IPU SDK工具链将原始的深度学习模型转换为硬件所支持的离线模型文件,然后通过调用MI IPU API在板端加载离线模型,并对离线模型推理进行加速。
1.7. 接口调用¶
当执行模型推理时,MI IPU的接口调用通常分为以下步骤:
-
解析模型信息,获取模型所需的variable buffer大小
-
创建IPU设备
-
创建IPU通道
-
获取IPU通道的输入、输出描述符
-
获取输入buffer的地址,并将输入内容拷贝到此buffer,然后flush cache,确保buffer与cache中内容相同
-
获取输出buffer的地址
-
执行模型推理
-
归还前述获取的输入、输出buffer到通道所有buffer
-
销毁IPU通道
-
销毁IPU设备

1.8. 实例介绍¶
1.8.1. dla_classify¶
dla_classify适用于推演分类模型,此时模型的输入格式要求为BGR或RGB。在运行时,该示例首先加载离线模型文件,并驱动IPU对输入图片进行分类,最后打印前5名的分类预测结果和对应的置信度。具体代码可参考
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <signal.h> #include <stdbool.h> #include <error.h> #include <errno.h> #include <pthread.h> #include <string.h> #include <fstream> #include <iostream> #include <string> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <sys/time.h> #include <unistd.h> #include <sys/mman.h> #if 0 #include <openssl/aes.h> #include <openssl/evp.h> #include <openssl/rsa.h> #endif using namespace std; using std::cout; using std::endl; using std::ostringstream; using std::vector; using std::string; #include "mi_common_datatype.h" #include "mi_sys_datatype.h" #include "mi_ipu.h" #include "mi_sys.h" #define LABEL_IMAGE_FUNC_INFO(fmt, args...) do {printf("[Info ] [%-4d] [%10s] ", __LINE__, __func__); printf(fmt, ##args);} while(0) #define alignment_up(a,b) (((a)+(b-1))&(~(b-1))) struct PreProcessedData { char *pImagePath; int intResizeH; int intResizeW; int intResizeC; bool bNorm; float fmeanB; float fmeanG; float fmeanR; float std; bool bRGB; unsigned char * pdata; } ; struct NetInfo { MI_IPU_OfflineModelStaticInfo_t OfflineModelInfo; MI_IPU_SubNet_InputOutputDesc_t desc; }; #define LABEL_CLASS_COUNT (1200) #define LABEL_NAME_MAX_SIZE (60) MI_S32 IPUCreateDevice(char *pFirmwarePath,MI_U32 u32VarBufSize) { MI_S32 s32Ret = MI_SUCCESS; MI_IPU_DevAttr_t stDevAttr; memset(&stDevAttr, 0, sizeof(stDevAttr)); stDevAttr.u32MaxVariableBufSize = u32VarBufSize; s32Ret = MI_IPU_CreateDevice(&stDevAttr, NULL, pFirmwarePath, 0); return s32Ret; } static int H2SerializedReadFunc_1(void *dst_buf,int offset, int size, char *ctx) { // read data from buf return 0; } static int H2SerializedReadFunc_2(void *dst_buf,int offset, int size, char *ctx) { // read data from buf std::cout<<"read from call back function"<<std::endl; memcpy(dst_buf,ctx+offset,size); return 0; } MI_S32 IPUCreateChannel(MI_U32 *s32Channel, char *pModelImage) { MI_S32 s32Ret ; MI_SYS_GlobalPrivPoolConfig_t stGlobalPrivPoolConf; MI_IPUChnAttr_t stChnAttr; //create channel memset(&stChnAttr, 0, sizeof(stChnAttr)); stChnAttr.u32InputBufDepth = 2; stChnAttr.u32OutputBufDepth = 2; return MI_IPU_CreateCHN(s32Channel, &stChnAttr, NULL, pModelImage); } MI_S32 IPUCreateChannel_FromMemory(MI_U32 *s32Channel, char *pModelImage) { MI_S32 s32Ret ; MI_SYS_GlobalPrivPoolConfig_t stGlobalPrivPoolConf; MI_IPUChnAttr_t stChnAttr; //create channel memset(&stChnAttr, 0, sizeof(stChnAttr)); stChnAttr.u32InputBufDepth = 2; stChnAttr.u32OutputBufDepth = 2; return MI_IPU_CreateCHN(s32Channel, &stChnAttr, H2SerializedReadFunc_2, pModelImage); } MI_S32 IPUCreateChannel_FromEncryptFile(MI_U32 *s32Channel, char *pModelImage) { MI_S32 s32Ret ; MI_SYS_GlobalPrivPoolConfig_t stGlobalPrivPoolConf; MI_IPUChnAttr_t stChnAttr; //create channel memset(&stChnAttr, 0, sizeof(stChnAttr)); stChnAttr.u32InputBufDepth = 2; stChnAttr.u32OutputBufDepth = 2; return MI_IPU_CreateCHN(s32Channel, &stChnAttr, H2SerializedReadFunc_2, pModelImage); } MI_S32 IPUDestroyChannel(MI_U32 s32Channel) { MI_S32 s32Ret = MI_SUCCESS; s32Ret = MI_IPU_DestroyCHN(s32Channel); return s32Ret; } void GetImage( PreProcessedData *pstPreProcessedData) { string filename=(string)(pstPreProcessedData->pImagePath); cv::Mat sample; cv::Mat img = cv::imread(filename, -1); if (img.empty()) { std::cout << " error! image don't exist!" << std::endl; exit(1); } int num_channels_ = pstPreProcessedData->intResizeC; if (img.channels() == 3 && num_channels_ == 1) { cv::cvtColor(img, sample, cv::COLOR_BGR2GRAY); } else if (img.channels() == 4 && num_channels_ == 1) { cv::cvtColor(img, sample, cv::COLOR_BGRA2GRAY); } else if (img.channels() == 4 && num_channels_ == 3) { cv::cvtColor(img, sample, cv::COLOR_BGRA2BGR); } else if (img.channels() == 1 && num_channels_ == 3) { cv::cvtColor(img, sample, cv::COLOR_GRAY2BGR); } else { sample = img; } cv::Mat sample_float; if (num_channels_ == 3) sample.convertTo(sample_float, CV_32FC3); else sample.convertTo(sample_float, CV_32FC1); cv::Mat sample_norm = sample_float; if (pstPreProcessedData->bRGB) { cv::cvtColor(sample_float, sample_norm, cv::COLOR_BGR2RGB); } cv::Mat sample_resized; cv::Size inputSize = cv::Size(pstPreProcessedData->intResizeW, pstPreProcessedData->intResizeH); if (sample.size() != inputSize) { cout << "input size should be :" << pstPreProcessedData->intResizeC << " " << pstPreProcessedData->intResizeH << " " << pstPreProcessedData->intResizeW << endl; cout << "now input size is :" << img.channels() << " " << img.rows<<" " << img.cols << endl; cout << "img is going to resize!" << endl; cv::resize(sample_norm, sample_resized, inputSize); } else { sample_resized = sample_norm; } float *pfSrc = (float *)sample_resized.data; int imageSize = pstPreProcessedData->intResizeC*pstPreProcessedData->intResizeW*pstPreProcessedData->intResizeH; for(int i=0;i<imageSize;i++) { *(pstPreProcessedData->pdata+i) = (unsigned char)(round(*(pfSrc + i))); } } static MI_BOOL GetTopN(float aData[], int dataSize, int aResult[], int TopN) { int i, j, k; float data = 0; MI_BOOL bSkip = FALSE; for (i=0; i < TopN; i++) { data = -0.1f; for (j = 0; j < dataSize; j++) { if (aData[j] > data) { bSkip = FALSE; for (k = 0; k < i; k++) { if (aResult[k] == j) { bSkip = TRUE; } } if (bSkip == FALSE) { aResult[i] = j; data = aData[j]; } } } } return TRUE; } MI_U32 _MI_IPU_GetTensorUnitDataSize(MI_IPU_ELEMENT_FORMAT eElmFormat) { switch (eElmFormat) { case MI_IPU_FORMAT_INT16: return sizeof(short); case MI_IPU_FORMAT_INT32: return sizeof(int); case MI_IPU_FORMAT_INT8: return sizeof(char); case MI_IPU_FORMAT_FP32: return sizeof(float); case MI_IPU_FORMAT_UNKNOWN: default: return 1; } } MI_U32 IPU_CalcTensorSize(MI_IPU_TensorDesc_t* pstTensorDescs) { MI_U32 u32Size = 1; MI_U32 u32UnitSize = 1; u32UnitSize = _MI_IPU_GetTensorUnitDataSize(pstTensorDescs->eElmFormat); for (int i = 0; i < pstTensorDescs->u32TensorDim; i++) { u32Size *= pstTensorDescs->u32TensorShape[i]; } u32Size *= u32UnitSize; return u32Size; } static void IPU_PrintOutputXOR(MI_IPU_SubNet_InputOutputDesc_t* desc, MI_IPU_TensorVector_t OutputTensorVector) { MI_U32 u32InputNum = desc->u32InputTensorCount; MI_U32 u32OutputNum = desc->u32OutputTensorCount; volatile MI_U32 u32XORValue = 0; MI_U8 *pu8XORValue[4]= {(MI_U8 *)&u32XORValue,(MI_U8 *)&u32XORValue+1,(MI_U8 *)&u32XORValue+2,(MI_U8 *)&u32XORValue+3 }; MI_U32 u32Count = 0; for (MI_U32 idxOutputNum = 0; idxOutputNum < desc->u32OutputTensorCount; idxOutputNum++) { MI_U8 u8Data = 0; MI_U8 *pu8Data = (MI_U8 *)OutputTensorVector.astArrayTensors[idxOutputNum].ptTensorData[0]; for(int i = 0; i < IPU_CalcTensorSize(&(desc->astMI_OutputTensorDescs[idxOutputNum])); i++) { u8Data = *(pu8Data + i); *pu8XORValue[u32Count%4] ^= u8Data; u32Count++; } } printf("All outputs XOR = 0x%08x\n", u32XORValue); } int main(int argc,char *argv[]) { if ( argc < 5 ) { std::cout << "USAGE: " << argv[0] <<": <xxxsgsimg.img> " \ << "<picture> " << "<labels> "<< "<model intput_format:RGB or BGR>"<<std::endl; exit(0); } else { std::cout<<"model_img:"<<argv[1]<<std::endl; std::cout<<"picture:"<<argv[2]<<std::endl; std::cout<<"labels:"<<argv[3]<<std::endl; std::cout<<"model input_format:"<<argv[4]<<std::endl; } char * pFirmwarePath = NULL; char * pModelImgPath = argv[1]; char * pImagePath= argv[2]; char * pLabelPath =argv[3]; char * pRGB = argv[4]; char * pfps = NULL; char * ptime = NULL; int fps = -1; int duration = -1; if (argc == 7) { pfps = argv[5]; ptime = argv[6]; fps = atoi(pfps); duration = atoi(ptime); } MI_BOOL bRGB = FALSE; if(strncmp(pRGB,"RGB",sizeof("RGB"))!=0 && strncmp(pRGB,"BGR",sizeof("BGR"))!=0 && strncmp(pRGB,"RAWDATA",sizeof("RAWDATA"))!=0) { std::cout << "model intput_format error" <<std::endl; return -1; } static char label[LABEL_CLASS_COUNT][LABEL_NAME_MAX_SIZE]; MI_U32 u32ChannelID = 0; MI_S32 s32Ret; MI_IPU_TensorVector_t InputTensorVector; MI_IPU_TensorVector_t OutputTensorVector; auto net_info = std::make_shared<NetInfo>(); ifstream LabelFile; LabelFile.open(pLabelPath); int n=0; while(1) { LabelFile.getline(&label[n][0],60); if(LabelFile.eof()) break; n++; if(n>=LABEL_CLASS_COUNT) { cout<<"the labels have line:"<<n<<" ,it supass the available label array"<<std::endl; break; } } LabelFile.close(); MI_SYS_Init(0); //1.create device cout<<"get variable size from memory__"<<std::endl; char *pmem = NULL; int fd = 0; struct stat sb; fd = open(pModelImgPath, O_RDWR); if (fd < 0) { perror("open"); return -1; } memset(&sb, 0, sizeof(sb)); if (fstat(fd, &sb) < 0) { perror("fstat"); return -1; } pmem = (char *)mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0); if (pmem == NULL) { perror("mmap"); return -1; } if (MI_SUCCESS != MI_IPU_GetOfflineModeStaticInfo(H2SerializedReadFunc_2, pmem, &net_info->OfflineModelInfo)) { cout<<"get model variable buffer size failed!"<<std::endl; return -1; } if(MI_SUCCESS !=IPUCreateDevice(pFirmwarePath,net_info->OfflineModelInfo.u32VariableBufferSize)) { cout<<"create ipu device failed!"<<std::endl; return -1; } //2.create channel /*case 0 create module from path*/ #if 0 if(MI_SUCCESS !=IPUCreateChannel(u32ChannelID,pModelImgPath)) { cout<<"create ipu channel failed!"<<std::endl; MI_IPU_DestroyDevice(); return -1; } #endif #if 1 /*case1 create channel from memory*/ cout<<"create channel from memory__"<<std::endl; if(MI_SUCCESS !=IPUCreateChannel_FromMemory(&u32ChannelID,pmem)) { cout<<"create ipu channel failed!"<<std::endl; MI_IPU_DestroyDevice(); return -1; } #endif //3.get input/output tensor s32Ret = MI_IPU_GetInOutTensorDesc(u32ChannelID, &net_info->desc); if (s32Ret == MI_SUCCESS) { for (int i = 0; i < net_info->desc.u32InputTensorCount; i++) { cout<<"input tensor["<<i<<"] name :"<<net_info->desc.astMI_InputTensorDescs[i].name<<endl; } for (int i = 0; i < net_info->desc.u32OutputTensorCount; i++) { cout<<"output tensor["<<i<<"] name :"<<net_info->desc.astMI_OutputTensorDescs[i].name<<endl; } } unsigned char *pu8ImageData = NULL; const char* dump_input_bin = getenv("DUMP_INPUT_BIN"); MI_IPU_GetInputTensors( u32ChannelID, &InputTensorVector); int datasize = 0; if(strncmp(pRGB,"RAWDATA",sizeof("RAWDATA"))==0) { FILE* stream; stream = fopen(pImagePath,"r"); fseek(stream, 0, SEEK_END); int length = ftell(stream); cout << "length==" << length<<endl; rewind(stream); if(length != net_info->desc.astMI_InputTensorDescs[0].s32AlignedBufSize) { cout<<"please check input bin size"<<endl; exit(0); } pu8ImageData = new unsigned char[length]; datasize = fread(pu8ImageData,sizeof(unsigned char),length,stream); cout << "size==" << datasize <<endl; fclose(stream); } else { int intResizeH = net_info->desc.astMI_InputTensorDescs[0].u32TensorShape[1]; int intResizeW = net_info->desc.astMI_InputTensorDescs[0].u32TensorShape[2]; int intResizeC = net_info->desc.astMI_InputTensorDescs[0].u32TensorShape[3]; pu8ImageData = new unsigned char[intResizeH*intResizeW*intResizeC]; PreProcessedData stProcessedData; stProcessedData.intResizeC = intResizeC; stProcessedData.intResizeH = intResizeH; stProcessedData.intResizeW = intResizeW; stProcessedData.pdata = pu8ImageData; stProcessedData.pImagePath = pImagePath; if(strncmp(pRGB,"RGB",sizeof("RGB"))==0) { bRGB = TRUE; } stProcessedData.bRGB = bRGB; GetImage(&stProcessedData); datasize=intResizeH*intResizeW*intResizeC; } memcpy(InputTensorVector.astArrayTensors[0].ptTensorData[0],pu8ImageData,datasize); MI_SYS_FlushInvCache(InputTensorVector.astArrayTensors[0].ptTensorData[0], datasize); MI_IPU_GetOutputTensors( u32ChannelID, &OutputTensorVector); if(dump_input_bin) { FILE* stream_input = fopen("inputtoinvoke.bin","w"); int input_size = fwrite(InputTensorVector.astArrayTensors[0].ptTensorData[0],sizeof(unsigned char),datasize,stream_input); fclose(stream_input); } //4.invoke int times = 32; if(fps!=-1) { times =duration*fps; } printf("the times is %d \n",times); struct timespec ts_start, ts_end; clock_gettime(CLOCK_MONOTONIC, &ts_start); for (int i=0;i<times;i++ ) { struct timespec ts_start_1; clock_gettime(CLOCK_MONOTONIC, &ts_start_1); if(MI_SUCCESS!=MI_IPU_Invoke(u32ChannelID, &InputTensorVector, &OutputTensorVector)) { cout<<"IPU invoke failed!!"<<endl; delete pu8ImageData; IPUDestroyChannel(u32ChannelID); MI_IPU_DestroyDevice(); return -1; } struct timespec ts_end_1; clock_gettime(CLOCK_MONOTONIC, &ts_end_1); int elasped_time_1 = (ts_end_1.tv_sec-ts_start_1.tv_sec)*1000000+(ts_end_1.tv_nsec-ts_start_1.tv_nsec)/1000; float durationInus = 0.0; if(fps!=-1) { durationInus = 1000000.0/fps; } if ((elasped_time_1<durationInus)&&(fps!=-1)) { usleep((int)(durationInus-elasped_time_1)); } } clock_gettime(CLOCK_MONOTONIC, &ts_end); int elasped_time = (ts_end.tv_sec-ts_start.tv_sec)*1000000+(ts_end.tv_nsec-ts_start.tv_nsec)/1000; cout<<"fps:"<<1000.0/(float(elasped_time)/1000/times)<<std::endl; // show result of classify IPU_PrintOutputXOR(&net_info->desc, OutputTensorVector); int s32TopN[5]; memset(s32TopN,0,sizeof(s32TopN)); int iDimCount = net_info->desc.astMI_OutputTensorDescs[0].u32TensorDim; int s32ClassCount = 1; for(int i=0;i<iDimCount;i++ ) { s32ClassCount *= net_info->desc.astMI_OutputTensorDescs[0].u32TensorShape[i]; } float *pfData = (float *)OutputTensorVector.astArrayTensors[0].ptTensorData[0]; cout<<"the class Count :"<<s32ClassCount<<std::endl; cout<<std::endl; cout<<std::endl; GetTopN(pfData, s32ClassCount, s32TopN, 5); for(int i=0;i<5;i++) { cout<<"order: "<<i+1<<" index: "<<s32TopN[i]<<" "<<pfData[s32TopN[i]]<<" "<<label[s32TopN[i]]<<endl; } //5. put intput tensor MI_IPU_PutInputTensors(u32ChannelID,&InputTensorVector); MI_IPU_PutOutputTensors(u32ChannelID,&OutputTensorVector); //6.destroy channel/device delete pu8ImageData; IPUDestroyChannel(u32ChannelID); MI_IPU_DestroyDevice(); return 0; }
1.8.2. dla_detect¶
dla_detect用于推演检测模型,且检测模型的输入格式需要为RGB或BGR,模型必须使用SGS的后处理方法。在运行时,该示例首先加载离线模型文件,并驱动IPU对输入图片进行推理检测,最后在当前目录下输出带有检测结果框的图片。具体代码可参考
1.8.3. dla_classifyNBatch¶
dla_classifyNBatch同样用于推演分类模型,对于模型及输入的要求与dla_classify相同。不同之处在于,该示例展示了调用MI_IPU_Invoke2和MI_IPU_Invoke2Custom时输入、输出内存的排布方式,和用户自己分配内存时需要调用的接口和内存对齐等注意事项。具体代码可参考
1.8.4. dla_simulator¶
dla_simulator用于在板端推理模型,并与PC端IPU SDK工具链提供的simulator.py的运行结果进行比对,从而在板端验证模型推理的正确性。该示例适用的模型为经IPU SDK工具链转换的离线模型,模型输入及格式由模型自身决定。具体代码可参考
1.8.5. dla_simulatorNBatch¶
dla_simulatorNBatch同样用于推理板端模型,其适用模型和输入要求同dla_simulator。不同之处在于,dla_simulatorNBatch示例中调用MI_IPU_Invoke2接口,支持单次推理多张输入。具体代码可参考
1.8.6. dla_show_img_info¶
dla_show_img_info用于展示板端推理离线模型的帧率和带宽统计数据,还可以抓取IPU log来分析模型每层性能。其输入为经过IPU SDK工具链转换的任意模型。具体代码可参考
1.8.7. ipu_log¶
ipu_log工具用于在需要分析模型每层性能时抓取IPU log。该工具也集成在dla_show_img_info中。IPU log的开启方法参考抓取IPU log。具体代码可参考
1.8.8. ipu_utilization¶
ipu_utilization用于打印IPU的使用率。当应用程序调用MI IPU接口推理模型时,可运行该工具查看IPU的使用率情况。具体代码可参考
1.8.9. ipu_server¶
ipu_server用于创建IPU的推理服务,在PC端使用python接口推理模型。首先在板端运行该工具并配置端口号,然后在PC端使用IPU SDK工具链提供的rpc_simulator.py连接板端IP和配置的端口号。该工具可推理任意模型,运行结果保存在PC端当前目录下的log/output里。更多rpc_simulator的使用可参考IPU SDK用户文档。具体代码可参考
2. API参考¶
2.1. 功能模块API¶
API名 | 功能 |
---|---|
MI_IPU_CreateDevice | 创建IPU设备 |
MI_IPU_DestroyDevice | 销毁IPU设备 |
MI_IPU_CreateCHN | 创建IPU通道 |
MI_IPU_DestroyCHN | 销毁指定IPU通道 |
MI_IPU_GetInOutTensorDesc | 获取指定通道的网络模型输入输出信息 |
MI_IPU_GetInputTensors | 从指定通道分配输入Tensor Buffer |
MI_IPU_PutInputTensors | 释放指定通道的输入Tensor Buffer |
MI_IPU_GetOutputTensors | 从指定通道分配输出Tensor Buffer |
MI_IPU_PutOutputTensors | 释放指定通道的输出Tensor Buffer |
MI_IPU_Invoke | 执行一次网络模型推演 |
MI_IPU_GetInputTensors2 | 从指定通道分配批处理输入Tensor Buffer |
MI_IPU_PutInputTensors2 | 释放指定通道的批处理输入Tensor Buffer |
MI_IPU_GetOutputTensors2 | 从指定通道分配批处理输出Tensor Buffer |
MI_IPU_PutOutputTensors2 | 释放指定通道的批处理输出Tensor Buffer |
MI_IPU_Invoke2 | 执行一次n_buf batch模式网络模型推演 |
MI_IPU_Invoke2Custom | 执行一次one_buf batch模式网络模型推演 |
MI_IPU_GetOfflineModeStaticInfo | 获取离线模型运行需要的variable buffer size和离线模型文件大小 |
MI_IPU_CancelInvoke | 取消正在执行的Invoke任务 |
MI_IPU_CreateCHNWithUserMem | 使用用户提供的MMA内存创建IPU通道 |
MI_IPU_DestroyDeviceExt | 使用参数销毁IPU设备 |
2.2. MI_IPU_CreateDevice¶
-
功能
创建IPU设备。
-
语法
MI_S32 MI_IPU_CreateDevice(MI_IPU_DevAttr_t *pstIPUDevAttr, SerializedReadFunc pReadFunc, char *pReadCtx, MI_U32 FWSize);
-
形参
参数名称 描述 输入/输出 pstIPUDevAttr IPU设备属性结构体指针 输入 pReadFunc 用户自定义读取文件函数指针(设为NULL默认使用MI IPU提供的文件读取函数) 输入 pReadCtx IPU firmware文件路径(设为NULL默认使用MI IPU提供的文件路径:/config/dla/ipu_firmware.bin) 输入 FWSize IPU firmware文件大小(设为0默认MI IPU自动获取文件大小) 输入 -
返回值
-
MI_SUCCESS成功。
-
非MI_SUCCESS失败,参照错误码。
-
-
依赖
-
头文件:mi_ipu.h
-
库文件:libmi_ipu.so
-
-
举例
MI_S32 s32Ret; stDevAttr.u32MaxVariableBufSize = BufSize; /*模型内部Tensor使用的memory的最大size*/ s32Ret = MI_IPU_CreateDevice(&stDevAttr, NULL, NULL, 0); if (s32Ret != MI_SUCCESS) { printf("fail to create ipu device\n"); return s32Ret; }
2.3. MI_IPU_DestroyDevice¶
-
功能
销毁IPU设备。
-
语法
MI_S32 MI_IPU_DestroyDevice(void);
-
返回值
-
MI_SUCCESS成功。
-
非MI_SUCCESS失败,参照错误码。
-
-
依赖
-
头文件:mi_ipu.h
-
库文件:libmi_ipu.so
-
-
举例
MI_IPU_DestroyDevice();
2.4. MI_IPU_CreateCHN¶
-
功能
创建IPU通道。
-
语法
MI_S32 MI_IPU_CreateCHN(MI_IPU_CHN *ptChnId,MI_IPUChnAttr_t *pstIPUChnAttr, SerializedReadFunc pReadFunc, char *pReadCtx);
-
参数
参数名称 描述 输入/输出 ptChnId 获取IPU通道ID的指针 输出 pstIPUChnAttr IPU通道描述信息结构体指针 输入 pReadFunc 用户自定义读取文件函数(设为NULL默认使用MI IPU提供的文件读取函数) 输入 pReadCtx 网络模型文件路径或者网络模型OS内存地址 输入 -
返回值
-
MI_SUCCESS成功。
-
非MI_SUCCESS失败,参照错误码。
-
-
依赖
-
头文件:mi_ipu.h
-
库文件:libmi_ipu.so
-
-
注意
-
MI_IPUChnAttr_t.u32BatchMax 为批处理的最大值,如果这个模型不需要使用批处理,则将该值设置为1或者0。
-
MI_IPUChnAttr_t.u32InputBufDepth 为设定的输入预分配私有tensor buffer* u32BatchMax的个数,比如 0 or 1 or 2 or 3, 当设置为0时,表示buffer来源于外部。如果直接使用前级模块的输出MI buffer,建议此处设置input_depth为0避免内存浪费。
-
MI_IPUChnAttr_t. u32OutputBufDepth为设定的输出预分配私有tensor buffer* u32BatchMax的个数, 比如 0 or 1 or 2 or 3,当设置为0时,表示buffer来源于外部,如MI_RGN模块。
-
如果创建的是one_buf batch模式网络模型,则不会预分配输入和输出buffer。
-
IPU最大通道数为48。
-
-
举例
MI_S32 s32Ret, buf_depth = 3, batch_max = 1; MI_IPU_CHN u32ChnId = 0; chnAttr.u32InputBufDepth = buf_depth; chnAttr.u32OutputBufDepth = buf_depth; chnAttr.u32BatchMax = batch_max; char pReadCtx[] = "caffe_mobilenet_v2.tflite_sgsimg.img"; s32Ret = MI_IPU_CreateCHN(&u32ChnId, &chnAttr, NULL, pReadCtx); if (s32Ret != MI_SUCCESS) { printf("fail to create ipu channel\n"); return s32Ret; }
2.5. MI_IPU_DestroyCHN¶
-
功能
销毁指定IPU通道。
-
语法
MI_S32 MI_IPU_DestroyCHN(MI_IPU_CHN u32ChnId);
-
参数
参数名称 描述 输入/输出 u32ChnId IPU通道ID 输入 -
返回值
-
MI_SUCCESS成功。
-
非MI_SUCCESS失败,参照错误码。
-
-
依赖
-
头文件:mi_ipu.h
-
库文件:libmi_ipu.so
-
-
注意
- IPU最大通道数为48。
-
举例
MI_IPU_DestroyCHN(u32ChnId);
2.6. MI_IPU_GetInOutTensorDesc¶
-
描述
获取指定通道的网络模型输入输出信息。
-
语法
MI_S32 MI_IPU_GetInOutTensorDesc(MI_IPU_CHN u32ChnId,MI_IPU_SubNet_InputOutputDesc_t *pstDesc);
-
参数
参数名称 描述 输入/输出 u32ChnId IPU通道ID 输入 pstDesc 网络描述结构体指针 输出 -
返回值
-
MI_SUCCESS成功。
-
非MI_SUCCESS失败,参照错误码。
-
-
依赖
-
头文件:mi_ipu.h
-
库文件:libmi_ipu.so
-
-
注意
- IPU最大通道数为48。
-
举例
MI_IPU_SubNet_InputOutputDesc_t desc; s32Ret = MI_IPU_GetInOutTensorDesc(u32ChnId, &desc); if (s32Ret) { printf("fail to get network description\n"); MI_IPU_DestroyCHN(u32ChnId); MI_IPU_DestroyDevice(); return s32Ret; } else { int iNum = desc.astMI_InputTensorDescs[0].u32TensorShape[0]; int iResizeH = desc.astMI_InputTensorDescs[0].u32TensorShape[1]; int iResizeW = desc.astMI_InputTensorDescs[0].u32TensorShape[2]; int iResizeC = desc.astMI_InputTensorDescs[0].u32TensorShape[3]; unsigned char *pu8ImageData = new unsigned char[iNum*iResizeH*iResizeW*iResizeC]; ... }
2.7. MI_IPU_GetInputTensors¶
-
描述
从指定通道获取输入Tensor Buffer。
-
语法
MI_S32 MI_IPU_GetInputTensors(MI_IPU_CHN u32ChnId,MI_IPU_TensorVector_t *pstInputTensorVector);
-
参数
参数名称 描述 输入/输出 u32ChnId IPU通道ID 输入 pstInputTensorVector 输入IPU Tensor数组结构体指针 输出 -
返回值
-
MI_SUCCESS成功。
-
非MI_SUCCESS失败,参照错误码。
-
-
依赖
-
头文件:mi_ipu.h
-
库文件:libmi_ipu.so
-
-
注意
-
输入Tensor的Buffer来源有2种方式:
-
通过MI_IPU_GetInputTensors分配Buffer;
-
使用MI的其他模块已分配的Buffer。
-
-
-
举例
通过MI_IPU_GetInputTensors分配buffer:
MI_IPU_TensorVector_t inputV; MI_IPU_TensorVector_t OutputV; MI_U8 au8MaggiePic[3*224*224] ; cv::Mat img = cv::imread(filename, -1); cv::Size inputSize = cv::Size(224,224,3) cv ::Mat imgResize ; cv::resize(img, imgResize, inputSize); memcpy(au8MaggiePic, imgResize.data, sizeof(au8MaggiePic)); s32Ret = MI_IPU_GetInputTensors(u32ChnId, &inputV); if (s32Ret == MI_SUCCESS) { memcpy(inputV.astArrayTensors[0].ptTensorData[0], au8MaggiePic, sizeof(au8MaggiePic)); MI_SYS_FlushInvCache(inputV.astArrayTensors[0].ptTensorData[0], sizeof(au8MaggiePic)); } else { printf(“fail to get buffer, please try again”); } MI_IPU_GetOutputTensors( u32ChannelID, &OutputV); if(MI_SUCCESS!=MI_IPU_Invoke(u32ChannelID, & inputV, &OutputV)) { cout<<"IPU invoke failed!!"<<endl; MI_IPU_DestroyCHN(u32ChannelID); MI_IPU_DestroyDevice(); return -1; }
使用MI其他模块已经分配的buffer
MI_IPU_TensorVector_t inputVector, outputVector; inputVector.u32TensorCount = 1; if (stBufInfo.eBufType == E_MI_SYS_BUFDATA_RAW) { inputVector.astArrayTensors[0].phyTensorAddr[0] = stBufInfo.stRawData.phyAddr; inputVector.astArrayTensors[0].ptTensorData[0] = stBufInfo.stRawData.pVirAddr; } else if (stBufInfo.eBufType == E_MI_SYS_BUFDATA_FRAME) { inputVector.astArrayTensors[0].phyTensorAddr[0] = stBufInfo.stFrameData.phyAddr[0]; inputVector.astArrayTensors[0].ptTensorData[0] = stBufInfo.stFrameData.pVirAddr[0]; inputVector.astArrayTensors[0].phyTensorAddr[1] = stBufInfo.stFrameData.phyAddr[1]; inputVector.astArrayTensors[0].ptTensorData[1] = stBufInfo.stFrameData.pVirAddr[1]; } //prepare output vector s32Ret = MI_IPU_GetOutputTensors(FdaChn, &outputVector); s32Ret = MI_IPU_Invoke(FdaChn, &inputVector, &outputVector);
2.8. MI_IPU_PutInputTensors¶
-
功能
释放指定通道的输入Tensor Buffer。
-
语法
MI_S32 MI_IPU_PutInputTensors(MI_IPU_CHN u32ChnId,MI_IPU_TensorVector_t *pstInputTensorVector);
-
形参
参数名称 描述 输入/输出 u32ChnId IPU通道号 输入 pstInputTensorVector 输入IPU Tensor数组结构体指针 输入 -
返回值
-
MI_SUCCESS成功。
-
非MI_SUCCESS失败,参照错误码。
-
-
依赖
-
头文件:mi_ipu.h
-
库文件:libmi_ipu.so
-
2.9. MI_IPU_GetOutputTensors¶
-
功能
从指定通道获取输出Tensor Buffer。
-
语法
MI_S32 MI_IPU_GetOutputTensors(MI_IPU_CHN u32ChnId,MI_IPU_TensorVector_t *pstInputTensorVector);
-
形参
参数名称 描述 输入/输出 u32ChnId IPU通道ID 输入 pstInputTensorVector 输出IPU Tensor数组结构体指针 输出 -
返回值
-
MI_SUCCESS成功。
-
非MI_SUCCESS失败,参照错误码。
-
-
依赖
-
头文件:mi_ipu.h
-
库文件:libmi_ipu.so
-
-
举例
MI_IPU_TensorVector_t outputV; s32Ret = MI_IPU_GetOutputTensors(u32ChnId, &outputV); if (s32Ret != MI_SUCCESS) { printf(“fail to get buffer, please try again”); }
2.10. MI_IPU_PutOutputTensors¶
-
功能
释放指定通道的输出Tensor Buffer。
-
语法
MI_S32 MI_IPU_PutOutputTensors(MI_IPU_CHN u32ChnId,MI_IPU_TensorVector_t *pstInputTensorVector);
-
形参
参数名称 描述 输入/输出 u32ChnId IPU通道ID 输入 pstInputTensorVector 输出IPU Tensor数组结构体指针 输入 -
返回值
-
MI_SUCCESS成功。
-
非MI_SUCCESS失败,参照错误码。
-
-
依赖
-
头文件:mi_ipu.h
-
库文件:libmi_ipu.so
-
2.11. MI_IPU_Invoke¶
-
功能
执行一次AI网络推演过程。
-
语法
MI_S32 MI_IPU_Invoke(MI_IPU_CHN u32ChnId,MI_IPU_TensorVector_t *pstInputTensorVector,MI_IPU_TensorVector_t *pstOuputTensorVector);
-
形参
参数名称 描述 输入/输出 u32ChnId IPU通道ID 输入 pstInputTensorVector 输入IPU Tensor数组结构体指针 输入 pstOuputTensorVector 输出IPU Tensor数组结构体指针 输入 -
返回值
-
MI_SUCCESS成功。
-
非MI_SUCCESS失败,参照错误码。
-
-
依赖
-
头文件:mi_ipu.h
-
库文件:libmi_ipu.so
-
-
注意
-
MI_IPU_Invoke为同步API。
-
每一个输入/输出tensor的起始物理地址必须64 bytes 对齐。
-
-
举例
s32Ret =MI_IPU_Invoke(u32ChnId, &inputV, &outputV); if (s32Ret == MI_SUCCESS) { // process output buffer data // ... }
2.12. MI_IPU_GetInputTensors2¶
-
功能
从指定通道获取批处理输入Tensor Buffer
-
语法
MI_S32 MI_IPU_GetInputTensors2(MI_IPU_CHN u32ChnId, MI_IPU_BatchInvoke_param_t *pstInvokeParam);
-
形参
参数名称 描述 输入/输出 u32ChnId IPU通道ID 输入 pstInvokeParam 批处理参数结构体指针 输入 -
返回值
-
MI_SUCCESS成功。
-
非MI_SUCCESS失败,参照错误码。
-
-
依赖
-
头文件:mi_ipu.h
-
库文件:libmi_ipu.so
-
-
注意
输入Tensor的Buffer来源有2种方式:
-
通过MI_IPU_GetInputTensors2分配Buffer;
-
使用MI的其他模块已分配的Buffer。
-
2.13. MI_IPU_PutInputTensors2¶
-
功能
释放指定通道的批处理输入Tensor Buffer。
-
语法
MI_S32 MI_IPU_PutInputTensors2(MI_IPU_CHN u32ChnId, MI_IPU_BatchInvoke_param_t *pstInvokeParam);
-
形参
参数名称 描述 输入/输出 u32ChnId IPU通道ID 输入 pstInvokeParam 批处理参数结构体指针 输入 -
返回值
-
MI_SUCCESS成功。
-
非MI_SUCCESS失败,参照错误码。
-
-
依赖
-
头文件:mi_ipu.h
-
库文件:libmi_ipu.so
-
2.14. MI_IPU_GetOutputTensors2¶
-
功能
从指定通道获取批处理输出Tensor Buffer。
-
语法
MI_S32 MI_IPU_GetOutputTensors2(MI_IPU_CHN u32ChnId, MI_IPU_BatchInvoke_param_t *pstInvokeParam);
-
形参
参数名称 描述 输入/输出 u32ChnId IPU通道ID 输入 pstInvokeParam 批处理参数结构体指针 输入 -
返回值
-
MI_SUCCESS成功。
-
非MI_SUCCESS失败,参照错误码。
-
-
依赖
-
头文件:mi_ipu.h
-
库文件:libmi_ipu.so
-
2.15. MI_IPU_PutOutputTensors2¶
-
功能
释放指定通道的批处理输出Tensor Buffer。
-
语法
MI_S32 MI_IPU_PutOutputTensors2(MI_IPU_CHN u32ChnId, MI_IPU_BatchInvoke_param_t *pstInvokeParam);
-
形参
参数名称 描述 输入/输出 u32ChnId IPU通道ID 输入 pstInvokeParam 批处理参数结构体指针 输入 -
返回值
-
MI_SUCCESS成功。
-
非MI_SUCCESS失败,参照错误码。
-
-
依赖
-
头文件:mi_ipu.h
-
库文件:libmi_ipu.so
-
2.16. MI_IPU_Invoke2¶
-
功能
执行一次n_buf batch模式网络模型推演。
-
语法
MI_S32 MI_IPU_Invoke2(MI_IPU_CHN u32ChnId, MI_IPU_BatchInvoke_param_t *pstInvokeParam, MI_IPU_RuntimeInfo_t *pstRuntimeInfo);
-
形参
参数名称 描述 输入/输出 u32ChnId IPU通道ID 输入 pstInvokeParam 批处理参数结构体指针 输入 pstRuntimeInfo IPU运行信息结构体指针 输入 -
返回值
-
MI_SUCCESS成功。
-
非MI_SUCCESS失败,参照错误码。
-
-
依赖
-
头文件:mi_ipu.h
-
库文件:libmi_ipu.so
-
-
注意
-
MI_IPU_Invoke2为同步API。
-
MI_IPU_Invoke2只能推理n_buf batch模式的模型。
-
每一个输入/输出tensor的起始物理地址必须64 bytes 对齐。
-
用户指定的variable buffer的起始物理地址必须64 bytes 对齐。
-
-
举例
MI_IPU_BatchInvoke_param_t stInvokeParam; MI_IPU_RuntimeInfo_t stRuntimeInfo; stInvokeParam.u32BatchN = 16; stInvokeParam.s32TaskPrio = 20; stInvokeParam.u32IpuAffinity = 0; //由ipu调度 s32Ret = MI_IPU_GetInputTensors2(u32ChnId, &stInvokeParam); if (s32Ret != MI_SUCCESS) { printf(“Error: MI_IPU_GetInputTensors2 return %d\n”, s32Ret); return -1; } s32Ret = MI_IPU_GetOutputTensors2(u32ChnId, &stInvokeParam); if (s32Ret != MI_SUCCESS) { printf(“Error: MI_IPU_ GetOutputTensors2 return %d\n”, s32Ret); MI_IPU_PutInputTensors2(u32ChnId, &stInvokeParam); return -1; } s32Ret = MI_IPU_Invoke2(u32ChnId, &stInvokeParam, &stRuntimeInfo); if (s32Ret == MI_SUCCESS) { // process output buffer data // ... printf(“bw_total=%llu, bw_read=%llu, bw_read=%llu, iputime=%llu\n”, stRuntimeInfo.u64BandWidth, stRuntimeInfo.u64BandWidthRead, stRuntimeInfo.u64BandWidthWrite, stRuntimeInfo.u64IpuTime); }
2.17. MI_IPU_Invoke2Custom¶
-
功能
执行一次one_buf batch模式网络模型推演。
-
语法
MI_S32 MI_IPU_Invoke2Custom(MI_IPU_CHN u32ChnId, MI_IPU_BatchInvoke_param_t *pstInvokeParam, MI_IPU_RuntimeInfo_t *pstRuntimeInfo);
-
形参
参数名称 描述 输入/输出 u32ChnId IPU通道ID 输入 pstInvokeParam 批处理参数结构体指针 输入 pstRuntimeInfo IPU运行信息结构体指针 输入 -
返回值
-
MI_SUCCESS成功。
-
非MI_SUCCESS失败,参照错误码。
-
-
依赖
-
头文件:mi_ipu.h
-
库文件:libmi_ipu.so
-
-
注意
-
MI_IPU_Invoke2Custom为同步API。
-
MI_IPU_Invoke2Custom只能推理one_buf batch模式模型。
-
每一个输入/输出tensor的起始物理地址必须64 bytes 对齐。
-
用户指定的variable buffer的起始物理地址必须64 bytes 对齐。
-
-
举例
// input tensor number=1 output tensor number=1 MI_IPU_BatchInvoke_param_t stInvokeParam; MI_IPU_RuntimeInfo_t stRuntimeInfo; stInvokeParam.u32BatchN = 10; stInvokeParam.s32TaskPrio = 20; stInvokeParam.u32IpuAffinity = 0; //由ipu调度 int s32InputSize, s32InputSizeOne; s32InputSizeOne = stDesc.astMI_InputTensorDescs[0].u32BufSize; s32InputSize = s32InputSizeOne * stInvokeParam.u32BatchN; int s32OutputSize, s32OutputSizeOne; s32OutputSizeOne = stDesc.astMI_OutputTensorDescs[0].u32BufSize; s32OutputSize = s32OutputSizeOne * stInvokeParam.u32BatchN; s32Ret = MI_SYS_MMA_Alloc(0, NULL, s32InputSize, &u64InputPhyAddr); if (s32Ret != MI_SUCCESS) { printf("fail to allocate input buffer\n"); return -1; } s32Ret = MI_SYS_Mmap(u64InputPhyAddr, s32InputSize, &pInputVirAddr, TRUE); if (s32Ret != MI_SUCCESS) { MI_SYS_MMA_Free(0, u64InputPhyAddr); printf("Error: fail to map input address, error=%d\n", s32Ret); return -1; } stInvokeParam.astArrayTensors[0].ptTensorData[0] = pInputVirAddr; stInvokeParam.astArrayTensors[0].phyTensorAddr[0] = u64InputPhyAddr; s32Ret = MI_SYS_MMA_Alloc(0, NULL, s32OutputSize, &u64OutputPhyAddr); if (s32Ret != MI_SUCCESS) { MI_SYS_Munmap(pInputVirAddr, s32InputSize); MI_SYS_MMA_Free(0, u64InputPhyAddr); printf("fail to allocate output buffer\n"); return -1; } s32Ret = MI_SYS_Mmap(u64OutputPhyAddr, s32OutputSize, &pOutputVirAddr, TRUE); if (s32Ret != MI_SUCCESS) { MI_SYS_Munmap(pInputVirAddr, s32InputSize); MI_SYS_MMA_Free(0, u64InputPhyAddr); MI_SYS_MMA_Free(0, u64OutputPhyAddr); printf("Error: fail to map output address, error=%d\n", s32Ret); return -1; } stInvokeParam.astArrayTensors[1].ptTensorData[0] = pOutputVirAddr; stInvokeParam.astArrayTensors[1].phyTensorAddr[0] = u64OutputPhyAddr; for (int i = 0; i < stInvokeParam.u32BatchN; i++) { memcpy(pInputVirAddr+i*s32InputSizeOne; pInputBuf[i], s32InputSizeOne); } MI_SYS_FlushInvCache(pInputVirAddr, s32InputSize); s32Ret = MI_IPU_Invoke2Custom(channel, &stInvokeParam, NULL); if (s32Ret != MI_SUCCESS) { printf("fail to invoke\n"); MI_SYS_Munmap(pInputVirAddr, s32InputSize); MI_SYS_MMA_Free(0, u64InputPhyAddr); MI_SYS_Munmap(pOutputVirAddr, s32OutputSize); MI_SYS_MMA_Free(0, u64OutputPhyAddr); return -1; } else { // process output data for (int i = 0; i < stInvokeParam.u32BatchN; i++) { // pOutputVirAddr+i*s32OutputSizeOne } }
2.18. MI_IPU_GetOfflineModeStaticInfo¶
-
功能
获取离线模型运行需要的variable buffer size和离线模型文件大小
-
语法
MI_S32 MI_IPU_GetOfflineModeStaticInfo(SerializedReadFunc pReadFunc, char *pReadCtx, MI_IPU_OfflineModelStaticInfo_t *pStaticInfo);
-
形参
参数名称 描述 输入/输出 pReadFunc 用户自定义读取文件函数(设为NULL默认使用MI IPU提供的文件读取函数 输入 pReadCtx 离线模型文件路径 输入 pStaticInfo 离线模型静态信息结构体指针 输入 -
返回值
-
MI_SUCCESS成功。
-
非MI_SUCCESS失败,参照错误码。
-
-
依赖
-
头文件:mi_ipu.h
-
库文件:libmi_ipu.so
-
-
举例
MI_IPU_OfflineModelStaticInfo_t staticInfo; s32Ret = MI_IPU_GetOfflineModeStaticInfo(NULL, pModelImgPath, &staticInfo); if (s32Ret == MI_SUCCESS) { printf("variable buffer size: %u bytes\n%s size: %u bytes\n", staticInfo.u32VariableBufferSize, pModelImgPath, staticInfo.u32OfflineModelSize); }
2.19. MI_IPU_CancelInvoke¶
-
功能
取消正在执行的Invoke任务
-
语法
MI_S32 MI_IPU_CancelInvoke(MI_U32 u32ThreadId, MI_IPU_CHN u32ChnId);
-
形参
参数名称 描述 输入/输出 u32ThreadId 指定取消的invoke任务所属的线程ID 输入 u32ChnId 指定取消的invoke任务所属的通道ID 输入 -
返回值
- MI_SUCCESS成功。
- 非MI_SUCCESS失败,参照错误码。
-
依赖
- 头文件:mi_ipu.h
- 库文件:libmi_ipu.so
-
注意
- Cancel invoke功能只能取消本进程内的invoke任务,不能跨进程使用。
-
举例
Thread-0: s32Ret =MI_IPU_Invoke(u32ChnId, &inputV, &outputV); OR s32Ret = MI_IPU_Invoke2(u32ChnId, &stInvokeParam, &stRuntimeInfo); OR s32Ret = MI_IPU_Invoke2Custom(channel, &stInvokeParam, NULL); if (s32Ret == E_IPU_ERR_INVOKE_CANCELED) { printf("invoke has been canceled\n"); } Thread-1: s32Ret = MI_IPU_CancelInvoke(u32ThreadId, u32ChnId); if (s32Ret == MI_SUCCESS) { printf("succeed to cancel invoke task, thread id=%u, channel id=%u\n", u32ThreadId, u32ChnId); } else if (s32Ret == E_IPU_ERR_NOT_FOUND) { printf("do not find invoke task belongs to thread id=%u, channel id=%u\n", u32ThreadId, u32ChnId); } else if (s32Ret == E_IPU_ERR_NOT_SUPPORT) { printf("do not support cancel invoke on this platform\n"); } else { printf("unexpected error=%d\n", s32Ret); }
2.20. MI_IPU_CreateCHNWithUserMem¶
-
功能
使用用户提供的MMA内存创建IPU通道。
-
语法
MI_S32 MI_IPU_CreateCHNWithUserMem(MI_IPU_CHN *ptChnId, MI_IPUChnAttr_t *pstChnAttr, MI_PHY u64ModelPA);
-
参数
参数名称 描述 输入/输出 ptChnId 获取IPU通道ID的指针 输出 pstIPUChnAttr IPU通道描述信息结构体指针 输入 u64ModelPA 存放网络模型文件的MMA内存 输入 -
返回值
-
MI_SUCCESS成功。
-
非MI_SUCCESS失败,参照错误码。
-
-
依赖
-
头文件:mi_ipu.h
-
库文件:libmi_ipu.so
-
-
注意
- MI_IPUChnAttr_t.u32BatchMax 为批处理的最大值,如果这个模型不需要使用批处理,则将该值设置为1或者0。
- MI_IPUChnAttr_t.u32InputBufDepth 为设定的输入预分配私有tensor buffer* u32BatchMax的个数,比如 0 or 1 or 2 or 3, 当设置为0时,表示buffer来源于外部。如果直接使用前级模块的输出MI buffer,建议此处设置input_depth为0避免内存浪费。
- MI_IPUChnAttr_t. u32OutputBufDepth为设定的输出预分配私有tensor buffer* u32BatchMax的个数, 比如 0 or 1 or 2 or 3,当设置为0时,表示buffer来源于外部,如MI_RGN模块。
- 如果创建的是one_buf batch模式网络模型,则不会预分配输入和输出buffer。
- IPU最大通道数为48。
- 只有在调用MI_IPU_DestroyCHN后才能释放u64ModelPA
-
举例
MI_S32 s32Ret, buf_depth = 3, batch_max = 1; MI_IPU_CHN u32ChnId = 0; MI_IPUChnAttr_t chnAttr; MI_S32 fd, s32ModelSize; MI_U64 u64ModelPA = 0; void *pmem = NULL; void *pModelVA = NULL; char *pModelPath = "caffe_mobilenet_v2.tflite_sgsimg.img"; chnAttr.u32InputBufDepth = buf_depth; chnAttr.u32OutputBufDepth = buf_depth; chnAttr.u32BatchMax = batch_max; fd = open(pModelPath, O_RDONLY); if (fd < 0) { perror("Fail to open model!\n"); return -1; } s32ModelSize = lseek(fd, 0, SEEK_END); pmem = mmap(NULL, s32ModelSize, PROT_READ, MAP_SHARED, fd, 0); if (pmem == MAP_FAILED) { perror("mmap"); close(fd); return -1; } s32Ret = MI_SYS_MMA_Alloc(0, NULL, s32ModelSize, &u64ModelPA); if (s32Ret != MI_SUCCESS) { printf("fail to allocate model buf!\n"); munmap(pmem, s32ModelSize); close(fd); return s32Ret; } s32Ret = MI_SYS_Mmap(u64ModelPA, s32ModelSize, &pModelVA, TRUE); if (s32Ret != MI_SUCCESS) { printf("fail to mmap"); MI_SYS_MMA_Free(0, u64PhyAddr); munmap(pmem, s32ModelSize); close(fd); return s32Ret; } memcpy(pModelVA, pmem, s32ModelSize); MI_SYS_FlushInvCache(pModelVA, s32ModelSize); s32Ret = MI_IPU_CreateCHNWithUserMem(&u32ChnId, &chnAttr, u64ModelPA); if (s32Ret != MI_SUCCESS) { printf("fail to create ipu channel\n"); MI_SYS_Munmap(pModelVA, s32ModelSize); MI_SYS_MMA_Free(0, u64PhyAddr); munmap(pmem, s32ModelSize); close(fd); return s32Ret; }
2.21. MI_IPU_DestroyDeviceExt¶
-
功能
使用参数销毁IPU设备。
-
语法
MI_S32 MI_IPU_DestroyDeviceExt(MI_IPU_DevAttr_t *pstIPUDevAttr);
-
返回值
-
MI_SUCCESS成功。
-
非MI_SUCCESS失败,参照错误码。
-
-
依赖
-
头文件:mi_ipu.h
-
库文件:libmi_ipu.so
-
-
举例
MI_S32 s32Ret; MI_IPU_DevAttr_t stDevAttr; stDevAttr.u32MaxVariableBufSize = BufSize; /*模型内部Tensor使用的memory的最大size*/ stDevAttr.u32VariableGroup = 0; stDevAttr.u32CoreMask = IPU_DEV_0; s32Ret = MI_IPU_CreateDevice(&stDevAttr, NULL, NULL, 0); if (s32Ret != MI_SUCCESS) { printf("fail to create ipu device\n"); return s32Ret; } ... MI_IPU_DestroyDeviceExt(&stDevAttr);
3. 数据类型¶
3.1. 数据类型定义¶
数据类型 | 定义 |
---|---|
SerializedReadFunc | 定义用于客制化的读取文件方式,用于支持客制化的AI网络存储格式 |
MI_IPU_ELEMENT_FORMAT | 定义IPU输入数据枚举类型 |
MI_IPU_BatchMode_e | 定义IPU batch buffer模式枚举类型 |
MI_IPU_LayoutType_e | 定义tensor的排布枚举类型 |
MI_IPU_IpuWorkMode_e | 定义IPU模型的工作模式枚举类型 |
MI_IPU_TensorDesc_t | 定义IPU Tensor形状结构体 |
MI_IPU_SubNet_InputOutputDesc_t | 定义IPU子网络输入/输出描述结构体 |
MI_IPU_Tensor_t | 定义IPU Tensor地址结构体 |
MI_IPU_TensorVector_t | 定义IPU Tensor数组结构体指针 |
MI_IPU_DevAttr_t | 定义IPU设备属性结构体 |
MI_IPU_ChnAttr_t | 定义IPU通道属性结构体 |
MI_IPU_BatchInvoke_param_t | 定义批处理参数结构体 |
MI_IPU_RuntimeInfo_t | 定义IPU运行信息结构体 |
MI_IPU_OfflineModelStaticInfo_t | 定义IPU离线模型静态信息结构体 |
3.2. SerializedReadFunc¶
-
说明
定义用于客制化的读取文件方式,用于支持客制化的AI网络存储格式。
-
语法
typedef int (*SerializedReadFunc)(void *dst_buf,int offset, int size, char *ctx);
-
成员
成员名称 描述 dst_buf 数据存放地址 offset 文件指针偏移量 size 读取大小 ctx 文件路径
3.3. MI_IPU_ELEMENT_FORMAT¶
-
说明
定义IPU输入数据枚举类型。
-
语法
typedef enum { MI_IPU_FORMAT_U8, MI_IPU_FORMAT_NV12, MI_IPU_FORMAT_INT16, MI_IPU_FORMAT_INT32, MI_IPU_FORMAT_INT8, MI_IPU_FORMAT_FP32, MI_IPU_FORMAT_UNKNOWN, MI_IPU_FORMAT_ARGB8888, MI_IPU_FORMAT_ABGR8888, MI_IPU_FORMAT_GRAY, MI_IPU_FORMAT_COMPLEX64, } MI_IPU_ELEMENT_FORMAT;
-
成员
成员名称 描述 MI_IPU_FORMAT_U8 U8类型 MI_IPU_FORMAT_NV12 NV12类型,如YUV MI_IPU_FORMAT_INT16 INT16类型 MI_IPU_FORMAT_INT32 INT32类型 MI_IPU_FORMAT_INT8 INT8类型 MI_IPU_FORMAT_FP32 FLOAT类型 MI_IPU_FORMAT_UNKNOWN Unknown MI_IPU_FORMAT_ARGB8888 ARGB8888类型 MI_IPU_FORMAT_ABGR8888 ABGR8888类型 MI_IPU_FORMAT_GRAY GRAY类型 MI_IPU_FORMAT_COMPLEX64 COMPLEX64 类型 -
注意事项
-
ARGB/RGB/BGR tensor属于MI_IPU_FORMAT_U8数据类型
-
只有input tensor可以支援MI_IPU_FORMAT_NV12格式
-
只有output tensor可以支援MI_IPU_FORMAT_FP32格式
-
3.4. MI_IPU_BatchMode_e¶
-
说明
定义IPU batch buffer模式枚举类型。
-
定义
typedef enum { E_IPU_BATCH_N_BUF_MODE = 0, E_IPU_BATCH_ONE_BUF_MODE, } MI_IPU_BatchMode_e;
-
成员
成员名称 描述 E_IPU_BATCH_N_BUF_MODE 模型为n_buf batch模式 E_IPU_BATCH_ONE_BUF_MODE 模型为one_buf batch模式 -
相关数据类型及接口
3.5. MI_IPU_LayoutType_e¶
-
说明
定义tensor的排布枚举类型。
-
定义
typedef enum { E_IPU_LAYOUT_TYPE_NHWC = 0, E_IPU_LAYOUT_TYPE_NCHW, } MI_IPU_LayoutType_e;
-
成员
成员名称 描述 E_IPU_LAYOUT_TYPE_NHWC 该tensor为NHWC排布 E_IPU_LAYOUT_TYPE_NCHW 该tensor为NCHW排布 -
相关数据类型及接口
3.6. MI_IPU_IpuWorkMode_e¶
-
说明
定义IPU模型的工作模式枚举类型。
-
定义
typedef enum { E_IPU_IPU_WORK_MODE_SINGLECORE = 0, E_IPU_IPU_WORK_MODE_MULTICORE, } MI_IPU_IpuWorkMode_e;
-
成员
成员名称 描述 E_IPU_IPU_WORK_MODE_SINGLECORE 模型为单核模式 E_IPU_IPU_WORK_MODE_MULTICORE 模型为多核模式 -
相关数据类型及接口
3.7. MI_IPU_TensorDesc_t¶
-
说明
定义IPU Tensor描述结构体。
-
语法
typedef struct MI_IPU_TensorDesc_s { MI_U32 u32TensorDim; MI_IPU_ELEMENT_FORMAT eElmFormat; MI_U32 u32TensorShape[MI_IPU_MAX_TENSOR_DIM]; MI_S8 name[MAX_TENSOR_NAME_LEN]; MI_U32 u32InnerMostStride; MI_FLOAT fScalar; MI_S64 s64ZeroPoint; MI_S32 s32AlignedBufSize; MI_U32 u32BufSize; MI_U32 u32InputWidthAlignment; MI_U32 u32InputHeightAlignment; MI_IPU_LayoutType_e eLayoutType; MI_U32 au32Reserve[4]; // reserved } MI_IPU_TensorDesc_t;
-
成员
成员名称 描述 u32TensorDim Tensor维度 eElmFormat Tensor数据类型 u32TensorShape Tensor形状数组 name Tensor名称 u32InnerMostStride Tensor最内维长度(单位字节) fScalar Tensor量化系数 s64ZeroPoint Tensor量化offset s32AlignedBufSize Tensor buffer对齐后的大小 u32BufSize Tensor buffer大小 u32InputWidthAlignment 输入Tensor水平方向对齐大小 u32InputHeightAlignment 输入Tensor垂直方向对齐大小 eLayoutType Tensor的排布模式 au32Reserve 预留位 -
注意事项
-
Tensor维度最大为10。建议使用如下宏定义:
#define MI_IPU_MAX_TENSOR_DIM (10)
-
输入数据必须严格按照u32InputWidthAlignment和u32InputHeightAlignment对齐,否则结果会出错。
-
数据对齐方式
input_formats 板上运行时数据对齐方式 RGB/BGR 不用对齐 RGBA/BGRA W = ALIGN_UP(W * 4, input_width_alignment) / 4
input_width_alignment默认为1YUV_NV12 H = ALIGN_UP(H, input_height_alignment)
input_height_alignment默认为2
W = ALIGN_UP(W, input_width_alignment)
input_width_alignment默认为2GRAY H = ALIGN_UP(H, input_height_alignment)
input_height_alignment默认为1
W = ALIGN_UP(W, input_width_alignment)
input_width_alignment默认为1RAWDATA_F32_NHWC 不用对齐 RAWDATA_S16_NHWC 不用对齐
-
3.8. MI_IPU_SubNet_InputOutputDesc_t¶
-
说明
定义IPU子网络输入/输出描述结构体。
-
语法
typedef struct MI_IPU_SubNet_InputOutputDesc_s { MI_U32 u32InputTensorCount; MI_U32 u32OutputTensorCount; MI_IPU_TensorDesc_t astMI_InputTensorDescs[MI_IPU_MAX_INPUT_TENSOR_CNT]; MI_IPU_TensorDesc_t astMI_OutputTensorDescs[MI_IPU_MAX_OUTPUT_TENSOR_CNT]; } MI_IPU_SubNet_InputOutputDesc_t;
-
成员
成员名称 描述 u32InputTensorCount 输入Tensor个数 u32OutputTensorCount 输出Tensor个数 astMI_InputTensorDescs 输入Tensor形状结构体数组 astMI_OutputTensorDescs 输出Tensor形状结构体数组
3.9. MI_IPU_Tensor_t¶
-
说明
定义IPU Tensor地址结构体。
-
语法
typedef struct MI_IPU_Tensor_s { void *ptTensorData[2]; MI_PHY phyTensorAddr[2];//notice that this is miu bus addr,not cpu bus addr. } MI_IPU_Tensor_t;
-
成员
成员名称 描述 ptTensorData Tensor buffer虚拟地址 phyTensorAddr Tensor buffer物理地址
3.10. MI_IPU_TensorVector_t¶
-
说明
定义IPU Tensor数组结构体。
-
语法
typedef struct MI_IPU_TensorVector_s { MI_U32 u32TensorCount; MI_IPU_Tensor_t astArrayTensors[MI_IPU_MAX_TENSOR_CNT]; } MI_IPU_TensorVector_t;
-
成员
成员名称 描述 u32TensorCount Tensor个数 astArrayTensors 每个Tensor的地址信息
3.11. MI_IPU_DevAttr_t¶
-
说明
定义IPU设备属性结构体。
-
语法
typedef struct MI_IPU_DevAttr_s { MI_U32 u32MaxVariableBufSize; MI_U32 u32YUV420_W_Pitch_Alignment; // unused MI_U32 u32YUV420_H_Pitch_Alignment; // unused MI_U32 u32XRGB_W_Pitch_Alignment; // unused MI_U32 u32VariableGroup; // variable group ID MI_U32 u32CoreMask; // ipu core mask MI_U32 au32Reserve[6]; // reserve } MI_IPU_DevAttr_t;
-
成员
成员名称 描述 u32MaxVariableBufSize 模型内部Tensor使用的memory的最大大小 u32YUV420_W_Pitch_Alignment Unused u32YUV420_H_Pitch_Alignment Unused u32XRGB_W_Pitch_Alignment Unused u32VariableGroup variable内存组ID u32CoreMask IPU核掩码 au32Reserve 预留位
3.12. MI_IPU_ChnAttr_t¶
-
说明
定义IPU通道属性结构体。
-
语法
typedef struct MI_IPU_ChnAttr_s { MI_U32 u32SubNetId; MI_U32 u32OutputBufDepth; MI_U32 u32InputBufDepth; MI_U32 u32BatchMax; MI_U32 au32Reserve[8]; // reserved } MI_IPUChnAttr_t;
-
成员
成员名称 描述 u32SubNetId 子网络ID u32OutputBufDepth 输出Tensor Buffer深度 u32InputBufDepth 输入Tensor Buffer深度 au32Reserve 预留位 -
注意事项
IPU输入/输出缓冲区最大深度为3。建议使用如下宏定义:
#define MAX_IPU_INPUT_OUTPUT_BUF_DEPTH (3)
3.13. MI_IPU_BatchInvoke_param_t¶
-
说明
定义批处理参数结构体。
-
语法
typedef struct MI_IPU_BatchInvoke_param_s { MI_PHY u64VarBufPhyAddr; MI_U32 u32VarBufSize; MI_U32 u32BatchN; MI_S32 s32TaskPrio; MI_U32 u32IpuAffinity; MI_IPU_Tensor_t astArrayTensors[MI_IPU_MAX_BATCH_TENSOR_CNT]; MI_U32 au32Reserve[8]; // reserved } MI_IPU_BatchInvoke_param_t;
-
成员
成员名称 描述 u64VarBufPhyAddr 用户指定的variable buffer物理地址 u32VarBufSize 用户指定的variable buffer大小 u32BatchN 批处理个数 s32TaskPrio 任务优先级 u32IpuAffinity 绑定ipu core astArrayTensors 批处理所有的输入输出tensor buffer地址 au32Reserve 预留位 -
注意事项
-
astArrayTensors数组存放批处理所有的输入输出tensor buffer地址,规则是先依次存入所有输入tensor buffer地址,再存入所有输出tensor buffer地址。
-
每一个输入/输出tensor的起始物理地址必须64 bytes 对齐。
-
用户指定的variable buffer的起始物理地址必须64 bytes对齐。
-
3.14. MI_IPU_RuntimeInfo_t¶
-
说明
定义IPU运行信息结构体。
-
语法
typedef struct MI_IPU_RuntimeInfo_s { MI_U64 u64BandWidth; MI_U64 u64IpuTime; MI_U64 u64BandWidthRead; MI_U64 u64BandWidthWrite; MI_U32 au32Reserve[8]; // reserved } MI_IPU_RuntimeInfo_t;
-
成员
成员名称 描述 u64BandWidth 带宽数据总量 (bytes) u64IpuTime IPU处理时间 (us) u64BandWidthRead 带宽数据读总量 (bytes) u64BandWidthWrite 带宽数据写总量 (bytes) au32Reserve 预留位
3.15. MI_IPU_OfflineModelStaticInfo_t¶
-
说明
定义IPU离线模型静态信息结构体。
-
语法
typedef struct MI_IPU_OfflineModelStaticInfo_s { MI_U32 u32VariableBufferSize; MI_U32 u32OfflineModelSize; MI_IPU_BatchMode_e eBatchMode; MI_U32 u32TotalBatchNumTypes; MI_U32 au32BatchNumTypes[MI_IPU_MAX_BATCH_TYPE_NUM]; MI_IPU_IpuWorkMode_e eIpuWorkMode; MI_U32 au32Reserve[8]; // reserved } MI_IPU_OfflineModelStaticInfo_t;
-
成员
成员名称 描述 u32VariableBufferSize 离线模型运行需要的variable buffer size u32OfflineModelSize 离线模型文件大小 eBatchMode 离线模型batch buffer模式 u32TotalBatchNumTypes 离线模型所支持的batch数的种类个数 au32BatchNumTypes n_buf模式:离线模型板端运行所能够支持的最大batch数以及batch数推荐值的最大值
one_buf模式:离线模型板端运行所能够支持的batch数的种类eIpuWorkMode 离线模型的工作模式 au32Reserve 预留位 -
注意事项
-
如果模型的eBatchMode为E_IPU_BATCH_N_BUF_MODE:
u32TotalBatchNumTypes将会返回2。
au32BatchNumTypes[0]将会返回该离线模型板端运行所能够支持的最大batch数。
au32BatchNumTypes[1]将会返回该离线模型板端运行的推荐batch数中的最大值。(推荐batch数将是2的n次幂,当au32BatchNumTypes[1] = 2n,代表该模型的推荐batch数为20, 21, ..., 2(n-1), 2n)。
Ex:
au32BatchNumTypes[0]返回128,则可以支持1~128个batches。
au32BatchNumTypes[1]返回8,则该模型的推荐batch数为1, 2, 4, 8。
-
如果模型的eBatchMode为E_IPU_BATCH_ONE_BUF_MODE:
u32TotalBatchNumTypes将会返回离线模型板端运行所能够支持的batch数的种类的个数。
au32BatchNumTypes[0] ~ au32BatchNumTypes[u32TotalBatchNumTypes - 1]将会返回离线模型板端运行所能够支持的batch数的种类。
Ex:
u32TotalBatchNumTypes==3
au32BatchNumTypes[0]==10
au32BatchNumTypes[1]==20
au32BatchNumTypes[2]==30
则可以支持10、20、30这三种batch数。
-
4. 错误码¶
表4-1 IPU API错误码
错误代码 | 宏定义 | 描述 |
---|---|---|
0 | MI_SUCCESS | Success |
1 | E_IPU_ERR_INVALID_CHNID | Invlalid channel ID |
2 | E_IPU_ERR_CHNID_EXIST | Channel already exists |
3 | E_IPU_ERR_CHNID_UNEXIST | Channel does not exist |
4 | E_IPU_ERR_NOMEM | Failure caused by malloc memory |
5 | E_IPU_ERR_NOBUF | Failure caused by malloc buffer |
6 | E_IPU_ERR_BADADDR | Bad address, buffer address is not gotten from IPU buffer allocator |
7 | E_IPU_ERR_SYS_TIMEOUT | System timeout |
8 | E_IPU_ERR_FILE_OPERATION | File cannot be opened or read or written |
9 | E_IPU_ERR_ILLEGAL_TENSOR_BUFFER_SIZE | Tensor buffer size does not meet the requirement, usually less than the requirement |
10 | E_IPU_ERR_ILLEGAL_BUFFER_DEPTH | Input or output buffer depth quantum exceeds maximum number |
11 | E_IPU_ERR_ILLEGAL_INPUT_OUTPUT_DESC | Network description is illegal, usually input or output buffer quantum is wrong |
12 | E_IPU_ERR_ILLEGAL_INPUT_OUTPUT_PARAM | Uer's input or output buffer quantum does not match network description |
13 | E_IPU_ERR_MAP | Address mapping error |
14 | E_IPU_ERR_INIT_FIRMWARE | Fail to initialize IPU firmware |
15 | E_IPU_ERR_CREATE_CHANNEL | Fail to create channel |
16 | E_IPU_ERR_DESTROY_CHANNEL | Fail to destroy channel |
17 | E_IPU_ERR_INVOKE | Fail to invoke |
18 | E_IPU_ERR_SET_MALLOC_REGION | Fail to set malloc region for freertos |
19 | E_IPU_ERR_SET_IPU_PARAMETER | Fail to set IPU parameter |
20 | E_IPU_ERR_INVALID_PITCH_ALIGNMENT | Invalid pitch alignment |
21 | E_IPU_ERR_NO_CREATED_IPU_DEVICE | There is no created IPU device |
22 | E_IPU_ERR_GET_IPU_VERSION | Fail to get IPU version from IPU firmware |
23 | E_IPU_ERR_MISMATCH_IPU_HEAD_FILE | IPU head files version not matched |
24 | E_IPU_ERR_NO_SUPPORT_REQ | IPU firmware does not support this request |
25 | E_IPU_ERR_FAILED | Unexpected error |
26 | E_IPU_ERR_SEND_REQUEST | Fail to send request to IPU |
27 | E_IPU_ERR_GET_FIRMWARE_INFO | Fail to get ipu firmware information |
28 | E_IPU_ERR_INVALID_IPUCORE_BOOTING_PARAM | Invalid IPU cores booting parameters |
29 | E_IPU_ERR_INVALID_IPUCORE_SHUTDOWNING_PARAM | Invalid IPU cores shutdowning parameters |
30 | E_IPU_ERR_NO_MULTICORE_ENV | Multicore mode needs all ipu cores being alive |
31 | E_IPU_ERR_INVALID_TASK_PRIORITY | Invalid ipu task priority |
32 | E_IPU_ERR_DEV_SHUTDOWN | Ipu core has been shutdown |
33 | E_IPU_ERR_DEV_FAIL_RESET | Fail to reset ipu |
34 | E_IPU_ERR_DEV_FAIL_SHUTDOWN | Fail to shutdown ipu |
35 | E_IPU_ERR_NO_AVAILABLE_DEV | No available ipu dev |
36 | E_IPU_ERR_RESET_OFF | Reset function is off |
37 | E_IPU_ERR_INVALID_BATCH_NUM | batch number error |
38 | E_IPU_ERR_BATCH_TYPE | batch type error |
39 | E_IPU_ERR_BATCH_MODE | batch mode error |
40 | E_IPU_ERR_NO_AVAILABLE_BATCH_MODE | do not find available batch mode |
41 | E_IPU_ERR_IPU_HANG | invoke was dropped due to ipu hang |
42 | E_IPU_ERR_NO_RESET_DEV | no reset ipu dev |
43 | E_IPU_ERR_NO_BATCH_PARAM | no batch parameter |
44 | E_IPU_ERR_INVALID_MODEL_BUFFER | invalid user model buffer physical address or size |
45 | E_IPU_ERR_INVALID_VARIABLE_BUFFER | invalid variable buffer physical address or size |
46 | E_IPU_ERR_NOT_ASSIGN_CORE | not assign ipu core when use user's variable buffer |
47 | E_IPU_ERR_SWDISP_NOT_REGISTER | model has unsupported swdisp function |
48 | E_IPU_ERR_SWDISP_NOT_FIND_TASKID | not find swdisp task id |
49 | E_IPU_ERR_SWDISP_INVALID_PARAM | invalid swdisp parameter |
50 | E_IPU_ERR_SWDISP_UNEXPECTED | unexpected swdisp error |
51 | E_IPU_ERR_SWDISP_UNKNOWN | unknown swdisp error |
52 | E_IPU_ERR_BAD_PHY_ADDR_ALIGNMENT | ipu buffer physical addr not aligned |
53 | E_IPU_ERR_MISMATCH_INVOKE_FUNC | n_buf/one_buf batch model should use MI_IPU_Invoke2/MI_IPU_Invoke2Custom |
54 | E_IPU_ERR_MISMATCH_MODEL | other platform's model |
55 | E_IPU_ERR_INVOKE_CANCELED | invoke has been canceled |
56 | E_IPU_ERR_INVOKE_CANCEL_FAIL | fail to cancel invoke |
57 | E_IPU_ERR_NOT_SUPPORT_CANCELINVOKE | do not support cancel invoke |
58 | E_IPU_ERR_PERMISSION_DENIED | permission denied |
59 | E_IPU_ERR_INVOKE_INTERRUPT | invoke task was interrupted (maybe on suspend), please try again |
256 | E_IPU_ERR_NO_AVAILABLE_CHNID | There is no available channel |
5. PROCFS介绍¶
5.1. 概述¶
通过控制台debug IPU的方式是procfs。
-
IPU Procfs在open device(mi_dev)的时候创建节点
proc/mi_modules/mi_ipu/mi_ipu0
,close device的时候删除节点。 -
IPU Procfs在insmod ko的时候创建节点
/proc/mi_modules/mi_ipu/debug_hal/xxx
。
5.2. 如何看MMA信息¶
# cat /proc/mi_modules/mi_sys/mi_sys0
可以看到所有MMA的使用情况。
# cat /proc/mi_modules/mi_ipu/mi_ipu0
可以看IPU的device和各channel使用MMA的情况。
5.3. 查看IPU version信息¶
# cat /proc/mi_modules/mi_ipu/debug_hal/version
5.4. 查看IPU clock信息¶
# cat /proc/mi_modules/mi_ipu/debug_hal/freq
5.5. 调节IPU clock¶
# echo xxx > /proc/mi_modules/mi_ipu/debug_hal/freq *(XXX必须是available frequency)*
5.6. 开关auto reset功能¶
Auto reset功能可以在IPU无响应后reset IPU,继续未完成的任务。
打开auto reset功能:echo on > /proc/mi_modules/mi_ipu/debug_hal/auto_reset
关闭auto reset功能:echo off > /proc/mi_modules/mi_ipu/debug_hal/auto_reset
前期测试阶段,建议关闭auto reset功能,理清IPU无响应的原因。
5.7. 抓取IPU log¶
# echo “ctrl_size=0x800000 corectrl_size=0x800000 ctrl=0xffffff corectrl=0x1fff” > /proc/mi_modules/mi_ipu/debug_hal/ipu_log
ctrl_size和corectrl_size是为ctrl log和corectrl log分配buffer的大小,ctrl和corectrl是ctrl log和corectrl log的配置。