OpenMP不会使用所有核心?

时间:2011-09-26 17:38:16

标签: c++ stl openmp

我正在尝试使用OpenMP来使一些代码并行。

    omp_set_num_threads( 8 );
    #pragma omp parallel 
    for (int i = 0; i < verSize; ++i)
    {
        #pragma omp single nowait
        { 
            neighVec[i].index = i;
            mesh.getBoxIntersecTets(mesh.vertexList->at(i), &neighVec[i]);
        }
    }

verSize大约是90k,getBoxIntersecTets非常昂贵。所以我希望代码能够充分利用四核CPU。 但是CPU使用率仅为25%左右。 有什么想法吗?

我也尝试过使用omp parallel for construct,但同样的故事。

getBoxIntersecTets使用STL unordered_set,vector和deque,但我想OpenMP应该对它们不可知,对吧?

感谢。

1 个答案:

答案 0 :(得分:5)

首先,#pragma omp single禁用并行执行,你肯定不希望这样。


请改为尝试:

#pragma omp parallel for private(tempVec)
for (int i = 0; i < verSize; ++i)
{
    auto tempVec = neighVec[i];
    tempVec.index = i;
    mesh.getBoxIntersecTets(mesh.vertexList->at(i), &tempVec);
    neighVec[i] = tempVec;
}

原始代码的问题在于不同的线程正在使用数组的相邻元素。相邻元素在内存中彼此相邻放置,这意味着它们可能共享一个缓存行。由于只有一个核心可以同时拥有一个缓存行,因此只有一个核心可以一次完成工作。或者更糟糕的是,您的程序可能花费更多时间来转移缓存行的所有权而不是实际工作。

通过引入临时变量,每个工作人员可以在独立的缓存行上运行,然后您只需要访问末尾的共享缓存行来存储结果。如果第一个参数是由非const引用传递的,那么你应该对它做同样的事情。