OpenMP递归任务

时间:2014-03-24 21:40:18

标签: c++ multithreading openmp

请考虑以下程序计算Fibonacci数 它使用OpenMP Tasks进行并行化。

#include <iostream> 
#include <omp.h>

using namespace std;

int fib(int n)
{
    if(n == 0 || n == 1)
        return n;

    int res, a, b;
    #pragma omp parallel
    {
        #pragma omp single 
        {
            #pragma omp task shared(a)
            a = fib(n-1);
            #pragma omp task shared(b)
            b = fib(n-2);
            #pragma omp taskwait
            res = a+b;
        } 

    }
    return res;
  }

int main()
{  
    cout << fib(40);    
}

我使用gcc版本4.8.2和Fedora 20 使用g ++ -fopenmp name_of_program.cpp -Wall编译上述程序时 并且运行它,我在查看htop时只看到两个(有时是3个)线程正在运行。 我运行该程序的机器有8个逻辑CPU。 我的问题是,我需要做什么才能将工作卸载到8个线程上。 我尝试导出OMP_NESTED = TRUE,但这会在运行时导致跟随错误 计划:
libgomp:线程创建失败:资源暂时不可用
我的程序的要点不是有效地计算Fibonacci数,而是为了 在OpenMP中使用任务或类似的东西。

1 个答案:

答案 0 :(得分:2)

如果OMP_NESTED = FALSE,则将一组线程分配给顶级并行区域,并且每个嵌套级别没有额外的线程,因此最多两个线程将执行有用的工作。

如果OMP_NESTED = TRUE,则在每个级别分配一组线程。在您的系统上有8个逻辑CPU,因此团队规模可能为8.团队包含来自该区域外的一个线程,因此只启动了7个新线程。 fib(n)的递归树具有大约fib(n)个节点。 (fib的一个很好的自引用属性!)因此代码可能会产生7 * fib(n)个线程,这会很快耗尽资源。

修复是在整个任务树周围使用单个并行区域。将omp parallelomp single逻辑移到fib之外的main。这样一个线程团队就可以在整个任务树上工作。

一般要点是将潜在的并行性与实际的并行性区分开来。任务指令指定了潜在的并行性,在执行期间可能会或可能不会实际使用。 omp parallel(出于所有实际目的)指定实际并行性。通常,您希望实际并行度与可用硬件相匹配,以免淹没机器,但潜在的并行性要大得多,以便运行时可以平衡负载。