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