嵌套并行

OpenMP中不建议使用并行嵌套,如果一个并行计算中的某个线程遇到了另外一个并行分支,程序运行将会变得不稳定。将一个完整的工作任务通过一组并行线程分成若干小任务,每个线程只执行指定给它的那段代码,并没用多余的线程去做其他的工作,即使并行计算中正在运行的某个线程遇到了一个新的并行分支,通过分割这个任务形成更多的线程,这并没有任何实际意义。因此,嵌套并行在OpenMP中将不考虑。OpenMP在处理多级并行嵌套时默认采用串行的执行方式,所以采用多级的并行在程序执行上并不会获得更高的计算效率。

下面通过一个例子来说明OpenMP中的并行嵌套。代码如下:

//File :NestingTest.cpp #include"stdafx.h" #include<omp.h> #include<iostream> using namespace std; void NestingTest() { int i,j; #pragma omp parallel for for(i=0;i<4;i++) { #pragma omp parallel for for(j=0;j<4;j++) { cout<<"j Threads:"<<omp_get_num_threads()<<" ThreadID:"<<omp_get_thread_num()<<"\n"; } cout<<" i="<<i<<" Threads:"<<omp_get_num_threads()<<"\n"; } }

这是一个简单的并行嵌套,运行结果如下:

j Threads:jThreads:1

ThreadID:01 ThreadID:0

j Threads:1ThreadID:0

j Threads:1ThreadID:0

j Threads:1ThreadID:0

j Threads:1ThreadID:0

j Threads:1ThreadID:0

j Threads:1ThreadID:0

i=2 Threads:8

j Threads:1ThreadID:0

j Threads:1ThreadID:0

j Threads:1ThreadID:0

j Threads:1ThreadID:0

j Threads:1ThreadID:0

j Threads:1ThreadID:0

j Threads:1ThreadID:0

i=3 Threads:8

i=0 Threads:8

j Threads:1ThreadID:0

i=1 Threads:8

从输出结果可以发现,在i的循环中循环之间处于并行状态,而在j中循环属于串行。默认情况下即使将j循环定义成并行,其内部执行时仍然按串行方式运行。

若需要使用嵌套并行,则需要使用 omp_set_nested()函数设置在程序中可用并行嵌套。如下例子:

//File :NestedTest.cpp #include"stdafx.h" #include<omp.h> #include<iostream> using namespace std; void NestedTest() { int i,j,k; k=omp_get_nested(); cout<<"是否支持并行嵌套:"<<k<<"\n"; omp_set_nested(1);//设置支持嵌套并行 k=omp_get_nested(); cout<<"是否支持并行嵌套:"<<k<<"\n"; double starttime,endtime; starttime=omp_get_wtime(); #pragma omp parallel for for(i=0;i<2;i++) { #pragma omp parallel for for(j=0;j<4;j++) { cout<<" i="<<i<<" j="<<j<<" Threads:"<<omp_get_num_threads()<<" ThreadID:"<<omp_get_thread_num()<<"\n"; } cout<<" I="<<i<<" Threads:"<<omp_get_num_threads()<<" ThreadID:"<<omp_get_thread_num()<<"\n"; } endtime=omp_get_wtime(); k=omp_get_nested(); cout<<"是否支持并行嵌套:"<<k<<"\n"; cout<<"计算耗时:"<<endtime-starttime<<"s\n"; }

运行程序,其结果如下:

是否支持并行嵌套:0

是否支持并行嵌套:1

i=i=1 j=2 Threads:8i=0 j=0 Threads:8ThreadID:0

ThreadID:2

i=0j=3 Threads:8 ThreadID:3

i=0j=1 Threads:8 ThreadID:1

i=1j=3 Threads:8 ThreadID:3

i=1j=1 Threads:8 ThreadID:1

0 j=2Threads:8 ThreadID:2

i=1j=0 Threads:8 ThreadID:0

I=0 Threads:8ThreadID:0

I=1 Threads:8ThreadID:1

是否支持并行嵌套:1

计算耗时:0.0338853s

从上面结果可见,不仅在i的循环中每个循环处于并行,在j中每个循环也处于并行状态。默认情况下,程序的并行嵌套是不可用的,即并行中的并行将会当作串行来处理。如果使用omp_set_nested()设置其可用并行嵌套,则当并行中的线程遇到新的并行时,会创建新的线程来并行处理。

下面用一个例子来比较嵌套并行与非嵌套并行的运行效率,代码如下:

//File :NestingTest02.cpp #include"stdafx.h" #include<omp.h> #include<iostream> using namespace std; void test() { int i; for(i=0;i<100000000;i++); } void NestingTest02() { int i,j; double starttime,endtime; starttime=omp_get_wtime(); #pragma omp parallel for for(i=0;i<8;i++) { #pragma omp parallel for for(j=0;j<8;j++) { test(); } } endtime=omp_get_wtime(); cout<<"计算耗时:"<<endtime-starttime<<"s\n"; }

上面代码是一个嵌套并行,其计算耗时约为2.63688s。如果将j循环上面的并行指令注释,只有一个并行结构,其结果为0.678552s。如果将i循环上面的并行指令注释,保留j循环前面的并行指令,其结果为2.67237s。如果都不采用并行,直接用串行运行,其计算耗时为16.1329s。可以,采用嵌套并行并不一定能提高效率,只有在合适的地方设置并行才能达到事半功倍的效果。



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值