为了在OpenCV中测试并行for循环,我创建了以下代码,它只需要一个矩阵并进行一些操作并输出另一个矩阵。并行代码应该给出与串行代码给出的相同的结果。但事实并非如此。
在编译代码之前,确保您已经在OpenCV中正确启用并安装了TBB 。 (否则将不考虑并行化并将其视为序列代码,因此您显然会获得相同的结果。)
#include <opencv2/core/core.hpp>
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
class Parallel_process : public cv::ParallelLoopBody
{
private:
const Mat& im;
Mat& out;
int r;
public:
Parallel_process(const Mat& inputIm, int radius, Mat& outputIm)
: im(inputIm), out(outputIm), r(radius){}
virtual void operator()(const cv::Range& range) const
{
//cout << "start=" << range.start<< " end=" << range.end<<endl;
//cout << endl;
for(int y = range.start; y < range.end; y++)
{
//cout << " " << y;
for(int x=0; x< im.cols - r; x++)
{
out(Rect(x,y,r,r)) = im(Rect(x,y,r,r))*im(Rect(x,y,r,r));
//cout<<im(Rect(x,y,r,r))<<endl;
}
}
}
};
int main(int , char** )
{
double start, timeSec;
int n = 5, r = 2;
/// Define a matrix
Mat M = Mat(n, n, CV_32F);
//randu(M, 0, 1);
for(int y=0; y< M.rows; y++)
{
for(int x=0; x< M.cols; x++)
{
M.at<float>(x,y) = abs(x-y);
}
}
//cout<<M<<endl;
Mat M1 = M.clone();
Mat M2 = M.clone();
/// Serial loop
start = (double)getTickCount();
for(int y=0; y< M1.rows - r; y++)
{
for(int x=0; x< M1.cols - r; x++)
{
M1(Rect(x,y,r,r)) = M(Rect(x,y,r,r))*M(Rect(x,y,r,r));
}
}
timeSec = (getTickCount() - start) / getTickFrequency();
cout << "Non parallel time: " << timeSec << "s" << endl;
//cout<<M1<<endl;
/// Parallel loop
start = (double)getTickCount();
parallel_for_(Range(0,(int)M2.rows-r), Parallel_process(M,r,M2));
timeSec = (getTickCount() - start) / getTickFrequency();
cout << "Parallel time: " << timeSec << "s" << endl;
//cout<<M2<<endl;
/// Check the results
cout << "Check: norm(M1-M2)=" << norm(M1-M2) << endl;
return 0;
}
通过执行获得的二进制文件,我获得了非常随机的结果(即使使用相同的二进制文件,即编译一次但执行了几次)。
希望有人可以帮忙解决这个问题。提前谢谢。
答案 0 :(得分:3)
我猜计算结果时out矩阵有重叠: out(Rect(x,y,r,r))重叠(Rect(x +,y + 1,r,r)),对于r> 1。 1.因此在顺序执行中,在顺序扫描图像之后的最后计算结果总是存储在输出矩阵中,而在并行计算中,图像的扫描不再是连续的,因此线程可能会覆盖其他线程结果