openmp递归任务示例比顺序慢
Posted
技术标签:
【中文标题】openmp递归任务示例比顺序慢【英文标题】:openmp recursive tasks example slower than sequential 【发布时间】:2013-02-06 18:53:25 【问题描述】:我刚刚开始研究 OpenMP 并一直在阅读任务。看来 Sun 这里的示例实际上比顺序版本慢。我相信这与任务创建和管理的开销有关。它是否正确?如果是这样,有没有办法在不改变算法的情况下使用任务让代码更快?
int fib(int n)
int i, j;
if (n<2)
return n;
else
#pragma omp task shared(i) firstprivate(n)
i=fib(n-1);
#pragma omp task shared(j) firstprivate(n)
j=fib(n-2);
#pragma omp taskwait
return i+j;
【问题讨论】:
【参考方案1】:唯一明智的方法是将并行度削减到一定水平,低于此水平没有意义,因为开销变得大于正在完成的工作。最好的方法是拥有两个独立的fib
实现——一个串行实现,比如说fib_ser
,一个并行实现,fib
——并在给定阈值下在它们之间切换。
int fib_ser(int n)
if (n < 2)
return n;
else
return fib_ser(n-1) + fib_ser(n-2);
int fib(int n)
int i, j;
if (n <= 20)
return fib_ser(n);
else
#pragma omp task shared(i)
i = fib(n-1);
#pragma omp task shared(j)
j = fib(n-2);
#pragma omp taskwait
return i+j;
这里的阈值是n == 20
。它是任意选择的,它的最佳值在不同的机器和不同的 OpenMP 运行时会有所不同。
另一种选择是使用if
子句动态控制任务:
int fib(int n)
int i, j;
if (n<2)
return n;
else
#pragma omp task shared(i) if(n > 20)
i=fib(n-1);
#pragma omp task shared(j) if(n > 20)
j=fib(n-2);
#pragma omp taskwait
return i+j;
如果n <= 20
,这将关闭两个显式任务,并且代码将以串行方式执行,但 OpenMP 代码转换仍会产生一些开销,因此它会比使用单独串行的先前版本运行得更慢实施。
【讨论】:
【参考方案2】:您是对的,减速与任务创建和管理的开销有关。
添加 if(n > 20) 是修剪任务树的好方法,并且可以通过不创建第二个任务来进行更多优化。当新任务产生时,父线程什么也不做。可以通过允许父任务处理其中一个 fib 调用而不是创建更多任务来加速代码:
int fib(int n)
int i, j;
if (n < 2)
return n;
else
#pragma omp task shared(i) if(n > 20)
i=fib(n-1);
j=fib(n-2);
#pragma omp taskwait
return i+j;
【讨论】:
以上是关于openmp递归任务示例比顺序慢的主要内容,如果未能解决你的问题,请参考以下文章