基于MPI实现双层循环Nested Parallelism(仅用2个进程)
基于MPI实现两层循环的嵌套并行改造(双进程)
需求说明
原串行Fortran代码中,两层循环执行后数组a的每个元素值为8,变量ll值为16。现在需要仅用MPI工具、2个进程(0号和1号)实现嵌套并行,对应以下逻辑示意图:
(1,2) 0---------------------1 (3,4) -----------> i loop | | | | 0-------------1 0--------------1 | | | | | | | | (1,2) (3,4) (1,2) (3,4) ---------> j loop
改造后代码
program main implicit none include "mpif.h" integer nproc, rank, ierr, a(4), ll, i, j integer comm_world, comm_j, group_world, group_j integer ranks_j(2), local_a(4), local_ll ! 初始化MPI环境 call MPI_INIT(ierr) comm_world = MPI_COMM_WORLD call MPI_COMM_SIZE(comm_world, nproc, ierr) call MPI_COMM_RANK(comm_world, rank, ierr) ! 初始化局部变量,避免脏数据 local_a(:) = 0 local_ll = 0 a(:) = 0 ll = 0 ! 外层i循环:按进程rank划分任务 ! 进程0处理i=1、2,进程1处理i=3、4 do i = (rank*2)+1, (rank+1)*2 ! 创建包含所有进程的子通信域,用于内层j循环的并行 ranks_j(1) = 0 ranks_j(2) = 1 call MPI_COMM_GROUP(comm_world, group_world, ierr) call MPI_GROUP_INCL(group_world, 2, ranks_j, group_j, ierr) call MPI_COMM_CREATE(comm_world, group_j, comm_j, ierr) ! 内层j循环:再次按rank划分任务 ! 子通信域内进程0处理j=1、2,进程1处理j=3、4 do j = (rank*2)+1, (rank+1)*2 ! 执行原循环的累加逻辑 local_a(i) = local_a(i) + 1 local_a(j) = local_a(j) + 1 local_ll = local_ll + 1 end do ! 释放子通信域和组资源 call MPI_COMM_FREE(comm_j, ierr) call MPI_GROUP_FREE(group_j, ierr) call MPI_GROUP_FREE(group_world, ierr) end do ! 汇总所有进程的局部结果到全局变量(以进程0为根进程) call MPI_REDUCE(local_a, a, 4, MPI_INTEGER, MPI_SUM, 0, comm_world, ierr) call MPI_REDUCE(local_ll, ll, 1, MPI_INTEGER, MPI_SUM, 0, comm_world, ierr) ! 仅由进程0输出最终结果 if (rank == 0) then print *, "数组a的结果:", a print *, "变量ll的结果:", ll end if call MPI_FINALIZE(ierr) end program main
关键逻辑说明
- 外层i循环拆分:直接利用进程
rank划分i的范围,完美匹配示意图中上层i循环的任务分配(0号处理i=1、2,1号处理i=3、4)。 - 内层j循环嵌套并行:每个进程在处理自身i任务时,创建包含两个进程的子通信域,再次按
rank拆分j的任务,实现内层循环的并行执行。 - 结果全局汇总:通过
MPI_REDUCE将两个进程的局部累加结果求和,保证最终的a数组每个元素值为8,ll值为16,和串行逻辑完全一致。 - 资源清理:手动释放创建的子通信域和组,避免MPI资源泄漏,符合最佳实践。
内容的提问来源于stack exchange,提问作者quantax
相关产品推荐
相关产品推荐

