Vector-Matrix-Multiplication очень медленно работает в интерфейсе OpenCV C ++ - PullRequest
0 голосов
/ 08 августа 2011

Я определил «Random-Stop-Method», что следующие две строки выглядят очень медленными:

cv::Mat pixelSubMue = pixel - vecMatMue[kk_real];   // ca. 35.5 %
cv::Mat pixelTemp = pixelSubMue * covInvRef;        // ca. 58.1 %
cv::multiply(pixelSubMue, pixelTemp, pixelTemp);    // ca. 0 %
cv::Scalar sumScalar = cv::sum(pixelTemp);          // ca. 3.2 %

double cost = sumScalar.val[0] * 0.5 + vecLogTerm[kk_real]; // ca. 3.2 %
  • vecMatMue[kk_real] - это std::vector<cv::Mat> <- я знаю, что копирование сопряжено с большими трудностями, но использование указателей здесь не сильно влияет на производительность </li>
  • pixelSubMue - это cv::Mat(1, 3, CV_64FC1) вектор
  • covInvRef является ссылкой на cv::Mat(3, 3, CV_64FC1) матрицу
  • vecLogTerm[kk_real] является std::vector<double>

Приведенный выше фрагмент кода находится во внутреннем цикле, который вызывается миллионы раз.

Вопрос : Есть ли способ повысить скорость этой операции?

Редактировать : Спасибо за комментарии! Теперь я измерил время в программе, и проценты показывают, сколько времени тратится на каждую строку. Измерения проводились в режиме Release. Я сделал шесть измерений, каждый раз, когда код выполнялся миллионы раз.

Я должен также упомянуть, что std::vector объекты не влияют на производительность, я просто заменил их постоянными объектами.

Редактировать 2 : Я также реализовал алгоритм с использованием C-Api. Соответствующие строки теперь выглядят так:

cvSub(pixel, vecPMatMue[kk], pixelSubMue);                   // ca. 24.4 %
cvMatMulAdd(pixelSubMue, vecPMatFCovInv[kk], 0, pixelTemp);  // ca. 39.0 %
cvMul(pixelSubMue, pixelTemp, pixelSubMue);                  // ca. 22.0 %
CvScalar sumScalar = cvSum(pixelSubMue);                     // ca. 14.6 %
cost = sumScalar.val[0] * 0.5 + vecFLogTerm[kk];             // ca. 0.0 %

Реализация C ++ требует одинаковых входных данных ca. 3100 мсек, в то время как C-реализация требует только ок. 2050 мсек (оба измерения относятся к общему времени выполнения фрагмента миллионы раз). Но я все еще предпочитаю свою реализацию на C ++, поскольку мне легче читать (для того, чтобы она работала с C-API, нужно было внести другие «безобразные» изменения).

Редактировать 3 : я переписал код без использования каких-либо вызовов функций для фактических расчетов:

capacity_t mue0 = meanRef.at<double>(0, 0);
capacity_t mue1 = meanRef.at<double>(0, 1);
capacity_t mue2 = meanRef.at<double>(0, 2);

capacity_t sigma00 = covInvRef.at<double>(0, 0);
capacity_t sigma01 = covInvRef.at<double>(0, 1);
capacity_t sigma02 = covInvRef.at<double>(0, 2);
capacity_t sigma11 = covInvRef.at<double>(1, 1);
capacity_t sigma12 = covInvRef.at<double>(1, 2);
capacity_t sigma22 = covInvRef.at<double>(2, 2);

mue0 = p0 - mue0; mue1 = p1 - mue1; mue2 = p2 - mue2;

capacity_t pt0 = mue0 * sigma00 + mue1 * sigma01 + mue2 * sigma02;
capacity_t pt1 = mue0 * sigma01 + mue1 * sigma11 + mue2 * sigma12;
capacity_t pt2 = mue0 * sigma02 + mue1 * sigma12 + mue2 * sigma22;

mue0 *= pt0; mue1 *= pt1; mue2 *= pt2;

capacity_t cost = (mue0 + mue1 + mue2) / 2.0 + vecLogTerm[kk_real];

Теперь для вычисления каждого пикселя требуется всего 150 мс!

1 Ответ

1 голос
/ 08 августа 2011

Похоже, вы компилируете режим отладки, который, вероятно, объясняет снижение производительности. Вы можете профилировать свой код, используя функции времени, такие как clock().

* 1006 Е.Г. *

clock_t start,end;
...
start = clock();
cv::Mat pixelTemp = pixelSubMue * covInvRef;    // Very SLOW!
end = clock();

cout<<"Elapsed time in seconds: "<<(static_cast<double>(end)-start)/CLK_TCK<<endl;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...