请考虑以下程序计算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中使用任务或类似的东西。
答案 0 :(得分:2)
如果OMP_NESTED = FALSE,则将一组线程分配给顶级并行区域,并且每个嵌套级别没有额外的线程,因此最多两个线程将执行有用的工作。
如果OMP_NESTED = TRUE,则在每个级别分配一组线程。在您的系统上有8个逻辑CPU,因此团队规模可能为8.团队包含来自该区域外的一个线程,因此只启动了7个新线程。 fib(n)的递归树具有大约fib(n)个节点。 (fib的一个很好的自引用属性!)因此代码可能会产生7 * fib(n)个线程,这会很快耗尽资源。
修复是在整个任务树周围使用单个并行区域。将omp parallel
和omp single
逻辑移到fib之外的main。这样一个线程团队就可以在整个任务树上工作。
一般要点是将潜在的并行性与实际的并行性区分开来。任务指令指定了潜在的并行性,在执行期间可能会或可能不会实际使用。 omp parallel
(出于所有实际目的)指定实际并行性。通常,您希望实际并行度与可用硬件相匹配,以免淹没机器,但潜在的并行性要大得多,以便运行时可以平衡负载。