切换版块
×
基础软件平台
PyTorch开发
TensorFlow开发
编解码及SDK开发
BANG语言与计算库
开发工具链
MagicMind开发
软件栈百科
云平台集成
硬件产品专区
MLU370系列AI加速卡
MLU270系列AI加速卡
MLU220系列AI加速产品
经验方案交流区
经验案例与实践分享
开发者服务
开发者活动
公告与版务
高校支持
《智能计算系统》
签到
版块
社区
文档
SDK下载
370系列
200系列
开发平台
官网首页
注册
登录
全部版块
基础软件平台
硬件产品专区
经验方案交流区
开发者服务
高校支持
发布新帖
登录/注册
LV.1
yinyin123456
98
积分
0
赞
11
帖子
61
回复
0
收藏
TA的动态
TA的帖子
TA的回复
mlu220离线模型测试,测试结果异常
我的回复:#3zhangyanting回复您好,我这边注意到您的第一张推理错误的图中,有许多低概率的画框出现在边缘位置,您可以尝试看看画框后处理是否存在问题。展开这边输出后处理了,包括得分与坐标过滤,现在测试视频流 都没有出现第一张图的情形,但目前不知道什么原因造成。
0
mlu220离线模型测试,测试结果异常
我的回复:#1zhangyanting回复您好,您可以先试试不使用python调用c++的方式,直接使用c++推理,看看结果是否正确;如果结果正确的话再去排查反复调用时的情况。展开本地python单独掉C++动态库 推理输出 正常 以及 调用C++可以执行文件 推理正常, 跑RTSP流进行推理 不正常
0
关于视频流RTSP抓取图像进行在MLU220芯片盒子上进行推理的问题
我的回复:#15zhangyanting回复您好,分配内存空间也可以放在构造函数中,您可以运行结束之后再释放,每次复用已分配的空间。测试mlu220离线模型 人头识别,出现这种情况 模型输出的坐标有问题,多个线程分别加载模型进行预测,图像是通过python 读取传入 C++ demo中,有的线程预测正常,有的线程预测错误。请看图:线程1:线程2:
0
关于视频流RTSP抓取图像进行在MLU220芯片盒子上进行推理的问题
我的回复:#13zhangyanting回复您好,调用类中方法时,只要该方法没有调用cnrtLoadModel接口就不会反复加载模型;您可以把cnrtLoadModel放在类的构造函数中。展开好的 谢谢!创建运行时 分配mlu 与 cpu 内存空间 是否也放在构造函数里面, 还是在类方法里面,掉完 就释放完 再次调用,再分配 再释放
0
关于视频流RTSP抓取图像进行在MLU220芯片盒子上进行推理的问题
我的回复:#11zhangyanting回复您好,您可以在c++里定义类成员方法用于接收数据和推理,在python脚本里反复调用类成员方法就可以了。python 调用类里面该方法,这样会反复出现加载模型情况吗 模型加载在哪里进性呢
0
关于视频流RTSP抓取图像进行在MLU220芯片盒子上进行推理的问题
我的回复:#9zhangyanting回复您好,python是可以解析c++结构体的,您可以去了解一下ctypes的用法。python这边需要定义类去接收结构体,类里面成员与结构体要一致,数据类型也要一致,但C++demo中,CNRT里面function结构体变量无法获取里面的成员,python端无法解析from ctypes import * INTARRAY8 = c_int * 8 class PyTestStruct(Structure): 'TestStruct_st 的 Python 版本' _fields_ = [ ("integer", c_int), ("c_str", c_char_p), ("ptr", c_void_p), ("array", INTARRAY8) ]首先对结构体里的 int 数组进行了重定义,也就是 INTARRAY8。接着,注意一下 _fields_ 的内容:这里就是对 C 数据类型的转换。左边是 C 的结构成员名称,右边则是在 python 中声明一下各个成员的类型
0
关于视频流RTSP抓取图像进行在MLU220芯片盒子上进行推理的问题
我的回复:#7zhangyanting回复您好,封装调用的流程是一样的,您只需要把自己想要的循环的内容和其余的内容分开,分别封装就可以了。您可以参考《CNRT用户手册》的介绍章节(介绍 — 寒武纪运行时库用户手册 4.10.0 文档 (cambricon.com)),这一章介绍了关于您需要用的主要接口功能。展开我看了C++demo代码。我这边是这么考虑的,python先调用C++里模型加载函数返回function,然后将function传入到另一个数据传入与推理函数,里面已创建好的CNRT运行实例中进行预测,主要是python这边无法解析C++结构体,没有结构体里面的成员属性,python端无法接收function结构体变量
0
关于视频流RTSP抓取图像进行在MLU220芯片盒子上进行推理的问题
我的回复:#3zhangyanting回复 您好,您可以在193行到301行之间循环传入图片地址,这样就不用反复加载model了。 loop{传入图片地址; 数据从cpu传入mlu; 推理; 数据从mlu传回cpu}展开您好 方便能否你这边提供一份代码 加载模型与 数据+推理分开的demo
0
关于视频流RTSP抓取图像进行在MLU220芯片盒子上进行推理的问题
我的回复:#3zhangyanting回复 您好,您可以在193行到301行之间循环传入图片地址,这样就不用反复加载model了。 loop{传入图片地址; 数据从cpu传入mlu; 推理; 数据从mlu传回cpu}展开目前项目采用的python语言进行模型推理与部署,我把C++ main源码编译成python可以调用的动态库了,python会调用里面动态库里面的函数也就是(main部分已封装), 如果想单独加载一次模型的话,是否要再定义一个函数,单独加载模型给python调用,然后加载完后,python再调用传入数据函数进行推理?
0
关于视频流RTSP抓取图像进行在MLU220芯片盒子上进行推理的问题
我的回复:#1zhangyanting回复您好,数据传入时并不存在反复加载模型的问题。我查看了您的代码,发现您给mlu分配数据空间之后,并没有将数据从cpu传入mlu,这需要调用cnrtMemcpy接口,此外,您也没有做推理,这需要调用cnrtInvokeRuntimeContext接口。关于离线模型推理,建议您参考:离线模型示例程序 — 寒武纪运行时库用户手册 4.10.0 文档 (cambricon.com)展开我没有把代码传入完,视频流每抓一帧图像传入离线模型demo里面每一次都有设置模型加载,完成代码如下:#include <opencv2/core/core.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/highgui/highgui.hpp> #include <string> #include <vector> #include "cnrt.h" #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <dirent.h> #include <errno.h> #include "processor.hpp" using namespace std; using namespace cv; double GetTickCount() { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return (ts.tv_sec * 1000000 + ts.tv_nsec / 1000)/1000.0; } int main(int argc,char *argv[]) { if(argc!=8) { printf("Usage:%s model_path function_name dev_id dev_channel image_path is_rgb label_filename\\n",argv[0]); printf("\\nex. ./build/yolov5_offline_simple_demo model/yolov5.cambricon subnet0 0 0 data/000000000872.jpg 2 data/label_map_coco.txt\\n\\n"); return -1; } unsigned int dev_num=0; CNRT_CHECK(cnrtInit(0)); CNRT_CHECK(cnrtGetDeviceCount(&dev_num)); if (dev_num == 0) return -1; const char *model_path=argv[1]; //模型路径 const char *function_name=argv[2]; //离线模型中的Function Name unsigned dev_id=atoi(argv[3]); //使用的MLU 设备ID int dev_channel=atoi(argv[4]); //使用MLU设备的通道号 -1 为自动分配 const char *image_path=argv[5]; //测试图片的路径 int is_rgb=atoi(argv[6]); //数据预处理选项 string label_filename(argv[7]); //label文件 int input_width; //网络输入的宽度 int input_height; //网络输入的高度 int batch_size; //网络的batch int64_t *inputSizeS; //网络输入数据大小,用于分配内存 int64_t *outputSizeS; //网络输出数据量大小,用于分配内存 cnrtDataType_t *inputTypeS; //网络输入的数据类型 cnrtDataType_t *outputTypeS; //网络输出的数据类型 vector<int> output_count; cnrtQueue_t queue; //cnrt queue cnrtModel_t model; //离线模型 cnrtFunction_t function; //离线模型中的Function cnrtDev_t dev; //MLU设备句柄 cnrtRuntimeContext_t ctx; //推理上下文 int *dimValues; //保存维度shape int dimNum; //保存维度大小 int inputNum; //输入节点个数 int outputNum; //输出节点个数 void **param; //保存推理时,mlu上内存地址的指针 void **inputCpuPtrS; //输入数据的CPU指针 void **outputCpuPtrS; //输出数据的CPU指针 void **outputCpuNchwPtrS; //用来保存transpose后的NCHW数据 void **inputMluPtrS; //输入数据的MLU指针 void **outputMluPtrS; //输出数据的MLU指针 //获取指定设备的句柄 CNRT_CHECK(cnrtGetDeviceHandle(&dev, dev_id)); //设置当前使用的设备,作用于线程上下文 CNRT_CHECK(cnrtSetCurrentDevice(dev)); //加载离线模型 CNRT_CHECK(cnrtLoadModel(&model, model_path)); //创建function CNRT_CHECK(cnrtCreateFunction(&function)); //从离线模型中提取指定的function,离线模型可以存储多个function CNRT_CHECK(cnrtExtractFunction(&function, model, function_name)); //调用cnrtSetCurrentChannel之后 CNRT 仅在指定的通道上分配MLU内存,否则采用交织的方式分配 if(dev_channel>=0) CNRT_CHECK(cnrtSetCurrentChannel((cnrtChannelType_t)dev_channel)); //创建运行时 CNRT_CHECK(cnrtCreateRuntimeContext(&ctx,function,NULL)); //设置运行时使用的设备ID CNRT_CHECK(cnrtSetRuntimeContextDeviceId(ctx,dev_id)); //初始化运行时 CNRT_CHECK(cnrtInitRuntimeContext(ctx,NULL)); //创建队列 CNRT_CHECK(cnrtRuntimeContextCreateQueue(ctx,&queue)); //获取模型输入/输出 的数据大小及节点个数 CNRT_CHECK(cnrtGetInputDataSize(&inputSizeS,&inputNum,function)); CNRT_CHECK(cnrtGetOutputDataSize(&outputSizeS,&outputNum,function)); //获取模型输入/输出 的数据类型 CNRT_CHECK(cnrtGetInputDataType(&inputTypeS,&inputNum,function)); CNRT_CHECK(cnrtGetOutputDataType(&outputTypeS,&outputNum,function)); //分配 存放CPU端输入/输出地址的 指针数组 inputCpuPtrS = (void **)malloc(sizeof(void *) * inputNum); outputCpuPtrS = (void **)malloc(sizeof(void *) * outputNum); outputCpuNchwPtrS = (void **)malloc(sizeof(void *) * outputNum); //分配 存放MLU端输入/输出地址的 指针数组 outputMluPtrS = (void **)malloc(sizeof(void *) * outputNum); inputMluPtrS = (void **)malloc(sizeof(void *) * inputNum); //为输入节点 分配CPU/MLU内存 for (int i = 0; i < inputNum; i++) { CNRT_CHECK(cnrtMalloc(&inputMluPtrS[i],inputSizeS[i])); //分配MLU上内存 inputCpuPtrS[i] = (void *)malloc(inputSizeS[i]); //分配CPU上的内存 //printf("%d\\n", inputSizeS[i]); //获取输入的维度信息 NHWC CNRT_CHECK(cnrtGetInputDataShape(&dimValues,&dimNum,i,function)); printf("input shape:\\n"); for(int y=0;y<dimNum;y++) { printf("%d ",dimValues[y]); } printf("\\n"); input_width=dimValues[2]; input_height=dimValues[1]; batch_size=dimValues[0]; free(dimValues); } //为输出节点 分配CPU/MLU内存 for (int i = 0; i < outputNum; i++) { CNRT_CHECK(cnrtMalloc(&outputMluPtrS[i],outputSizeS[i])); //分配MLU上内存 outputCpuPtrS[i] = (void *)malloc(outputSizeS[i]); //分配CPU上的内存 //printf("%d\\n", outputSizeS[i]); //获取输出的维度信息 NHWC CNRT_CHECK(cnrtGetOutputDataShape(&dimValues,&dimNum,i,function)); int count=1; printf("output shape:\\n"); for(int y=0;y<dimNum;y++) { printf("%d ",dimValues[y]); count=count*dimValues[y]; } printf("\\n"); outputCpuNchwPtrS[i] = (void *)malloc(count*sizeof(float)); //将输出转为float32类型,方便用户后处理 output_count.push_back(count); free(dimValues); } //配置MLU输入/输出 地址的指针 param = (void **)malloc(sizeof(void *) * (inputNum + outputNum)); for (int i = 0; i < inputNum; i++) { param[i] = inputMluPtrS[i]; } for (int i = 0; i < outputNum; i++) { param[i + inputNum] = outputMluPtrS[i]; } //设置输入/输出的节点 索引 int input_idx=0; int output_idx=0; vector<cv::Mat> imgs; vector<string> img_names; unsigned char *ptr=(unsigned char *)inputCpuPtrS[input_idx]; for(int i=0;i<batch_size;i++) { // 选项 2 是yolov5的数据预处理方式 img_names.push_back(image_path); cv::Mat input_image=cv::imread(image_path); imgs.push_back(input_image); cv::Mat input_image_resized; cv::resize(input_image,input_image_resized,cv::Size(input_width,input_height)); if(is_rgb==1) { cv::Mat net_input_data_rgba(input_height,input_width,CV_8UC4,ptr); cv::cvtColor(input_image_resized, net_input_data_rgba, CV_BGR2RGBA); ptr+=(input_height*input_width*4); } else if(is_rgb==0) { cv::Mat net_input_data_rgba(input_height,input_width,CV_8UC4,ptr); cv::cvtColor(input_image_resized, net_input_data_rgba, CV_BGR2BGRA); ptr+=(input_height*input_width*4); } else if(is_rgb==2) { cv::Mat sample_temp; float img_w = input_image.cols; float img_h = input_image.rows; cv::Mat sample_temp_bgr(input_image.cols, input_image.rows, CV_32FC3); float img_scale = img_w < img_h ? (input_height / img_h) : (input_width / img_w); int new_w = std::floor(img_w * img_scale); int new_h = std::floor(img_h * img_scale); cv::cvtColor(input_image, sample_temp_bgr, CV_BGR2RGB); cv::resize(sample_temp_bgr, sample_temp, cv::Size(new_w, new_h), CV_INTER_LINEAR); cv::Mat net_input_data_rgba(input_height,input_width,CV_32FC3,ptr); sample_temp.copyTo(net_input_data_rgba( cv::Range((static_cast<float>(input_height) - new_h) / 2, (static_cast<float>(input_height) - new_h) / 2 + new_h), cv::Range((static_cast<float>(input_width) - new_w) / 2, (static_cast<float>(input_width) - new_w) / 2 + new_w))); net_input_data_rgba /= 255.0; ptr+=(input_height*input_width*4); } } auto t0=GetTickCount(); //拷贝输入数据到MLU内存 CNRT_CHECK(cnrtMemcpy(inputMluPtrS[input_idx],inputCpuPtrS[input_idx],inputSizeS[input_idx],CNRT_MEM_TRANS_DIR_HOST2DEV)); //创建事件 cnrtNotifier_t notifier_start; //用来记录硬件时间 cnrtNotifier_t notifier_end; CNRT_CHECK(cnrtRuntimeContextCreateNotifier(ctx,¬ifier_start)); CNRT_CHECK(cnrtRuntimeContextCreateNotifier(ctx,¬ifier_end)); CNRT_CHECK(cnrtPlaceNotifier(notifier_start, queue)); //设置invoke的参数 unsigned int affinity=1<<dev_channel; //设置通道亲和性,使用指定的MLU cluster做推理 cnrtInvokeParam_t invokeParam; //invoke参数 invokeParam.invoke_param_type=CNRT_INVOKE_PARAM_TYPE_0; invokeParam.cluster_affinity.affinity=&affinity; CNRT_CHECK(cnrtInvokeRuntimeContext_V2(ctx,nullptr,param,queue,&invokeParam)); CNRT_CHECK(cnrtPlaceNotifier(notifier_end, queue)); CNRT_CHECK(cnrtSyncQueue(queue)); //拷贝MLU输出到CPU内存 CNRT_CHECK(cnrtMemcpy(outputCpuPtrS[output_idx],outputMluPtrS[output_idx],outputSizeS[output_idx],CNRT_MEM_TRANS_DIR_DEV2HOST)); auto t1=GetTickCount(); float hwtime; CNRT_CHECK(cnrtNotifierDuration(notifier_start, notifier_end, &hwtime)); printf("HardwareTime:%f(ms) E2ETime:%f(ms)\\n",hwtime/1000.0,t1-t0); int dim_order[4] = {0, 3, 1, 2}; CNRT_CHECK(cnrtGetOutputDataShape(&dimValues,&dimNum,output_idx,function)); if(dimNum==4){ //NHWC->NCHW half->float32 CNRT_CHECK(cnrtTransOrderAndCast(reinterpret_cast<void*>(outputCpuPtrS[output_idx]), outputTypeS[output_idx], reinterpret_cast<void*>(outputCpuNchwPtrS[output_idx]), CNRT_FLOAT32, nullptr, dimNum, dimValues, dim_order)); } else { //数据类型转换 half->float32 CNRT_CHECK(cnrtCastDataType(reinterpret_cast<void*>(outputCpuPtrS[output_idx]), outputTypeS[output_idx], reinterpret_cast<void*>(outputCpuNchwPtrS[output_idx]), CNRT_FLOAT32, outputSizeS[output_idx]/2,nullptr)); } //打印输出结果 float *output_ptr=(float*)outputCpuNchwPtrS[output_idx]; cout << "boxnum:" << output_ptr[0] << endl; vector<vector<vector<float>>> detections = getResults(output_ptr, dimNum, dimValues); cout << "=========================" << endl; for(auto& d0:detections) for(auto &d1:d0){ for(auto &re:d1) cout << re << " "; cout << endl; } cout << "=========================" << endl; vector<string> labels; readLabels(label_filename, labels); writeVisualizeBBox(imgs, detections,labels, img_names, input_height); free(dimValues); CNRT_CHECK(cnrtSetCurrentDevice(dev)); CNRT_CHECK(cnrtDestroyQueue(queue)); CNRT_CHECK(cnrtDestroyFunction(function)); CNRT_CHECK(cnrtUnloadModel(model)); cnrtDestroyNotifier(¬ifier_start); cnrtDestroyNotifier(¬ifier_end); for (int i = 0; i < inputNum; i++) { free(inputCpuPtrS[i]); cnrtFree(inputMluPtrS[i]); } for (int i = 0; i < outputNum; i++) { free(outputCpuPtrS[i]); free(outputCpuNchwPtrS[i]); cnrtFree(outputMluPtrS[i]); } free(param); free(inputCpuPtrS); free(outputCpuPtrS); cnrtDestroyRuntimeContext(ctx); return 0; }
0
上一页
1
2
3
下一页
Github
开发平台
文档中心
新手必读
官方微信
版权所有 © 2024 寒武纪 Cambricon.com 备案/许可证号:
京ICP备17003415号-1
关闭