Tôi đã thực hiện một thời gian trước thuật toán Phân tích Procrustes trong Python và được yêu cầu chuyển nó sang OpenCV/C++ gần đây. Sau khi hoàn thành nó, tôi chạy một số kiểm tra và cho cùng một input/instances, mã C++ lấy hai lần thời gian mã Python (khoảng 8 vs 4 giây, tương ứng. Tôi lặp lại các bài kiểm tra hàng nghìn lần để đảm bảo rằng tôi 'không đo lường chúng trong một khoảng thời gian quá nhỏ). Tôi bị bối rối bởi những kết quả này.Chương trình OpenCV/C++ chậm hơn so với chương trình của nó, tôi nên làm gì?
Tôi đã sử dụng gprof để cố gắng hiểu điều gì đang diễn ra, nhưng tôi không thể nói được nhiều sai lầm, ngoài thực tế là cv :: Mat :: ~ Mat() đang chiếm 34,67% số lần thực thi thời gian và được gọi là hơn 100 lần so với bất kỳ chức năng nào khác. Không chắc chắn tôi nên làm gì về điều đó, trừ khi tôi phải thay thế cv :: Mats cho std :: vectơ hoặc mảng thô, cả hai đều có vẻ như là một hành động xấu với tôi.
void align(const cv::Mat& points, const cv::Mat& pointsRef, cv::Mat& res, cv::Mat& ops) {
cv::Mat pts(points.rows, points.cols, CV_64FC1);
cv::Mat ptsRef(points.rows, points.cols, CV_64FC1);
points.copyTo(pts);
pointsRef.copyTo(ptsRef);
cv::Mat avgs = meanOfColumns(pts);
for(int i = 0; i < avgs.cols; i++) {
pts.col(i) -= avgs.col(i);
}
cv::Mat avgsR = meanOfColumns(ptsRef);
for(int i = 0; i < avgsR.cols; i++) {
ptsRef.col(i) -= avgsR.col(i);
}
cv::Mat x2(pts.rows, 1, CV_64FC1);
cv::Mat y2(pts.rows, 1, CV_64FC1);
cv::Mat x2R(pts.rows, 1, CV_64FC1);
cv::Mat y2R(pts.rows, 1, CV_64FC1);
cv::pow(pts.col(0), 2, x2);
cv::pow(pts.col(1), 2, y2);
cv::pow(ptsRef.col(0), 2, x2R);
cv::pow(ptsRef.col(1), 2, y2R);
cv::Mat sqrootP(pts.rows, 1, CV_64FC1);
cv::Mat sqrootPR(pts.rows, 1, CV_64FC1);
cv::sqrt(x2R + y2R, sqrootPR);
cv::sqrt(x2 + y2, sqrootP);
double offsetS = (cv::mean(sqrootPR)/cv::mean(sqrootP))[0];
pts *= offsetS;
cv::Mat rot(pts.rows, 1, CV_64FC1);
cv::Mat rotR(pts.rows, 1, CV_64FC1);
rot = arctan2(pts.col(1), pts.col(0));
rotR = arctan2(ptsRef.col(1), ptsRef.col(0));
double offsetR = -cv::mean((rot - rotR))[0];
cv::Mat angRot(pts.rows, 1, CV_64FC1);
angRot = rot + offsetR;
cv::Mat dist(pts.rows, 1, CV_64FC1);
cv::pow(pts.col(0), 2, x2);
cv::pow(pts.col(1), 2, y2);
cv::sqrt(x2 + y2, dist);
copyColumn(dist.mul(cosine(angRot)), res, 0, 0);
copyColumn(dist.mul(sine(angRot)), res, 0, 1);
ops.at<double>(0, 0) = -avgs.at<double>(0, 0);
ops.at<double>(0, 1) = -avgs.at<double>(0, 1);
ops.at<double>(0, 2) = offsetS * cv::cos(offsetR/RADIANS_TO_DEGREES);
ops.at<double>(0, 3) = offsetS * cv::sin(offsetR/RADIANS_TO_DEGREES);
}
Đây là mã để căn chỉnh 2 bộ điểm. Nó gọi một số chức năng không được hiển thị, nhưng chúng đơn giản và tôi có thể giải thích chúng nếu cần thiết, mặc dù tôi hy vọng rằng những cái tên đó là đủ để hiểu những gì chúng làm.
Tôi là một lập trình viên C++ bình thường, dễ dàng với các bạn.
Dường như Ignacio Vazquez-Abrams có ý tưởng đúng. Ví dụ ngắn gọn/trực tiếp hơn:
#include <boost/date_time/posix_time/posix_time.hpp>
#include <cv.hpp>
#include <iostream>
using namespace boost::posix_time;
int main() {
cv::Mat m1(1000, 1000, CV_64FC1);
cv::Mat m2(1000, 1000, CV_64FC1);
ptime firstValue(microsec_clock::local_time());
for(int i = 0; i < 10; i++) {
cv::Mat m3 = m1 * m2;
}
ptime secondValue(microsec_clock::local_time());
time_duration diff = secondValue - firstValue;
std::cout << diff.seconds() << "." << diff.fractional_seconds() << " microsec" << std::endl;
}
Mất khoảng 14 giây trong máy của tôi. Bây giờ Python:
import datetime
import numpy as np
if __name__ == '__main__':
print datetime.datetime.now()
m1 = np.zeros((1000, 1000), dtype=float)
m2 = np.zeros((1000, 1000), dtype=float)
for i in range(1000):
m3 = np.dot(m1, m2)
print datetime.datetime.now()
Đó mất 4+ giây, mặc dù C++ ví dụ chỉ làm việc đó 10 lần, trong khi Python (Fortran) ai làm việc đó 1000.
Vâng okay, cập nhật thời gian.
Tôi đã xem lại mã Python tôi đang sử dụng và nhận ra rằng nó chỉ tải một tập con của các điểm (khoảng 5%) ... Điều đó có nghĩa là các kiểm tra C++ của tôi thực sự chạy nhiều hơn 20 lần so với mã Python. mã C++ thực sự nhanh hơn khoảng 10 lần, vì mã chỉ chậm gấp hai lần. Nó vẫn có vẻ như numpy có OpenCV đánh bại trong một số hoạt động mặc dù.
Mã hoặc nó không xảy ra. –
Vui lòng đăng một số mã đại diện. Không thể nói mà không có thêm chi tiết. –
Bạn không so sánh C++ với Python, bạn đang so sánh C++ với Fortran. Nếu đó là số crunching, sau đó Fortran * sẽ * giành chiến thắng. –