【问题标题】:How do Fortran and MPI_Reduce deal with integer overflow?Fortran 和 MPI_Reduce 如何处理整数溢出?
【发布时间】:2017-03-25 10:40:56
【问题描述】:

按照this thread,我想将单/双精度实数“AA”转换为整数“II”来计算分布式变量的校验和。

在 cmets 之后,我使用了内在的“转移”并完全重写了这篇文章。下面是一个小型 fortran 模块,可用于计算依赖于库 2DECOMP&FFT 的分布式数组的校验和。该模块似乎可以在我的工作站上运行(gfortran 4.9.2、openmpi 1.6.5、4 个处理器)。任何可能提高代码可移植性的评论/评论都将受到高度赞赏。关于可移植性的主要问题是:根据标准,fortran 和 MPI_reduce 是否以相同的方式处理整数溢出?

module checksum

   use MPI
   use decomp_2d, only : mytype, nrank, &
   xsize, ysize, zsize, &
   transpose_x_to_y, transpose_y_to_z, &
   transpose_z_to_y, transpose_y_to_x

   implicit none

   private ! Make everything private unless declared public

   real(mytype), parameter :: xx=1.

   integer, parameter, public :: chksum_size = size(transfer(xx,(/0,0/)))

   integer, dimension(chksum_size) :: chkr1, chkr2, chkr3

   logical, save :: chksum_is_working

   ! Temporary work variables / arrays
   integer :: code
   integer, dimension(chksum_size) :: tmprchk

   public :: init_chksum, chksum, equal_chksum

   contains

   !
   ! Function to compute the checksum of a real 3D array var
   !
   function chksum(var,nx,ny,nz)
      integer, intent(in) :: nx, ny, nz
      real(mytype), dimension(nx,ny,nz), intent(in) :: var
      integer, dimension(chksum_size) :: chksum

      tmprchk = sum(transfer(var,(/0,0/)))
      call MPI_ALLREDUCE(tmprchk,chksum,chksum_size,MPI_INTEGER,MPI_SUM,MPI_COMM_WORLD,code)

   end function chksum

   !
   ! Subroutine to make sure input arrays have the same checksum
   ! First / second / third array are in X / Y / Z pencil
   ! If switch is provided, reference array is var3.
   !    Otherwise, reference array is var1
   !
   subroutine equal_chksum(var1, var2, var3, switch)
      real(mytype), dimension(xsize(1),xsize(2),xsize(3)), intent(inout) :: var1
      real(mytype), dimension(ysize(1),ysize(2),ysize(3)), intent(inout) :: var2
      real(mytype), dimension(zsize(1),zsize(2),zsize(3)), intent(inout) :: var3
      logical, optional, intent(in) :: switch

      if (chksum_is_working) then ! compute checksums
         chkr1 = chksum(var1,xsize(1),xsize(2),xsize(3))
         chkr2 = chksum(var2,ysize(1),ysize(2),ysize(3))
         chkr3 = chksum(var3,zsize(1),zsize(2),zsize(3))
      else ! generate checksums
         chkr1 = 1
         chkr2 = 2
         chkr3 = 3
      endif

      if (present(switch)) then
         if (any(chkr3.ne.chkr2)) call transpose_z_to_y(var3,var2)
         if (any(chkr3.ne.chkr1)) call transpose_y_to_x(var2,var1)
      else
         if (any(chkr1.ne.chkr2)) call transpose_x_to_y(var1,var2)
         if (any(chkr1.ne.chkr3)) call transpose_y_to_z(var2,var3)
      endif

   end subroutine equal_chksum

   !
   ! Subroutine used to check we have a working checksum
   !
   subroutine init_chksum(var1,var2,var3)
      real(mytype), dimension(xsize(1),xsize(2),xsize(3)), intent(out) :: var1
      real(mytype), dimension(ysize(1),ysize(2),ysize(3)), intent(out) :: var2
      real(mytype), dimension(zsize(1),zsize(2),zsize(3)), intent(out) :: var3

      ! Same random data inside all arrays
      call random_number(var1)
      call transpose_x_to_y(var1,var2)
      call transpose_y_to_z(var2,var3)

      ! Compute checksums
      chkr1 = chksum(var1,xsize(1),xsize(2),xsize(3))
      chkr2 = chksum(var2,ysize(1),ysize(2),ysize(3))
      chkr3 = chksum(var3,zsize(1),zsize(2),zsize(3))

      ! Check checksums
      if (any(chkr1.ne.chkr2).or.any(chkr1.ne.chkr3)) then
         chksum_is_working = .false.
         if (nrank.eq.0) print *,'Checksums based on integer overflow do not work'
      else
         chksum_is_working = .true.
      endif

   end subroutine init_chksum

end module checksum

【问题讨论】:

  • 你所说的“演员”是什么意思?您想使用相同的位模式而不是值(例如 transfer)?
  • @francescalus 谢谢,我不知道转移,这正是我需要的。它是标准的/便携式的吗?
  • 你应该明白cast这个词是模棱两可的,你必须简单地解释你对一些代码做了什么。例如,在 C++ 中,有 reinterpret_cast、dynamic_cast、static_cast 等等stackoverflow.com/questions/332030/…我们无法从水晶球中看出您指的是哪种类型的演员。
  • @VladimirF reinterpret_cast 似乎对应,问题已更新
  • 好像他把它编辑成一个完全不同的问题

标签: casting integer fortran


【解决方案1】:

Fortran 标准未定义整数溢出。在 C 中,有符号整数溢出是未定义的行为

如果您在 gfortran 中启用未定义的行为清理,您的程序将停止并显示错误消息。 (当我使用 3rd 方随机数生成器时发生在我身上。)

您可以使用较大的整数执行操作并裁剪结果或调用使用无符号整数的 C 函数。整数溢出仅适用于有符号整数。

【讨论】:

    【解决方案2】:

    fortran 和 MPI_reduce 是否按照标准以相同的方式处理整数溢出?

    Fortran 标准和 MPI 3.0 标准都没有提到整数溢出,所以你只能任由实现者摆布。

    但是,我看到您只使用默认的整数种类,为中间结果使用更大的整数种类,您可以实现自己的溢出检测。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-12
      • 1970-01-01
      • 2013-06-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多