openmp常用指令(fortran版)(2)

1.! OMPDO/! OMP END DO

指令对使最近的do循环并行执行,将do循环分散到不同的线程,每个线程仅仅计算部分迭代,所有的线程之和完成所有的计算任务,换句话说,就是所有的线程合力去完成所有的循环;

program test
use omp_lib
!call omp_set_nested(.true.)
write(*,*) "线程数为:",omp_get_num_procs()
!$OMP PARALLEL
!$OMP DO
Do i=1,10
write(*,10) i,OMP_get_thread_num()
end do
!$OMP END DO
!$OMP END PARALLEL
10 FORMAT(1X,'i=',I3,'       ThreadID=',I3)

End program

其中,OMP_get_thread_num()是omp_lib中的函数,返回当前线程的线程号,取值范围0到并行区域线程数-1,后续相关函数还有有相关介绍;本实验开了四个线程,结果如下:openmp常用指令(fortran版)(2)_第1张图片
可以看到i从1到10分别由不同的thread打印输出;
值得注意的是:因为是并行计算,一次迭代的输入是上一次的迭代的结果,这种情况就会在成不确定性结果,像下面的程序:

real(8)  :: A(1000)
do i = 1, 999
A(i) = A(i+1)
End do

错误的原因是:在执行第i次迭代时,需要索引i+1处的未修改值。串行执行时毫无问题,但在并行计算时,不能获取到i+1处的未修改值。这种情况称为竞赛条件(racing condition):结果依赖于线程执行顺序和每颗处理器的速度。

2.! OMPSECTIONS/! OMP END SECTIONS

指令对允许给每个线程分派完全不同的任务,生成MPMD(Multiple Programs Multiple Data)执行模块。每段代码仅被一个线程执行一次,代码如下:

!$OMP PARALLEL
!$OMP SECTIONS
!$OMP SECTION
write(*,*)"hello" , OMP_get_thread_num()
!$OMP SECTION
write(*,*)"hi" , OMP_get_thread_num()
!$OMP SECTION
write(*,*)"Bye" , OMP_get_thread_num()
!$OMP END SECTIONS
!$OMP END PARALLEL

每段代码被唯一线程执行,以! OMPSECTION! OMP SECTION
指令;或者以!$OMP END SECTIONS指令结束。可在当前指令对内定义任意数量的代码段,
但只有已经存在的线程才可以分派代码块。这意味着如果代码段的数量大于可用线程数,部
分线程将会串行执行不止一段代码。如果代码段的数量少于线程数,又将导致有效资源的低
效率使用。举例来说,如果由4线程执行5个代码段,在第四个线程执行第五个代码段时,另
外3个线程会被闲置。
最后的运行结果是:
openmp常用指令(fortran版)(2)_第2张图片

3.! OMPSINGLE/! OMP END SINGLE

指令对包含的代码仅由其中一条线程执行,也就是最先到达! OMPSINGLE线NOWAIT线! OMP END SINGLE处等待(隐式同时性)。
示意图如下:
openmp常用指令(fortran版)(2)_第3张图片
另外! OMPMASTER/! OMP END MASTER用法于此相似,置顶其中的代码只由主线程执行,主线程执行期间其他线程等待。

你可能感兴趣的:(fortran,并行化,并行计算)