使用OpenMP非常奇怪的行为

时间:2015-09-29 15:16:54

标签: c++ opencv openmp

现在,我一直在使用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;
}

奇怪的是,它至少在我的另一台计算机上运行,​​至少......

注意:关于将ij设为私有的一些评论,我已将其设为私有,但在学校的计算机上没有帮助。

抱歉,忘了写关于操作系统和硬件的信息。它是一个包含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的东西还有问题?

0 个答案:

没有答案