OpenMP C并行嵌套for循环缓慢

时间:2011-08-21 01:44:33

标签: for-loop parallel-processing openmp

我一直在尝试并行化嵌套循环,如下所示:

http://pastebin.com/nkictYsw

我正在比较此代码的顺序版本和并行版本的执行时间,但顺序版本似乎总是具有更短的执行时间和各种输入?

该计划的输入是:

  • numParticles(循环索引)
  • timeStep(不重要,值不会改变)
  • numTimeSteps(循环索引)
  • numThreads(要使用的线程数)

我环顾网络并尝试了一些事情(现在)并没有真正改变。我很确定并行代码是正确的,因为我检查了输出。我在这里做错了吗?

编辑:另外,似乎你不能在C结构上使用减少条款?

EDIT2:使用2核心cpu在linux上使用gcc。我试过运行它的值高达numParticles = 40和numTimeSteps = 100000.也许我应该尝试更高?

谢谢

2 个答案:

答案 0 :(得分:1)

您的循环可能太小。创建线程以处理循环的一部分会产生开销,因此如果循环太小,并行化版本可能会运行得更慢。另一个考虑因素是可用核心数量。

您的第二个omp指令不太可能有用,因为该循环中的计算量要少得多。我建议删除它。

编辑:我用numParticles 1000和两个线程测试了你的代码。它跑了30秒。单线程版本在57秒内运行。即使使用numParticles 40,我也看到了显着的加速。这是Visual Studio 2010。

答案 1 :(得分:0)

我可以想到两个可能的减速源:a)编译器在顺序版本中进行了一些优化(矢量化是第一个)但在OpenMP版本中没有,b)线程管理开销。如果您还使用单个线程运行OpenMP版本(即将numThreads设置为1),则两者都很容易检查。如果它比顺序慢得多,则(a)是最可能的原因;如果它类似于顺序并且比具有2个线程的相同代码更快,则最可能的原因是(b)。

在后一种情况下,您可以重新构建OpenMP代码,以减少开销。首先,不需要在循环内部具有两个平行区域(#pragma omp parallel);你可以在里面有一个平行的区域和两个平行的循环:

for (t = 0; t <= numTimeSteps; t++) {
    #pragma omp parallel num_threads(numThreads)
    {
    #pragma omp for private(j)
    /* The first loop goes here */
    #pragma omp for
    /* The second loop goes here */
    }
}

然后,可以在时间步循环之前启动并行区域:

#pragma omp parallel num_threads(numThreads) private(t)
for (t = 0; t <= numTimeSteps; t++) {
    ...
}

该区域中的每个线程都将运行此循环,并且在每次迭代时,线程将在OpenMP循环结束时进行同步。这样,无论使用何种OpenMP实现,都可以确保同一组线程贯穿整个计算。