【问题标题】:How Can I make it faster in c++11 with std::vector?如何在 c++11 中使用 std::vector 使其更快?
【发布时间】:2019-07-09 15:30:02
【问题描述】:

我有 cv::Mat Mat_A 和 cv::Mat Mat_B 都是 (800000 X 512) 浮点数

下面的代码看起来很慢。

int rows = Mat_B.rows;
cv::Mat Mat_A = cv::repeat(img, rows, 1, Mat_A);
Mat_A = Mat_A - Mat_B
cv::pow(Mat_A,2,Mat_A)
cv::reduce(Mat_A, Mat_A, 1, CV_REDUCE_SUM);
cv::minMaxLoc(Mat_A, &dis, 0, &point, 0);

如何在 std::vector 中做到这一点?

我认为它应该更快。

在我的 2.4 Ghz mabook pro 中需要 4 秒?很慢。

【问题讨论】:

  • 那是一堆花车!您正在尝试使用 3GB 的数据,然后您正在对其进行操作,我不确定您是否可以更快地做到这一点。为什么你认为 std::vector 会更快?
  • Mat_A 和 MAT_B 正如您看到的非常巨大的 Mat 对象和 - 来自。在 Numpy (python) 中执行相同操作时: (np.square(compare_desc - people_descs[x])) 它比上面带有 MAT 对象的 C++ 代码更快(1,9 秒)
  • 具体是怎么编译的?

标签: c++ opencv c++11 stdvector mat


【解决方案1】:

我认为您不应该使用 std::vector 来执行这些操作。图像处理(CV 又名计算机视觉)算法的计算量往往很大,因为要处理的数据太多。 OpenCV 2.0 C++ 针对此类操作进行了高度优化,例如cv::Mat 有一个标头,每当使用复制赋值或构造函数复制 cv::Mat 时,只会复制标头并带有指向数据的指针。他们使用引用计数来跟踪实例。所以内存管理已经为你完成了,这是一件好事。

https://docs.opencv.org/2.4/doc/tutorials/core/mat_the_basic_image_container/mat_the_basic_image_container.html

您可以尝试不使用调试符号进行编译,即发布与调试。您还可以尝试使用优化标志进行编译,例如对于 gcc -O3 这应该会减小二进制文件的大小并加快运行时操作。也许它会有所作为。

https://www.rapidtables.com/code/linux/gcc/gcc-o.html

您可以尝试的另一件事是为您的进程赋予更高的优先级,即优先级越高,进程产生的 CPU 越少。同样,这可能没有太大区别,这完全取决于其他流程及其优先级等。

https://superuser.com/questions/42817/is-there-any-way-to-set-the-priority-of-a-process-in-mac-os-x

希望对你有所帮助。

【讨论】:

    【解决方案2】:

    你的想法是错误的。

    1. 为什么你的程序很慢:

    您的 CPU 必须循环处理大量数字并进行计算。这将使计算复杂度很高。这就是为什么它很慢。您的程序速度与 Mat A 和 B 的大小成正比。您可以通过减小/增加 Mat A 和 B 的大小来检查这一点。

    1. 我们可以通过 std::vector 来加速它吗

    抱歉,没有。使用 std::vector 不会降低计算复杂度。 opencv 的数学算法是“最好的”,重写只会导致代码变慢。

    1. 如何加速计算:需要开启opencv的加速选项

    您可以在:https://github.com/opencv/opencv/wiki/CPU-optimizations-build-options 看到它。英特尔提供英特尔 mkl 库来加速矩阵计算。你可以先试试。

    就个人而言,最简单的方法是使用 GPU。但是你的机器没有 GPU,所以不在此范围内。

    【讨论】:

      【解决方案3】:

      您一遍又一遍地迭代数据以对它们进行独立操作。

      这样的事情只在数据上迭代一次。

      //assumes Mat_B and img cv::Mat
      using px_t = float;//you mentioned float so I'll assume both img and Mat_B use floats
      int rows = Mat_B.rows;
      cv::Mat output(1,rows, Mat_B.type());
      auto output_ptr = output.ptr<px_t>(0);
      auto img_ptr = img.ptr<px_t>(0);
      int min_idx =0;
      int max_idx =0;
      px_t min_ele = std::numeric_limits<px_t>::max();
      px_t max_ele = std::numeric_limits<px_t>::min();
      for(int i = 0; i< rows; ++i)
      {
          output[i]=0;
          auto mat_row = Mat_B.ptr<px_t>(i);
          for(int j = 0; j< Mat_B.cols; ++j)
          {
              output[i] +=(img_ptr[j]-mat_row[j])*(img_ptr[j]-mat_row[j]);
          }
          if(output[i]<min_ele)
          {
             min_idx = i;
             min_ele = output[i];
          }
          if(output[i]>max_ele)
          {
             max_idx = i;
             max_ele = output[i];
          }
      }
      

      【讨论】:

        【解决方案4】:

        虽然我也不确定它是否更快,但假设 Mat_B 包含 uchar

        std::vector<uchar> array_B(Mat_B.rows* Mat_B.cols);
        if(Mat_B.isContinuous())
            array_B = Mat_B.data;
        

        【讨论】:

        • 鉴于herehere 提供的类型,这甚至无法编译
        猜你喜欢
        • 2011-05-08
        • 1970-01-01
        • 2013-07-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多