我一直在尝试并行化嵌套循环,如下所示:
我正在比较此代码的顺序版本和并行版本的执行时间,但顺序版本似乎总是具有更短的执行时间和各种输入?
该计划的输入是:
我环顾网络并尝试了一些事情(现在)并没有真正改变。我很确定并行代码是正确的,因为我检查了输出。我在这里做错了吗?
编辑:另外,似乎你不能在C结构上使用减少条款?EDIT2:使用2核心cpu在linux上使用gcc。我试过运行它的值高达numParticles = 40和numTimeSteps = 100000.也许我应该尝试更高?
谢谢
答案 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实现,都可以确保同一组线程贯穿整个计算。