欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-04-19 11:15:15
...

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)
可以看到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)

3.!OMPSINGLE/!OMP END SINGLE

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

相关标签: fortran openmp