Here is a reproducer of the problem. I want the distributed 3D array arr(:,:,:)
have reproducible random numbers for the same global index ig,jg,kg
, irrespective of the number of MPI tasks. Right now I just loop through the whole domain and pick the indexes pertaining to the local array arr
.
Please don’t mind the MPI domain decomposition boilerplate code:
program p
use mpi_f08
implicit none
integer, parameter, dimension(3) :: ng =[8,4,6]
integer :: il,jl,kl,ig,jg,kg,n(3),lo(3)
real :: rn
integer, allocatable :: iseed(:)
integer :: nrank,myid,dims(3),coords(3),rem(3)
type(MPI_COMM) :: COMM_CART
real, allocatable :: arr(:,:,:)
!
! domain decomposition MPI boiler plate code
!
call MPI_INIT()
call MPI_COMM_SIZE(MPI_COMM_WORLD,nrank)
dims(:) = 0
call MPI_DIMS_CREATE(nrank,3,dims)
call MPI_CART_CREATE(MPI_COMM_WORLD,3,dims,[.false.,.false.,.false.],.true.,COMM_CART)
call MPI_COMM_RANK(COMM_CART,myid)
call MPI_CART_COORDS(COMM_CART,myid,3,coords)
!
! determine local array extents
!
n = ng(:)/dims(:) ! local array size
rem = mod(ng(:),dims(:))
where(coords(:)+1 <= rem(:)) n(:) = n(:) + 1
lo(:) = (coords(:) )*n(:)
where(coords(:)+1 > rem(:))
lo(:) = lo(:) + rem(:)
end where
!
! random number generation
! goal -- the random number corresponding
! to each global index ig,jg,kg must be independent
! of the number of MPI tasks
!
allocate(iseed(64))
iseed(:) = 42
call random_seed(put=iseed(:))
allocate(arr(n(1),n(2),n(3)))
do kg=1,ng(3) ! global index kg
kl = kg - (lo(3)-1) ! local index kl
do jg=1,ng(2) ! global index jg
jl = jg - (lo(2)-1) ! local index jl
do ig=1,ng(1) ! global index ig
il = ig - (lo(1)-1) ! local index il
!
! random_number called product(ng(:)) times to
! obtain the same sequence for all MPI tasks
!
call random_number(rn)
!
! now I choose the values corresponding
! to the local computational subdomain
!
if(il >= 1.and.il <= n(1) .and. &
jl >= 1.and.jl <= n(2) .and. &
kl >= 1.and.kl <= n(3) ) then
arr(il,jl,kl) = rn
print*,ig,jg,kg,rn
endif
enddo
enddo
enddo
call MPI_FINALIZE()
end
and here’s how to test the program:
mpif90 prog.f90 # compile
mpirun -n 1 ./a.out | sort -k3,3 -k2,2 -k1,1 -n > out_1.log # run and sort outputs
mpirun -n 3 ./a.out | sort -k3,3 -k2,2 -k1,1 -n > out_3.log # run and sort outputs
diff out_1.log out_3.log # should be equal!