用OpenMP替换TBB parallel_for

时间:2014-01-03 16:12:41

标签: c++ multithreading openmp tbb parallel-for

我正在尝试使用OpenMP来替换使用parallel_for的英特尔TBB tbb::blocked_range循环。在网上挖掘,我只是设法找到另外一个做类似事情的人;提交给Open Cascade项目的补丁,其中TBB循环如此出现(但没有使用tbb :: blocked_range):

tbb::parallel_for_each (aFaces.begin(), aFaces.end(), *this);

和OpenMP等价物是:

int i, n = aFaces.size();
#pragma omp parallel for private(i)
for (i = 0; i < n; ++i)
    Process (aFaces[i]);

这是TBB循环,我试图取代:

tbb::parallel_for( tbb::blocked_range<size_t>( 0, targetList.size() ), DoStuff( targetList, data, vec, ptr ) );

它使用DoStuff类来执行工作:

class DoStuff
{
private:
    List& targetList;
    Data* data;
    vector<things>& vec;
    Worker* ptr;

public:
    DoIdentifyTargets( List& pass_targetList, 
                       Data* pass_data, 
                       vector<things>& pass_vec, 
                       Worker* pass_worker) 
        : targetList(pass_targetList), data(pass_data), vecs(pass_vec), ptr(pass_worker)
    {
    }

    void operator() ( const tbb::blocked_range<size_t> range ) const
    {
        for ( size_t idx = range.begin(); idx != range.end(); ++idx )
        {
            ptr->PerformWork(&targetList[idx], data->getData(), &Vec);
        }
    }
};

我的理解based on this reference是TBB会将阻塞的范围划分为更小的子集,并为每个线程提供一个范围循环。由于每个线程都会得到自己的DoStuff类,它有一堆引用和指针,这意味着线程实际上是在共享这些资源。

这是我在OpenMP中作为等效替代品提出的:

int index = 0;
#pragma omp parallel for private(index)
for (index = 0; index < targetList.size(); ++index)
{
    ptr->PerformWork(&targetList[index], data->getData(), &Vec);
}

由于我无法控制的情况(这只是一个跨越+5计算机的大型系统中的一个组件)通过调试器逐步查看代码以确切地看到正在发生的事情......不太可能。我正在努力进行远程调试,但看起来并不是很有希望。我所知道的是,上面的OpenMP代码在某种程度上与TBB不同,并且没有获得为每个索引调用PerformWork后的预期结果。

鉴于上述信息,是否有人对OpenMP和TBB代码在功能上不相同的原因有任何想法?

1 个答案:

答案 0 :(得分:0)

根据Ben和Rick的建议,我在没有omp pragma(连续)的情况下测试了以下循环,并获得了我预期的结果(非常慢)。重新添加pragma后,并行代码也会按预期执行。看起来问题在于将索引声明为循环外部的私有,或者在循环内将numTargets声明为私有。或两者兼而有之。

    int numTargets = targetList.size();
    #pragma omp parallel for
    for (int index = 0; index < numTargets; ++index)
    {
        ptr->PerformWork(&targetList[index], data->getData(), &vec);
    }