Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Fortran 16字节实数的MPI_AllReduce的奇怪结果_Fortran_Mpi_Openmpi_Quadruple Precision - Fatal编程技术网

Fortran 16字节实数的MPI_AllReduce的奇怪结果

Fortran 16字节实数的MPI_AllReduce的奇怪结果,fortran,mpi,openmpi,quadruple-precision,Fortran,Mpi,Openmpi,Quadruple Precision,编译器:gfortran-4.8.5 MPI库:OpenMPI-1.7.2(预安装的OpenSuSE 13.2) 该计划: use mpi implicit none real*16 :: x integer :: ierr, irank, type16 call MPI_Init(ierr) call MPI_Comm_Rank(MPI_Comm_World, irank, ierr) if (irank+1==1) x = 2.1 if (irank+

编译器:gfortran-4.8.5

MPI库:OpenMPI-1.7.2(预安装的OpenSuSE 13.2)

该计划:

  use mpi
  implicit none

  real*16 :: x
  integer :: ierr, irank, type16

  call MPI_Init(ierr)

  call MPI_Comm_Rank(MPI_Comm_World, irank, ierr)

  if (irank+1==1) x = 2.1
  if (irank+1==8) x = 2.8
  if (irank+1==7) x = 5.2
  if (irank+1==4) x = 6.7
  if (irank+1==6) x = 6.5
  if (irank+1==3) x = 5.7
  if (irank+1==2) x = 4.0
  if (irank+1==5) x = 6.8

  print '(a,i0,a,f3.1)', "rank+1: ",irank+1," x: ",x

  call MPI_AllReduce(MPI_IN_PLACE, x, 1, MPI_REAL16, MPI_MAX, MPI_Comm_World, ierr)

  if (irank==0) print '(i0,a,f3.1)', irank+1," max x: ", x

  call MPI_Finalize(ierr)
end
我还尝试了
real(16)
real(kind(1.q0))
<对于此编译器,code>real(real128)实际上与
real*10
等效

结果是:

> mpif90 reduce16.f90 
> mpirun -n 8 ./a.out 
rank+1: 1 x: 2.1
rank+1: 2 x: 4.0
rank+1: 3 x: 5.7
rank+1: 4 x: 6.7
rank+1: 5 x: 6.8
rank+1: 6 x: 6.5
rank+1: 7 x: 5.2
rank+1: 8 x: 2.8
1 max x: 2.8
程序为
real*10
保持
MPI\u REAL16
找到真正的最大值。如果
MPI\u REAL16
对应于
real*16
real(real128)
,则MPI规范(3.1,第628页和674页)不是很清楚

此外,假设MPI_REAL16实际上是
real(real128)
,尝试在程序中使用它会导致不同的问题:

Error: There is no specific subroutine for the generic 'mpi_recv' at (1)
Error: There is no specific subroutine for the generic 'mpi_send' at (1)
这在
real*16
中不会发生。 (忽略应该能够通过任何位模式,因此该检查是多余的)


使用16字节实数的正确方法是什么?OpenMPI库出错了吗?

虽然这应该在每个MPI实现中都能正常工作,但一个简单的解决方法是为这种类型实现一个用Fortran编写的用户定义的简化,因此在C中实现它没有问题(这就是MPICH和OpenMPI尝试做任何事情的方式,因此当C无法重现Fortran的行为时会出现问题)

下面是实现这一点的尝试。这是Fortran中用户定义的简化。我相信经验丰富的现代Fortran程序员可以做得更好

  subroutine sum_real16(iv,iov,n)
    implicit none
    integer, intent(in) ::  n
    real*16, intent(in) :: iv(:)
    real*16, intent(inout) :: iov(:)
    integer :: i
    do i = 1,n
      iov(i) = iov(i) + iv(i)
    enddo
  end subroutine sum_real16
  subroutine reduce_sum_real16(iv, iov, n, dt)
    use, intrinsic ::  iso_c_binding, only : c_ptr
    use mpi_f08
    implicit none
    type(c_ptr), value ::  iv, iov
    integer ::  n
    type(MPI_Datatype) ::  dt
    if ( dt .eq. MPI_REAL16 ) then
        call sum_real16(iv,iov,n)
    endif
  end subroutine reduce_sum_real16
  program test_reduce_sum_real16
    use, intrinsic ::  iso_c_binding
    use mpi_f08
    implicit none
    integer, parameter ::  n = 10
    real*16 :: output(n)
    real*16 :: input(n)
    real*16 :: error
    integer :: me, np
    procedure(MPI_User_function) :: reduce_sum_real16
    type(MPI_Op) :: mysum
    integer :: i
    call MPI_Init()
    call MPI_Comm_rank(MPI_COMM_WORLD,me)
    call MPI_Comm_size(MPI_COMM_WORLD,np)
    output = 0.0
    input  = 1.0*me
    call MPI_Op_create(reduce_sum_real16,.true.,mysum)
    call MPI_Allreduce(input,output,n,MPI_REAL16,mysum,MPI_COMM_WORLD)
    error = 0.0
    do i = 1,n
      error = error + (output(i)-1.0*np)
    enddo
    if (error.gt.0.0) then
        print*,'SAD PANDA = ',error
        call MPI_Abort(MPI_COMM_SELF,1)
    endif
    call MPI_Op_free(mysum)
    call MPI_Finalize()
  end program test_reduce_sum_real16

使用“英特尔16 Fortran编译器”和MPICH 3.2+,此程序返回时不会出错。显然,我没有正确使用I/O,因此我对此程序正确性的信心不如将所有结果写入标准输出时那么高。

您可以尝试使用mpi_type_create_f90_real来获得与ge相同的数据类型虽然一些MPI库版本没有正确地解决这个问题,但我仍然认为这是最具可移植性和建议性的方法。另请参阅此票证:@francescalus我不确定gfortran是否支持MPI\u f08,因为它是非标准数组描述符。我现在肯定没有,但我可以尝试我自己编译。contants的准确值并不重要,它们只是从实际计算中复制和粘贴的。你应该将该问题发布到ompi-devel邮件列表中。它们很重要。该库已经在发布版本中实现了
使用mpi\u f08
接口和
使用mpi\u f08
GitHub master中的手册页中已经包含了语法(老实说,提交时间是2天前,但迟做总比不做强)