openMP的循环运行速度比串行代码慢

时间:2015-09-18 12:59:54

标签: c++ parallel-processing openmp

我有一段代码,我试图并行运行,但是,由于某种原因它不会提高速度。

代码执行一组新找到的keyPoints和较旧找到的keyPoints之间的匹配,然后在500次迭代中执行RANSAC。

由于每对都是相互独立的,我希望做匹配和RANSAC可以提高速度。

以下是代码:

Eigen::VectorXf RigidChainTracker::GPUgetCamera(cv::Mat depthNew, cv::Mat colorNew, cv::Mat grayNew, deque<imgPair> oldImg, const Eigen::VectorXf &XiInit,
    vector<cv::KeyPoint> foundPtsNew, cv::Mat descriptorNew, const float alpha){

    vector<cv::KeyPoint> matchedOld[CHAINLENGTH];
    vector<cv::KeyPoint> matchedNew[CHAINLENGTH];

    FindFeatures::FindFeatures fFeatures[CHAINLENGTH];
    for (int i = 0; i < CHAINLENGTH; ++i){
        fFeatures[i] = FindFeatures::FindFeatures(METHOD, fx, fy, cx, cy);
    }
    double t1 = omp_get_wtime(); 
    int i = 0;
    int chainlength = CHAINLENGTH;
    vector<cv::KeyPoint> keyPtsNew[CHAINLENGTH];
    vector<cv::KeyPoint> keyPtsOld[CHAINLENGTH]; 
    const float THRESHOLD = 0.02;
    Eigen::Matrix3f Rrel[CHAINLENGTH];
    Eigen::Vector3f trel[CHAINLENGTH];

#pragma omp parallel for private (i) shared(fFeatures,matchedNew, matchedOld, depthNew, colorNew, grayNew, oldImg,descriptorNew,foundPtsNew, keyPtsNew, keyPtsOld,Rrel,trel, chainlength, THRESHOLD) 
    for (i = 0; i < chainlength; ++i){
        if (i < oldImg.size()){
            fFeatures[i].MatchFeatures(depthNew, oldImg[i].depth, descriptorNew, oldImg[i].descriptor, foundPtsNew, oldImg[i].foundPts, keyPtsNew[i], keyPtsOld[i]);
            fFeatures[i].RANSAC3D(depthNew, oldImg[i].depth, keyPtsNew[i], keyPtsOld[i],  Rrel[i], trel[i],THRESHOLD);


            matchedNew[i] = keyPtsNew[i]; 
            matchedOld[i] = keyPtsOld[i];
        } 
    }

当串行运行时,它以大约2-5赫兹的速度运行,但OpenMp略慢。我尝试了一些不同的东西,但我无法做到。尝试从同一个内存中读取时可能会有些奇怪,例如从depthNew或descriptorNew读取时。我将信息写入MatchFeatures和RANSAC3D中的keyPtsNew,keyPtsOld,matchedNew,matchedOld,Rrel和trel。从图像depthNew和descriptorNew,我只读取信息。串口代码真的可能更快吗?

我已经确认正在执行多个线程并且启用了visual studio中的openMP标志。 :)

我已经尝试过Avi Ginsburg的建议,它加快了并行部分的速度,但串行代码仍然更快。

我将不同功能的MatchFeatures和RANSAC3D定时。当串行运行时,每个任务最多需要0.05秒。

当并行运行时,每个任务需要0.1到0.15秒,相当慢。我试图弄清楚OpenCV是否存在一些我不知道的并行化。例如,在匹配过程中或其他任何内容。

/ Erik

1 个答案:

答案 0 :(得分:2)

Erik,由于编译器执行了CACHE和流水线优化,因此串行代码运行速度比并行代码更快是可能的。

在你的情况下,由于线程之间共享大量变量,似乎就是这种情况。 共享变量具有同步开销,会影响性能。 我相信可以通过将OMP循环分成两部分来解决。第一个执行计算并创建一个新的结果数组。第二个循环遍历执行匹配的旧数组和新数组。

在并行编程中,由于设备延迟和频带限制,将值从内存传输到CACHE和寄存器的时间成本通常很大,将数据复制到每个线程的CACHE,计算它,可能是值得的,然后减少结果,而不是在线程和进程之间不断共享它以避免重复。这意味着内存优化程度较低的代码段实际上可以提高性能。