现在,我一直在使用OpenMP得到糟糕的结果,所以它一定是我不明白的东西。目前,我在没有OpenMP的情况下运行的for循环上有非常奇怪的行为。这是该计划的大纲:
void computeAandB(Xi, XiDX, XiDY, XiDZ, depthImg){
double tstart = omp_get_wtime();
cv::Mat Error = rayCast(Xi, depthImg);
cv::Mat ErrorDX = rayCast(XiDX, depthImg);
cv::Mat ErrorDY = rayCast(XiDY, depthImg);
cv::Mat ErrorDZ = rayCast(XiDZ, depthImg);
float A1 = 0;
float b1 = 0;
for (i = 0; i < rows; ++i){
for (j = 0; j < cols; ++j){
V0 = Error(i,j);
V0DX = ErrorDX(i,j);
V0DY = ErrorDY(i,j);
V0DZ = ErrorDZ(i,j);
VectorXf grad = computeGrad(V0,V0DX,V0DY,V0DZ);
A1 += grad(0);
b1 += grad(1);
}
}
double t2 = omp_get_wtime();
cout<<"Time for everything: "<< t2 - t1 <<endl;
当我连续运行所有内容时,每个光线投射大约需要0.8秒,总和为1.1秒。
当我使用OpenMP并行运行rayCast中的for循环时,它在大约0.2秒内运行,但是在四次调用rayCast之后的循环大约需要115秒!甚至没有使用openMp。我没有看到任何逻辑,为什么之后的循环会如此缓慢?目前我只是对上面编写的代码进行计时,即在所有rayCasts和for循环之间进行计时。
我从rayCast获得的图片看起来都很好,所以该功能有效。
这是rayCast功能:
cv::Mat ModelTracker::rayCast(const Eigen::VectorXf &Xi, const cv::Mat &depthImg)
{
LieAlgebra::LieAlgebra Lie;
cv::Mat tmp = cv::Mat::zeros(depthImg.rows, depthImg.cols, CV_32FC1);
Eigen::Matrix3f R = Lie.getRotation(Xi);
Eigen::Vector3f t = Lie.getTranslation(Xi);
int i, j;
#pragma omp parallel for private (i,j) shared(R,t,tmp)
for (i = 0; i < depthImg.rows; ++i){
for (j = 0; j < depthImg.cols; ++j){
const float z = depthImg.at<float>(i, j);
if (!isnan(z)){
Eigen::Vector3f pLocal = reproject3f(j, i, z);
Eigen::Vector3f pGlobal = R*pLocal + t;
Eigen::Vector3f ray = (pGlobal - t);
float pointDist = ray.norm();
ray.normalize();
/* cout << "norm ray" << endl;
cout << ray.norm() << endl;
getchar();*/
float d = traverseRay(ray, t,pointDist);
//cout << "d: " << d << endl;
//cout << "t + d*ray: " << t + d*ray << endl;
//cout << " t + pointDist*ray: " << t + pointDist*ray << endl;
//cout << endl;
//cout << "pGlobal: " << pGlobal << endl;
//getchar();
float err = (pointDist - d);
//float SDF = interpolate(pGlobal);
//cout << "err SDF: "<< err << " " << SDF << endl;
//getchar();
if (fabs(err) > RAYTHRESHOLD){
float sign = err / fabs(err);
err = sign*RAYTHRESHOLD;
}
tmp.at<float>(i, j) = (err);
}
else {
tmp.at<float>(i, j) = NAN;
}
}
}
return tmp;
}
奇怪的是,它至少在我的另一台计算机上运行,至少......
注意:关于将i
和j
设为私有的一些评论,我已将其设为私有,但在学校的计算机上没有帮助。
抱歉,忘了写关于操作系统和硬件的信息。它是一个包含6个物理内核的Windows 7发行版,我运行的是Visual Studio 2013,启用了OpenMP并优化了快速代码。
更新: 我刚刚重新启动计算机并再次运行程序。前七次computeAandB共计1.8秒。然后接下来的四个每个花了91秒!然后每次通话回到1.8秒。可能是某些设置错了吗?我在发布模式下运行它,但是它可能是其他一些设置使它有时在调试中运行吗?
另一个奇怪的事情是,如果我在rayCast中使用OpenMP,然后在computeAandB中执行此操作:
cv::Mat Error = rayCast(Xi, depthImg);
cv::Mat ErrorDX = rayCast(XiDX, depthImg);
cv::Mat ErrorDY = rayCast(XiDY, depthImg);
cv::Mat ErrorDZ = rayCast(XiDZ, depthImg);
cv::imshow("Error",Error);
cv::waitKey(0)
这样我就可以显示图像并等待在串行for循环之前按下一个键。然后串行for循环按预期工作。计算不需要130秒。好像来自openMP的东西还有问题?