嵌套并行

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

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

//File :NestingTest.cpp #include"stdafx.h" #include #include 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:"<

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

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 #include using namespace std; void NestedTest() { int i,j,k; k=omp_get_nested(); cout<<"是否支持并行嵌套:"<

运行程序,其结果如下:

是否支持并行嵌套: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 #include 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<<"计算耗时:"<

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



你可能感兴趣的:(嵌套并行)