Fortran带线程通信的并行编程示例及线程终止实现
Fortran并行搜索中找到解后终止所有线程的实现
(更新:已找到解决方案,见文末代码)
Fortran具备原生内置并行特性,我尝试在一个求解搜索程序中使用该特性。
program do_co implicit none real(kind(1d0)) :: q(24) integer :: i, j, flag=0, max=2000000000 flag = 0 ! 尚未找到解 q(:) = 1 ! 生成24个不同序列 do concurrent (i = 1:24) ! 为此循环使用并行线程 do j = 0, max q(i) = 1.9832*i/24d0 - q(i)**2 if( abs(q(i))<3d-6 ) flag=1 ! 在指定范围内找到解 ! 接下来该怎么做? ! if(flag==1) exit ! 无法使用此语句,会阻止 ! 循环并行化 end do end do print "(6g12.4)", q end program
借助do concurrent实现了循环并行化,使用编译命令:
gfortran -Ofast -ftree-parallelize-loops=12 search.f90
可启动12个线程,但程序在找到解后不会停止。若引入全局标志变量让所有线程在某线程找到解后退出循环,编译器将不再并行化该循环。在预期某线程能快速找到解但无法预测具体线程的场景下,遍历整个搜索空间会非常低效。因此问题如下:
如何在某线程成功找到解后立即终止所有线程?
我了解到可使用coarray(用于跨进程镜像的分布式内存并行)和/或OpenMP(用于每个镜像内的共享内存多线程),但不清楚需添加的代码内容、编译选项及需安装的依赖库,尝试如下选项未成功:
gfortran -fopenmp -Ofast -ftree-parallelize-loops=12 -fcoarray=lib
能否提供一个线程通信的基础示例?
更新:使用OpenMP可实现需求,代码如下
program do_co use omp_lib implicit none real(kind(1d0)) :: q(12), range=2d-7 integer :: i, j, flag=0, max=2000000000 q(:) = 1 ! 将使用12个线程 call omp_set_num_threads(12) ! 每个线程对应一个i值 !$omp parallel private(i,j) ! 启动并行子句,每个线程拥有独立的i和j i = omp_get_thread_num()+1 ! 线程编号为0,1,.. do j = 0, max q(i) = 1.9832*i/12d0 - q(i)**2 if( abs(q(i))<range ) then ! 在指定范围内找到解 !$omp critical print *, "solution found in sequence", i flag=1 !$omp end critical ! 所有通信需在临界区进行 endif if(flag==1) exit end do !$omp end parallel ! 并行子句结束 print "(6g12.4)", q end program
这个方案需要添加4处!$omp指令,且依赖OpenMP,但代码简洁易懂,可实现需求:某线程找到解后所有线程终止,运行时CPU利用率可达1200%。编译命令仅需:
gfortran -fopenmp search.f90
注意:该方案未使用Fortran标准中的并行特性,此方法同样适用于C语言。
内容的提问来源于stack exchange,提问作者Jos Bergervoet
相关产品推荐
相关产品推荐

