简体   繁体   中英

My MPI fortran code gives different results for large integers

I am very new to MPI programming (like 3 days old). I am now dealing with MPI_ALLREDUCE and MPI_REDUCE . The code below takes a value n and the task of every process is to add 1 to the variable mypartialsum for n/num_procs times, where num_procs is the number of processes. After the reduction the values of mypartialsum are gathered in sum and the final result is sum=n . The code seems to work fine if n<1d10 , but for n>=1d10 I get the wrong result. For example, if I run the code with n=1d10 the value of sum is 1410065408 , while it is correct for n=1d9 . What I am missing? I suspect it could be something with the kind of the variables, but after looking on the inte.net it is not clear to me what the problem is.

program test
      use mpi
      IMPLICIT NONE
      !include 'mpif.h'
      integer:: ierr, num_procs, my_id, status(MPI_STATUS_SIZE), sender(MPI_STATUS_SIZE), root, rank
      integer:: i!, n 
      integer, parameter :: MyLongIntType = selected_int_kind (12)
      integer(kind=MyLongIntType):: n
      !real:: sum=0., partialsum=0., mypartialsum=0.
      integer(kind=MyLongIntType):: sum=0, partialsum=0, mypartialsum=0
      real:: starttime, endtime
      root=0

      call MPI_INIT ( ierr )
      call MPI_COMM_RANK (MPI_COMM_WORLD, my_id, ierr)
      call MPI_COMM_SIZE (MPI_COMM_WORLD, num_procs, ierr)
      starttime = MPI_WTIME()
      if (my_id .eq. root) then 
            print*, "Running in process 0."
            print*, "total numeber of process is", num_procs
            n=int8(1d10)!1000000000
      endif
      
      call MPI_BCAST(n, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
      !print*, "running process", my_id
      mypartialsum=0.
      do i = my_id+1, n, num_procs
            mypartialsum=mypartialsum+int(1)
      enddo 
      partialsum=mypartialsum
      print*, "Running process", my_id, "Partial sum is ", partialsum
      call MPI_REDUCE(partialsum, sum, 1, MPI_INTEGER, MPI_SUM, ROOT, MPI_COMM_WORLD, ierr)
      !call MPI_ALLREDUCE(partialsum, sum, 1, MPI_INTEGER, MPI_SUM, MPI_COMM_WORLD, ierr)

      endtime = MPI_WTIME()
      if (my_id .eq. 0) then
       print*, "sum is", sum, "time spent processing",  endtime-starttime
!      else if (my_id .gt. 0) then 
!       print*, "sum on process", my_id, "is", sum , "time spent processing is", endtime-starttime
      endif
     
     
      call MPI_FINALIZE ( ierr )
     

end program

You are telling MPI_Reduce that the type being summed is MPI_INTEGER . However, MPI_INTEGER corresponds to the default integer kind in Fortran. You have to provide the correct MPI type that corresponds to the selected_int_kind (12) type.

One of the possible ways, specifically for kinds resulting from selected_integer_kind is the MPI_Type_create_f90_integer(r, newtype, ierror) subroutine.

So something like call MPI_Type_create_f90_integer(12, MyLongIntMPIType, ierror) .

There are other alternatives, like using fixed memory storage kinds like integer(int64) and the MPI_INTEGER8 MPI type originally developed for the non-standard integer*8 .

See alsoAdditional Support for Fortran Numeric Intrinsic Types

It also contains this important advice to users:

The datatypes returned by the above functions are predefined datatypes. They cannot be freed; they do not need to be committed; they can be used with predefined reduction operations.

which makes it simple to use the returned type in MPI_Reduce() with MPI_SUM .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM