For loop OpenMP C并行化嵌套循环速度慢

For loop OpenMP C并行化嵌套循环速度慢,for-loop,parallel-processing,openmp,For Loop,Parallel Processing,Openmp,我一直在尝试并行化嵌套循环,如下所示: 我正在比较这段代码的顺序版本和并行版本的执行时间,但是顺序版本在各种输入下似乎总是有更短的执行时间 程序的输入为: numParticles(循环索引) timeStep(不重要,值不变) numTimeSteps(循环索引) numThreads(要使用的线程数) 我环顾了一下网络,尝试了一些东西(nowait),但没有什么真正的改变。我很确定并行代码是正确的,因为我检查了输出。我在这里做错什么了吗 编辑:而且,似乎你不能在C结构上使用reduce

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

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

程序的输入为:

  • numParticles(循环索引)
  • timeStep(不重要,值不变)
  • numTimeSteps(循环索引)
  • numThreads(要使用的线程数)
我环顾了一下网络,尝试了一些东西(nowait),但没有什么真正的改变。我很确定并行代码是正确的,因为我检查了输出。我在这里做错什么了吗

编辑:而且,似乎你不能在C结构上使用reduce子句

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


谢谢

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

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


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

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

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


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

我可以想到两个可能的减速来源:a)编译器在顺序版本中进行了一些优化(首先是矢量化),但在OpenMP版本中没有,以及b)线程管理开销。如果还使用单个线程运行OpenMP版本(即,将numThreads设置为1),则很容易检查这两个版本。如果它比顺序慢得多,那么(a)是最可能的原因;如果它类似于sequential,并且比具有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 */
    }
}

对于(t=0;t我可以想到两个可能的减速来源:a)编译器在顺序版本中进行了一些优化(首先是矢量化),但在OpenMP版本中没有,以及b)线程管理开销。如果还使用单个线程运行OpenMP版本(即,将numThreads设置为1),则很容易检查这两个版本。如果它比顺序慢得多,那么(a)是最可能的原因;如果它类似于sequential,并且比具有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 */
    }
}


用于(t=0;t您使用的编译器是什么?numParticles的值是多少?您的CPU有多少个内核?在linux上使用gcc。numParticles是40,numTimeSteps是100000。CPU有2个内核。我尝试了这两个变量的更高值,但结果仍然是samenumTimeSteps应该没有影响,因为它在并行区域之外。是吗ou启用openmp?(我认为gcc中的-fopenmp)正常。numParticles=200,numTimeSteps=100会发生什么?有两个线程,非线程版本=0秒,线程版本=1秒。我也尝试了500 10000,非线程版本更快(184秒对155秒)您使用的编译器是什么?numParticles的值是多少?您的CPU有多少个内核?在linux上使用gcc。numParticles是40,numTimeSteps是100000。CPU有2个内核。我尝试了这两个变量的更高值,但结果仍然是samenumTimeSteps应该没有影响,因为它在并行区域之外。您是否启用了g openmp?(我认为gcc中的-fopenmp)可以。numParticles=200,numTimeSteps=100会发生什么?有两个线程,非线程版本=0秒,线程版本=1秒。我也尝试了500 10000,非线程版本更快(184秒对155秒)哦,很好,知道它至少可以工作。我在linux上用gcc编译器运行它,这有什么区别吗?有。创建线程的开销可能更大。OpenMP实现可能略有不同。请尝试使用更多的粒子(例如500个)然后看看会发生什么。确保您已经在gcc命令行上启用了OpenMP支持。哦,很高兴知道它至少可以工作。我正在使用gcc编译器在linux上运行此程序。这有什么区别吗?有。创建线程的开销可能会更大。OpenMP实现可能会略有不同。请尝试更多的particles(例如500)并查看发生了什么。确保您在gcc命令行上启用了OpenMP支持。我也在考虑优化…可能是自动矢量化。但您可能认为编译器也会对子循环执行相同的操作?我有点不明白为什么并行区域可以在ti之前启动