program main_mpi_test
use mpi
implicit none
integer(kind=8) :: n
integer(kind=8) :: max_optical_depth
integer(kind=8) :: bin
integer(kind=8) :: tmax
integer(kind=8) :: sum_scatt
integer(kind=8) :: i,j,k
real(kind=8) :: rad
real(kind=8), dimension(:), allocatable :: send_results, recv_results
integer :: nrank, nproc,ierr,root
call MPI_INIT(ierr)
call MPI_COMM_RANK(MPI_COMM_WORLD, nrank, ierr)
call MPI_COMM_SIZE(MPI_COMM_WORLD, nproc, ierr)
call MPI_BARRIER(MPI_COMM_WORLD, ierr)
root = 0
max_optical_depth = 10
bin = 10
tmax = max_optical_depth*bin
allocate(send_results(tmax))
allocate(recv_results(tmax))
do i = nrank+1, tmax, nproc
rad = real(i)/real(bin)
send_results(i) = rad
print*,'send', rad, send_results(i)
end do
call MPI_BARRIER(MPI_COMM_WORLD, ierr)
call MPI_REDUCE(send_results, recv_results, tmax, MPI_DOUBLE_PRECISION, &
MPI_SUM, root, MPI_COMM_WORLD, ierr)
if (nrank ==0) then
do i = 1, tmax
rad = real(i)/real(bin)
print*,'recv',rad, recv_results(i)
end do
end if
call MPI_FINALIZE(ierr)
deallocate(send_results)
deallocate(recv_results)
end program main_mpi_test
这是我的代码。 我用
MPI_REDUCE
。我使用 mpiifort 编译器。
问题是当我打印recv_results时,
rad
和recv_results
的值必须相等,但在数组中的某些位置显示Nan或大约1e186的大数。
在其他位置,rad
和 recv_results
具有相同的值。
如何解决这个问题?
你的程序有不少问题。
real(8)
和 integer(8)
是不好的做法。它们不可移植,可能无法达到您的预期,甚至可能不受编译器支持。从您最喜欢的 Fortran 书籍或教程中了解 Fortran 类型,Vladimir 提供的链接(Fortran:整数*4 vs 整数(4) vs 整数(kind=4) 和 Fortran 90 类型参数)是有用的支持材料。我的首选方法是使用 iso_fortran_env
标准模块,请参阅下面的程序integer(8)
做什么(如果支持的话),它都不太可能与 MPI 库兼容。 MPI(对于大多数例程)是根据默认 Fortran 整数定义的,因此我强烈建议您使用默认 Fortran 整数send_results
。因此,正如您所观察到的,任何结果都是可能的。未初始化的东西可以取任何值,只有运气好它们才会为零。Real
函数将该参数转换为默认实数类型的值,这不是您想要的。这与上面的 1) 密切相关,但是要获得您想要的类型,您需要提供该类型。请参阅下面的我的程序MPI_Barrier
是完全没有必要的,只是浪费时间 - MPI_Reduce
已经阻塞了。根据经验,除了测量时序、调试以及可能使用共享内存时,您永远不会需要 mpi_barrier (对于纯粹主义者来说,我可能也应该调用
MPI_Type_create_f90_real
但我会很懒,假设 MPI_DOUBLE_PRECISION
映射到 real64
)
无论如何,这是我的程序,它与 gfortran、ifort 和 ifx 一起使用
ijb@ijb-Latitude-5410:~/work/stack$ cat red.f90
Program main_mpi_test
Use iso_fortran_env, Only : wp => real64
Use mpi
Implicit None
Real( wp ), Dimension(:), Allocatable :: send_results, recv_results
Real( wp ) :: rad
Integer :: n
Integer :: max_optical_depth
Integer :: bin
Integer :: tmax
Integer :: sum_scatt
Integer :: i,j,k
Integer :: nrank, nproc, ierr, root
Logical :: worked
Call MPI_INIT(ierr)
Call MPI_COMM_RANK(MPI_COMM_WORLD, nrank, ierr)
Call MPI_COMM_SIZE(MPI_COMM_WORLD, nproc, ierr)
Call MPI_BARRIER(MPI_COMM_WORLD, ierr)
root = 0
max_optical_depth = 10
bin = 10
tmax = max_optical_depth*bin
Allocate(send_results(tmax))
Allocate(recv_results(tmax))
send_results = 0.0_wp
Do i = nrank+1, tmax, nproc
rad = Real( i, Kind( rad ) ) / Real( bin, Kind( rad ) )
send_results(i) = rad
! Print*,'send', rad, send_results(i)
End Do
Call MPI_REDUCE(send_results, recv_results, tmax, MPI_DOUBLE_PRECISION, &
MPI_SUM, root, MPI_COMM_WORLD, ierr)
If (nrank ==0 ) Then
worked = .true.
Do i = 1, tmax
rad = Real( i, Kind( rad ) ) / Real( bin, Kind( rad ) )
! Write( *, * ) 'recv', rad, recv_results(i)
worked = worked .And. ( Abs( rad - recv_results(i) ) < 1e-15_wp )
End Do
Write( *, * ) "Worked? ", worked
End If
Deallocate(send_results)
Deallocate(recv_results)
Call MPI_FINALIZE(ierr)
End Program main_mpi_test
ijb@ijb-Latitude-5410:~/work/stack$ mpif90 -Wall -Wextra -fcheck=all -O -g red.f90
red.f90:18:16:
18 | Integer :: i,j,k
| 1
Warning: Unused variable ‘j’ declared at (1) [-Wunused-variable]
red.f90:18:18:
18 | Integer :: i,j,k
| 1
Warning: Unused variable ‘k’ declared at (1) [-Wunused-variable]
red.f90:13:14:
13 | Integer :: n
| 1
Warning: Unused variable ‘n’ declared at (1) [-Wunused-variable]
red.f90:17:22:
17 | Integer :: sum_scatt
| 1
Warning: Unused variable ‘sum_scatt’ declared at (1) [-Wunused-variable]
ijb@ijb-Latitude-5410:~/work/stack$ mpirun -np 4 ./a.out
Worked? T
ijb@ijb-Latitude-5410:~/work/stack$ mpiifort red.f90
ijb@ijb-Latitude-5410:~/work/stack$ mpirun -np 4 ./a.out
Worked? T
ijb@ijb-Latitude-5410:~/work/stack$ mpiifort -fc=ifx red.f90
ijb@ijb-Latitude-5410:~/work/stack$ mpirun -np 4 ./a.out
Worked? T
ijb@ijb-Latitude-5410:~/work/stack$