Toybrick

标题: rknn c++ api无法连续进行inference,程序会自动终止 [打印本页]

作者: protossw512    时间: 2019-3-9 05:02
标题: rknn c++ api无法连续进行inference,程序会自动终止
本帖最后由 protossw512 于 2019-3-9 05:06 编辑

为了进行压力测试,使用c++ api进行连续inference的时候,过一段时间程序会自动停止,目前无法找到原因,随后我换成了官方自带的ssd example code,一样会有同样的问题。这是我的代码(在官方代码的基础上,在第251行增加了while loop):
  1. #include <stdio.h>
  2. #include <stdint.h>
  3. #include <stdlib.h>
  4. #include <fstream>
  5. #include <iostream>
  6. #include <sys/time.h>
  7. #include <chrono>

  8. #include "rknn_api.h"
  9. #include "opencv2/core/core.hpp"
  10. #include "opencv2/imgproc/imgproc.hpp"
  11. #include "opencv2/highgui/highgui.hpp"

  12. using namespace std;
  13. using namespace cv;
  14. using namespace chrono;

  15. #define NUM_RESULTS         1917
  16. #define NUM_CLASSES         91

  17. #define Y_SCALE  10.0f
  18. #define X_SCALE  10.0f
  19. #define H_SCALE  5.0f
  20. #define W_SCALE  5.0f

  21. Scalar colorArray[10] = {
  22.         Scalar(139,   0,   0, 255),
  23.         Scalar(139,   0, 139, 255),
  24.         Scalar(  0,   0, 139, 255),
  25.         Scalar(  0, 100,   0, 255),
  26.         Scalar(139, 139,   0, 255),
  27.         Scalar(209, 206,   0, 255),
  28.         Scalar(  0, 127, 255, 255),
  29.         Scalar(139,  61,  72, 255),
  30.         Scalar(  0, 255,   0, 255),
  31.         Scalar(255,   0,   0, 255),
  32. };

  33. float MIN_SCORE = 0.4f;

  34. float NMS_THRESHOLD = 0.45f;


  35. int loadLabelName(string locationFilename, string* labels) {
  36.     ifstream fin(locationFilename);
  37.     string line;
  38.     int lineNum = 0;
  39.     while(getline(fin, line))
  40.     {
  41.         labels[lineNum] = line;
  42.         lineNum++;
  43.     }
  44.     return 0;
  45. }

  46. int loadCoderOptions(string locationFilename, float (*boxPriors)[NUM_RESULTS])
  47. {
  48.     const char *d = ", ";
  49.     ifstream fin(locationFilename);
  50.     string line;
  51.     int lineNum = 0;
  52.     while(getline(fin, line))
  53.     {
  54.         char *line_str = const_cast<char *>(line.c_str());
  55.         char *p;
  56.         p = strtok(line_str, d);
  57.         int priorIndex = 0;
  58.         while (p) {
  59.             float number = static_cast<float>(atof(p));
  60.             boxPriors[lineNum][priorIndex++] = number;
  61.             p=strtok(nullptr, d);
  62.         }
  63.         if (priorIndex != NUM_RESULTS) {
  64.             return -1;
  65.         }
  66.         lineNum++;
  67.     }
  68.     return 0;

  69. }

  70. float CalculateOverlap(float xmin0, float ymin0, float xmax0, float ymax0, float xmin1, float ymin1, float xmax1, float ymax1) {
  71.     float w = max(0.f, min(xmax0, xmax1) - max(xmin0, xmin1));
  72.     float h = max(0.f, min(ymax0, ymax1) - max(ymin0, ymin1));
  73.     float i = w * h;
  74.     float u = (xmax0 - xmin0) * (ymax0 - ymin0) + (xmax1 - xmin1) * (ymax1 - ymin1) - i;
  75.     return u <= 0.f ? 0.f : (i / u);
  76. }

  77. float expit(float x) {
  78.     return (float) (1.0 / (1.0 + exp(-x)));
  79. }

  80. void decodeCenterSizeBoxes(float* predictions, float (*boxPriors)[NUM_RESULTS]) {

  81.     for (int i = 0; i < NUM_RESULTS; ++i) {
  82.         float ycenter = predictions[i*4+0] / Y_SCALE * boxPriors[2][i] + boxPriors[0][i];
  83.         float xcenter = predictions[i*4+1] / X_SCALE * boxPriors[3][i] + boxPriors[1][i];
  84.         float h = (float) exp(predictions[i*4 + 2] / H_SCALE) * boxPriors[2][i];
  85.         float w = (float) exp(predictions[i*4 + 3] / W_SCALE) * boxPriors[3][i];

  86.         float ymin = ycenter - h / 2.0f;
  87.         float xmin = xcenter - w / 2.0f;
  88.         float ymax = ycenter + h / 2.0f;
  89.         float xmax = xcenter + w / 2.0f;

  90.         predictions[i*4 + 0] = ymin;
  91.         predictions[i*4 + 1] = xmin;
  92.         predictions[i*4 + 2] = ymax;
  93.         predictions[i*4 + 3] = xmax;
  94.     }
  95. }

  96. int scaleToInputSize(float * outputClasses, int (*output)[NUM_RESULTS], int numClasses)
  97. {
  98.     int validCount = 0;
  99.     // Scale them back to the input size.
  100.     for (int i = 0; i < NUM_RESULTS; ++i) {
  101.         float topClassScore = static_cast<float>(-1000.0);
  102.         int topClassScoreIndex = -1;

  103.         // Skip the first catch-all class.
  104.         for (int j = 1; j < numClasses; ++j) {
  105.             float score = expit(outputClasses[i*numClasses+j]);
  106.             if (score > topClassScore) {
  107.                 topClassScoreIndex = j;
  108.                 topClassScore = score;
  109.             }
  110.         }

  111.         if (topClassScore >= MIN_SCORE) {
  112.             output[0][validCount] = i;
  113.             output[1][validCount] = topClassScoreIndex;
  114.             ++validCount;
  115.         }
  116.     }

  117.     return validCount;
  118. }

  119. int nms(int validCount, float* outputLocations, int (*output)[NUM_RESULTS])
  120. {
  121.     for (int i=0; i < validCount; ++i) {
  122.         if (output[0][i] == -1) {
  123.             continue;
  124.         }
  125.         int n = output[0][i];
  126.         for (int j=i + 1; j<validCount; ++j) {
  127.             int m = output[0][j];
  128.             if (m == -1) {
  129.                 continue;
  130.             }
  131.             float xmin0 = outputLocations[n*4 + 1];
  132.             float ymin0 = outputLocations[n*4 + 0];
  133.             float xmax0 = outputLocations[n*4 + 3];
  134.             float ymax0 = outputLocations[n*4 + 2];

  135.             float xmin1 = outputLocations[m*4 + 1];
  136.             float ymin1 = outputLocations[m*4 + 0];
  137.             float xmax1 = outputLocations[m*4 + 3];
  138.             float ymax1 = outputLocations[m*4 + 2];

  139.             float iou = CalculateOverlap(xmin0, ymin0, xmax0, ymax0, xmin1, ymin1, xmax1, ymax1);

  140.             if (iou >= NMS_THRESHOLD) {
  141.                 output[0][j] = -1;
  142.             }
  143.         }
  144.     }

  145.     return 0;
  146. }

  147. int main(int argc, char** argv)
  148. {
  149.     int counter;
  150.     auto start = high_resolution_clock::now();
  151.     auto end = high_resolution_clock::now();
  152.     auto duration = duration_cast<microseconds>(end - start);
  153.     const char *img_path = "/tmp/road.bmp";
  154.     const char *model_path = "/tmp/mobilenet_ssd.rknn";
  155.     const char *label_path = "/tmp/coco_labels_list.txt";
  156.     const char *box_priors_path = "/tmp/box_priors.txt";

  157.     const int img_width = 300;
  158.     const int img_height = 300;
  159.     const int img_channels = 3;
  160.     const int input_index = 0;      // node name "Preprocessor/sub"

  161.     const int output_elems1 = NUM_RESULTS * 4;
  162.     const uint32_t output_size1 = output_elems1 * sizeof(float);
  163.     const int output_index1 = 0;    // node name "concat"

  164.     const int output_elems2 = NUM_RESULTS * NUM_CLASSES;
  165.     const uint32_t output_size2 = output_elems2 * sizeof(float);
  166.     const int output_index2 = 1;    // node name "concat_1"

  167.     // Load image
  168.     cv::Mat img = cv::imread(img_path, 1);
  169.     if(!img.data) {
  170.         printf("cv::imread %s fail!\n", img_path);
  171.         return -1;
  172.     }
  173.     if(img.cols != img_width || img.rows != img_height)
  174.         cv::resize(img, img, cv::Size(img_width, img_height), (0, 0), (0, 0), cv::INTER_LINEAR);

  175.     // Load model
  176.     FILE *fp = fopen(model_path, "rb");
  177.     if(fp == NULL) {
  178.         printf("fopen %s fail!\n", model_path);
  179.         return -1;
  180.     }
  181.     fseek(fp, 0, SEEK_END);
  182.     int model_len = ftell(fp);
  183.     void *model = malloc(model_len);
  184.     fseek(fp, 0, SEEK_SET);
  185.     if(model_len != fread(model, 1, model_len, fp)) {
  186.         printf("fread %s fail!\n", model_path);
  187.         free(model);
  188.         return -1;
  189.     }

  190.     // Start Inference
  191.     rknn_input inputs[1];
  192.     rknn_output outputs[2];
  193.     rknn_tensor_attr outputs_attr[2];

  194.     int ret = 0;
  195.     rknn_context ctx = 0;

  196.     ret = rknn_init(&ctx, model, model_len, RKNN_FLAG_PRIOR_MEDIUM);
  197.     if(ret < 0) {
  198.         printf("rknn_init fail! ret=%d\n", ret);
  199.         goto Error;
  200.     }

  201.     outputs_attr[0].index = 0;
  202.     ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(outputs_attr[0]), sizeof(outputs_attr[0]));
  203.     if(ret < 0) {
  204.         printf("rknn_query fail! ret=%d\n", ret);
  205.         goto Error;
  206.     }

  207.     outputs_attr[1].index = 1;
  208.     ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(outputs_attr[1]), sizeof(outputs_attr[1]));
  209.     if(ret < 0) {
  210.         printf("rknn_query fail! ret=%d\n", ret);
  211.         goto Error;
  212.     }

  213.     while(1){
  214.       inputs[0].index = input_index;
  215.       inputs[0].buf = img.data;
  216.       inputs[0].size = img_width * img_height * img_channels;
  217.       inputs[0].pass_through = false;
  218.       inputs[0].type = RKNN_TENSOR_UINT8;
  219.       inputs[0].fmt = RKNN_TENSOR_NHWC;
  220.       start = high_resolution_clock::now();
  221.       ret = rknn_inputs_set(ctx, 1, inputs);
  222.       if(ret < 0) {
  223.         printf("rknn_input_set fail! ret=%d\n", ret);
  224.         goto Error;
  225.       }

  226.       ret = rknn_run(ctx, nullptr);
  227.       if(ret < 0) {
  228.         printf("rknn_run fail! ret=%d\n", ret);
  229.         goto Error;
  230.       }

  231.       outputs[0].want_float = true;
  232.       outputs[0].is_prealloc = false;
  233.       outputs[1].want_float = true;
  234.       outputs[1].is_prealloc = false;
  235.       ret = rknn_outputs_get(ctx, 2, outputs, nullptr);
  236.       if(ret < 0) {
  237.         printf("rknn_outputs_get fail! ret=%d\n", ret);
  238.         goto Error;
  239.       }
  240.       end = high_resolution_clock::now();
  241.       duration = duration_cast<microseconds>(end - start);
  242.       counter += 1;
  243.       cout << counter << ": run_time: " << duration.count() << endl;
  244.     }

  245.     // Process output
  246.     if(outputs[0].size == outputs_attr[0].n_elems*sizeof(float) && outputs[1].size == outputs_attr[1].n_elems*sizeof(float))
  247.     {
  248.         float boxPriors[4][NUM_RESULTS];
  249.         string labels[91];

  250.         /* load label and boxPriors */
  251.         loadLabelName(label_path, labels);
  252.         loadCoderOptions(box_priors_path, boxPriors);

  253.         float* predictions = (float*)outputs[0].buf;
  254.         float* outputClasses = (float*)outputs[1].buf;

  255.         int output[2][NUM_RESULTS];

  256.         /* transform */
  257.         decodeCenterSizeBoxes(predictions, boxPriors);

  258.         int validCount = scaleToInputSize(outputClasses, output, NUM_CLASSES);
  259.         printf("validCount: %d\n", validCount);

  260.         if (validCount < 100) {
  261.             /* detect nest box */
  262.             nms(validCount, predictions, output);

  263.             Mat rgba = imread(img_path, CV_LOAD_IMAGE_UNCHANGED);
  264.             cv::resize(rgba, rgba, cv::Size(1200, 1200), (0, 0), (0, 0), cv::INTER_LINEAR);

  265.             /* box valid detect target */
  266.             for (int i = 0; i < validCount; ++i) {
  267.                 if (output[0][i] == -1) {
  268.                     continue;
  269.                 }
  270.                 int n = output[0][i];
  271.                 int topClassScoreIndex = output[1][i];

  272.                 int x1 = static_cast<int>(predictions[n * 4 + 1] * rgba.cols);
  273.                 int y1 = static_cast<int>(predictions[n * 4 + 0] * rgba.rows);
  274.                 int x2 = static_cast<int>(predictions[n * 4 + 3] * rgba.cols);
  275.                 int y2 = static_cast<int>(predictions[n * 4 + 2] * rgba.rows);

  276.                 string label = labels[topClassScoreIndex];

  277.                 std::cout << label << "\t@ (" << x1 << ", " << y1 << ") (" << x2 << ", " << y2 << ")" << "\n";

  278.                 rectangle(rgba, Point(x1, y1), Point(x2, y2), colorArray[topClassScoreIndex%10], 3);
  279.                 putText(rgba, label, Point(x1, y1 - 12), 1, 2, Scalar(0, 255, 0, 255));
  280.             }
  281.             imwrite("out.jpg", rgba);
  282.             printf("write out.jpg succ!\n");
  283.         } else {
  284.             printf("validCount too much!\n");
  285.         }
  286.     }
  287.     else
  288.     {
  289.         printf("rknn_outputs_get fail! get outputs_size = [%d, %d], but expect [%lu, %lu]!\n",
  290.             outputs[0].size, outputs[1].size, outputs_attr[0].n_elems*sizeof(float), outputs_attr[1].n_elems*sizeof(float));
  291.     }

  292.     rknn_outputs_release(ctx, 2, outputs);

  293.     rknn_perf_run perf_run;
  294.     ret = rknn_query(ctx, RKNN_QUERY_PERF_RUN, &perf_run, sizeof(perf_run));
  295.     if(ret < 0) {
  296.       printf("rknn_query fail! ret=%d\n", ret);
  297.       goto Error;
  298.     }
  299.     printf("perf_run.run_duration = %ld us\n", perf_run.run_duration);
  300. Error:
  301.     if(ctx)             rknn_destroy(ctx);
  302.     if(model)           free(model);
  303.     if(fp)              fclose(fp);
  304.     return 0;
  305. }
复制代码


我会每次打印inference消耗的时间,最后三次时间会明显增加,随后提示“Killed”
这是我的部分输出:
  1. 4523: run_time: 25540
  2. 4524: run_time: 25014
  3. 4525: run_time: 25170
  4. 4526: run_time: 25620
  5. 4527: run_time: 25013
  6. 4528: run_time: 25402
  7. 4529: run_time: 25137
  8. 4530: run_time: 25600
  9. 4531: run_time: 25446
  10. 4532: run_time: 25686
  11. 4533: run_time: 39072
  12. 4534: run_time: 931086
  13. 4535: run_time: 3565199
  14. Killed
复制代码




作者: linuxsky    时间: 2019-3-9 07:28
等着更新固件吧
作者: pecado    时间: 2019-3-9 13:45
看看系统日志,是不是OOM了?
作者: protossw512    时间: 2019-3-9 16:03
pecado 发表于 2019-3-9 13:45
看看系统日志,是不是OOM了?

可以的,我看看




欢迎光临 Toybrick (https://t.rock-chips.com/) Powered by Discuz! X3.3