Как я могу сделать это быстрее в C ++ 11 с std :: vector? - PullRequest
0 голосов
/ 09 июля 2019

У меня 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 ГГц MacBook Pro это заняло 4 секунды?очень медленно.

Ответы [ 4 ]

0 голосов
/ 12 июля 2019

Вы продолжаете перебирать данные снова и снова, чтобы выполнять над ними независимые операции.

Примерно так происходит итерация по данным только один раз.

//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];
    }
}
0 голосов
/ 10 июля 2019

Я не думаю, что вы должны использовать std :: vector для выполнения этих операций.Алгоритмы обработки изображений (CV aka Computer Vision) имеют тенденцию быть достаточно сложными в вычислительном отношении, поскольку приходится иметь дело с большим количеством данных.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

Вы можете попытаться скомпилировать без символов отладки, то есть release против debug.Также вы можете попробовать скомпилировать с флагами оптимизации, например, для gcc -O3, которые должны уменьшить размер вашего бинарного файла и ускорить выполнение во время выполнения.Возможно, это может иметь значение.

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

Еще одна вещь, которую вы можете попробовать, - это дать вашему процессу более высокий приоритет, то есть, чем выше приоритет, тем меньше процесс дает процессору,Опять же, это может не иметь большого значения, все зависит от других процессов и их приоритетов и т. Д.

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

Надеюсь, это немного поможет.

0 голосов
/ 12 июля 2019

Ну, ваше мышление не так.

  1. Почему ваша программа работает медленно:

Ваш ЦП должен перебирать большое количество цифр и выполнять вычисления. Это сделает сложность вычислений высокой. Вот почему это медленно. Скорость вашей программы пропорциональна размеру матов A и B. Вы можете проверить этот момент, уменьшив / увеличив размер матов A и B.

  1. Можем ли мы ускорить его с помощью std :: vector

Извините, но это не так. Использование std :: vector не уменьшит сложность вычислений. Математическая модель opencv - «лучшая», переписывание приведет только к замедлению кода.

  1. Как ускорить расчет: вам нужно включить опции ускорения для opencv

Вы можете увидеть это по адресу: https://github.com/opencv/opencv/wiki/CPU-optimizations-build-options. Intel предоставляет библиотеку Intel MKL для ускорения расчета матрицы. Вы могли бы попробовать это в первую очередь.

Лично самый простой подход - использовать графический процессор. Но ваша машина не имеет графического процессора, поэтому она выходит за рамки этого.

0 голосов
/ 09 июля 2019

Хотя я также не уверен, что это быстрее, вы можете сделать это, предполагая, Mat_B содержит uchar

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