2012-02-19 48 views
2

我想实现openMP,但是像我之前的很多其他海报一样,结果只是简化了代码。受到以前答案的启发,我从#pragma omp parallel for#pragma omp task去了,希望能避免一些开销。不幸的是,并行代码仍然是串行速度的两倍。从其他答案看来,正确的过程似乎取决于代码的具体要求,这就是为什么我认为我必须自己提问。使用openmp更好

第一伪代码:

#pragma omp parallel 
{ 
#pragma omp master 
while (will be run some hundreds of millions of times) 
{ 
    for (between 5 and 20 iterations) 
    { 
     #pragma omp task 
     (something) 
    } 
    #pragma omp taskwait <- it is important that all the above tasks are completed before going on 

    (something) 

    if (something) 
    { 
     (something) 

     for (between 50 and 200 iterations) 
     { 
      #pragma omp task 
      (something) 
     } 
     #pragma omp taskwait 

     (something) 
    } 

} 
} 

只有两个for循环可以并行,其余的必须按正确的顺序进行。我想出了将while和master指令放在while循环之外的尝试,以减少创建团队的开销。

我也有点好奇我是否正确使用了taskwait - 规范说明“父任务”被搁置,直到所有的子任务都被执行完毕,但这个术语是否也适用于此,任务区域不嵌套。

任何人都可以想出一个更好的方式使用openMP,这样我实际上可以加快速度吗?

编辑:while循环中的每一步都依赖于前面的所有步骤,因此它们必须连续完成,并在最后进行更新。如果有人想知道,它是模拟神经网络的“事件驱动算法”的实现。

+0

for循环的每次迭代需要多长时间?如果任务规模很小,很可能无法在这里获得加速。此外为什么'#pragma omp task'会更快,然后'#pragma omp for'?毕竟后者应该能够以更少的管理开销逃脱。对我来说,似乎如果速度更快,那么您的情况可能使用了错误的调度模式。关于taskwait:据我了解,'master'部分应该是你的父任务(或者'parallel'部分,但似乎不太可能) – Grizzly 2012-02-19 19:43:49

+0

我知道任务会更快,因为对一个老问题的回答说了些什么“如果for循环中的迭代次数太少,则最好使用任务代替”。在序列情况下,1.7秒内可能经历10000次while循环。考虑到其他设置,对于第二个for循环的每次迭代,球估计将为1.0-0.5微秒。我知道它很短,但被告知我低估了并行化的力量,并决定给它一个镜头:) – Kaare 2012-02-19 19:54:02

+0

这听起来好像你需要考虑新算法或新的并行处理范例,或者可能甚至两个。 – talonmies 2012-02-19 20:07:34

回答

2

对于并行编程,您还应该设计您的问题,以便您很少需要同步您的线程。每次你同步你的线程时,你将得到所有线程中最差的性能。如果您需要同步您的线索,请尝试重新设计您的问题,以避免这些同步。

将您的代码从#pragma omp parallel for调整为#pragma omp task不会让您有任何重大改进,因为它们的执行时间差别通常是可忽略的。在尝试调整一些常规调用或omp语句之前,您需要将问题调整为并行执行。您需要真正地以“并行”思考才能获得良好的可扩展性能增长,只是适应串行代码很少有效。

在你的代码中,你应该尝试parallize while循环而不是内循环。如果你将小型for循环合并,你不会得到任何显着的性能提升。

+0

恐怕这是完全不可能的。我意识到它在上面并不明显,但while循环中的每个迭代都依赖于前面的循环,所以它们必须按顺序进行。 – Kaare 2012-02-19 19:35:10

+1

然后尝试重新设计您的问题,以获得独立的循环。否则,你会浪费你的时间调整并行执行不好的代码。 – tune2fs 2012-02-19 19:48:51

0

我不确定任务是否正确。我不熟悉任务,但似乎每次遇到#pragma omp task时都会启动一个线程。我宁愿尝试类似:

while (will be run some hundreds of millions of time) 
{ 
#pragma omp parallel 
{ 
    for (between 5 and 20 iterations) 
    { 
     (something) 
    } 
#pragma omp single/master 
{ 

    (something) 
    bool flag = false; 
    if (something) 
    { 
     (something) 
     flag = true; 
    } 
} 

    if (flag) 
    { 
     for (between 50 and 200 iterations) 
     { 
      (something) 
     } 
    } 
#pragma omp single/master 
{ 
      (something) 
} 
    } 
    } 

同样重要的是要记住的是,在该任务的循环可能是小的并行执行提供任何加速,因为在启动和同步线程的开销。你也应该看看重写你的程序的可能性,所以你不需要同步你的线程,你现在做了很多。我的猜测是,你的算法和工作量对于并行执行来说实际上很小,因为它现在写入的速度很快。

+1

这会每次迭代n次(其中n是线程数),所以确实没有任何好处。使用任务不会启动新线程,而是使用当前队伍的线程,这些线程目前处于保持状态(不完全正确但足够接近) – Grizzly 2012-02-19 19:41:46

0

您是否记得相应地设置环境变量? OMP_NUM_THREADS = N,其中N是处理器支持的线程或核心的数量

+0

我没有触及环境变量,但让“#pragma omp parallel”自己弄清楚。我的各种版本的“hello world”显示了正确的输出数量(2)。 – Kaare 2012-02-19 20:09:59

+0

好奇你是否尝试在串行中运行代码? – pyCthon 2012-02-19 20:31:26

+0

你是什么意思?以上?是的,如果我不向g ++提供“-fopenmp”,代码将以串行方式运行。这就是我可以说平行版太慢的原因。我是否正确理解你的问题? – Kaare 2012-02-19 20:44:55