OpenMP递归任务

use*_*151 7 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);    
}
Run Code Online (Sandbox Code Playgroud)

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

Arc*_*son 4

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

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

解决方法是在整个任务树周围使用单个并行区域。将omp parallelomp single逻辑移至 main,位于 fib 之外。这样,单个线程团队将处理整个任务树。

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