我正在尝试实现openMP,但就像我之前的许多其他海报一样,结果只是放慢了代码的速度。受到之前答案的启发,我从使用#pragma omp parallel for
转到#pragma omp task
,希望能避免一些开销。不幸的是,并行化代码仍然是串行代码的两倍。从其他答案来看,似乎正确的程序取决于代码的具体要求,这就是为什么我认为我必须自己提出问题。
首先是伪代码:
#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循环之外,以减少创建团队的开销。
我也有点好奇我是否正确使用taskwait - 规范声明“父任务”被搁置直到所有子任务都被执行,但不清楚这个术语是否也适用于此,任务区域没有嵌套的地方。
任何人都可以想出一个更好的使用openMP的方式,这样我才能真正加速吗?
编辑:while循环中的每个步骤都取决于之前的所有步骤,因此必须按顺序完成,最后更新。如果有人想知道的话,它是用于模拟神经网络的“事件驱动算法”的实现。答案 0 :(得分:2)
对于并行编程,您还应该以一种很少需要同步线程的方式设计问题。每次同步线程时,您将获得所有线程的最差性能。如果您需要同步线程,请尝试重新设计问题,以避免这些同步。
将代码从#pragma omp parallel for
调整为#pragma omp task
将无法获得任何重大改进,因为他们的执行时间差异通常可以忽略不计。在尝试调整一些例程调用或omp语句之前,您需要调整问题以适应并行执行。您需要真正考虑“并行”才能获得良好且可扩展的性能提升,只需调整序列代码即可。
在你的代码中,你应该尝试并行化while循环而不是内部for循环。如果你将小for循环平行化,你将不会获得任何显着的性能提升。
答案 1 :(得分: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)
}
}
}
同样重要的是要记住,对于并行执行,for循环中的任务可能很小,以提供任何加速,因为启动和同步线程会产生开销。您还应该考虑重写程序的可能性,这样您就不需要同步线程了,您现在做了很多。我的猜测是你的算法和工作负载实际上对于并行执行来说很小,因为它现在就可以提供任何加速。
答案 2 :(得分:0)
你还记得相应地设置你的环境变量吗? OMP_NUM_THREADS = N,其中N是处理器支持的线程数或核心数