×

签到

分享到微信

打开微信,使用扫一扫进入页面后,点击右上角菜单,

点击“发送给朋友”或“分享到朋友圈”完成分享

【BANGC】segmentation fault core dumped 已解决 xyy2023-03-06 16:42:34 回复 4 查看 技术答疑 使用求助 经验交流
【BANGC】segmentation fault core dumped
分享到:

【寒武纪硬件产品型号】必填*:
MLU270

【使用操作系统】必填*:
ubuntu

【使用驱动版本】必填*:
例如v4.20.6

【使用AI框架】必填*:
Pytorch

【出错信息】必填*:

在使用离线模型进行推理时报错:

(torch_mlu_py36) root@pointpillor-v1-85cbc7cd74-cc4lq:/data/xyy/yolos_offline/offline_yolos# bash run.sh 
CNRT: 4.10.1 a884a9a
inputNum:1
outputNum:2
input shape:
1 384 640 3 
output shape:
1 1 1 7232 
output shape:
1 384 640 19 
batchsize:1
input_image.shape:720 1280
entering yolov5 preprocess
input_height:384        input_width:640 img_h:720       img_w:1280      img_scale:0.500000
input_height:384        input_width:640 new_h:360       new_w:640
[640 x 384]
-----start to copy data to device------
input_idx:0
-----start to set notifier------
-----start to set parameters------
-----start to process------
run.sh: line 17: 71980 Segmentation fault      (core dumped) ./build/yolos_offline model/yolov5s_int8_1b_1c_offline.cambricon subnet0 0 0 ./image/image2.jpg 2 label_map_cityscapes.txt

run.sh

./build/yolos_offline model/yolov5s_int8_1b_1c_offline.cambricon subnet0 0 0 ./image/image2.jpg 2 label_map_cityscapes.txt

【当前已做了哪些信息确认】选填:
经过调试 发现出错在算子执行步骤

#define OPENCV_TRAITS_ENABLE_DEPRECATED
#include <opencv2/core/core.hpp>
#include <opencv2/opencv.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 <ATen/ATen.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>
#include <iostream>
#include <torch/torch.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 \n",argv[0]);
        printf("\nex.  ./src/yolop_offline_simple_demo model/yolop.cambricon subnet0 0 0 data/000000000872.jpg 2 \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);
    printf("inputNum:%d\n",inputNum);//1
    printf("outputNum:%d\n",outputNum);//2

    //为输入节点 分配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];//640
        input_height=dimValues[1];//384
        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;
    printf("batchsize:%d\n",batch_size);
    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);
        printf("input_image.shape:%d %d\n",input_image.rows,input_image.cols);
        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;
          int img_w = input_image.cols;
          int img_h = input_image.rows;
          cv::Mat sample_temp_bgr(input_image.cols, input_image.rows, CV_32FC3);
          printf("entering yolov5 preprocess\n");
          float img_scale = img_w < img_h ? (input_height / img_h) : (input_width*1.0 / img_w);
          printf("input_height:%d\tinput_width:%d\timg_h:%d\timg_w:%d\timg_scale:%f\n",input_height,input_width,img_h,img_w,img_scale);
          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);
          printf("input_height:%d\tinput_width:%d\tnew_h:%d\tnew_w:%d\n",input_height,input_width,new_h,new_w);
          //384 640 360 640
          sample_temp.copyTo(net_input_data_rgba(
                                             cv::Range((static_cast<float>(input_height) - new_h) / 2,//12
                                                       (static_cast<float>(input_height) - new_h) / 2 + new_h),//372
                                             cv::Range((static_cast<float>(input_width) - new_w) / 2,//0
                                                       (static_cast<float>(input_width) - new_w) / 2 + new_w)));//640
          net_input_data_rgba /= 255.0;
          cout<<net_input_data_rgba.size()<<endl;//640*384
          ptr+=(input_height*input_width*4);

        }
    }
    cout<<"-----start to copy data to device------"<<endl;
    auto t0=GetTickCount();
    //拷贝输入数据到MLU内存
   
    CNRT_CHECK(cnrtMemcpy(inputMluPtrS[input_idx],inputCpuPtrS[input_idx],inputSizeS[input_idx],CNRT_MEM_TRANS_DIR_HOST2DEV));
    cout<<"input_idx:"<<input_idx<<endl;
    cout<<"-----start to set notifier------"<<endl;
    //创建事件
    cnrtNotifier_t          notifier_start;             //用来记录硬件时间
    cnrtNotifier_t          notifier_end;
    CNRT_CHECK(cnrtRuntimeContextCreateNotifier(ctx,&notifier_start));
    CNRT_CHECK(cnrtRuntimeContextCreateNotifier(ctx,&notifier_end));
    CNRT_CHECK(cnrtPlaceNotifier(notifier_start, queue));
    cout<<"-----start to set parameters------"<<endl;
    //设置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;
    //执行算子
    cout<<"-----start to process------"<<endl;
    CNRT_CHECK(cnrtInvokeRuntimeContext_V2(ctx,nullptr,param,queue,&invokeParam));
    cout<<"-----process completed------"<<endl;



版权所有 © 2024 寒武纪 Cambricon.com 备案/许可证号:京ICP备17003415号-1
关闭