mpi_f08: fix Fortran-8-byte-INTEGER vs. C-4-byte-int issue
It is important to have the mpi_f08 Type(MPI_Status) be the same length (in bytes) as the mpif.h status (which is an array of MPI_STATUS_SIZE INTEGERs). The reason is because MPI_Status_ctof() basically does the following: MPI_Fint *f_status = ...; int *s = (int*) &c_status; for i=0..sizeof(MPI_Status)/sizeof(int) f_status[i] = c_status[i]; Meaning: the Fortran status needs to be able to hold as many INTEGERs are there are C int's that can fit in sizeof(MPI_Status) bytes. This is because a Fortran INTEGER may be larger than a C int (e.g., Fortran 8 bytes vs. C 4 bytes). Hence, the assignment on the Fortran side will take sizeof(INTEGER) bytes for each sizeof(int) bytes in the C MPI_Status. This commit pads out the mpi_f08 Type(MPI_Status) with enough INTEGERs to make it the same size as an array of MPI_TYPE_SIZE INTEGERs. Hence, MPI_Status_ctof() will work properly, regardless of whether it is assinging to an mpi_f08 Type(MPI_Status) or an mpif.h array of MPI_STATUS_SIZE INTEGERs. Thanks to @ahaichen for reporting the issue. Signed-off-by: Jeff Squyres <jsquyres@cisco.com>
Этот коммит содержится в:
родитель
ad81839dd5
Коммит
98bc7af7d4
@ -244,12 +244,28 @@ AC_DEFUN([OMPI_SETUP_MPI_FORTRAN],[
|
||||
|
||||
# How big should MPI_STATUS_SIZE be? (i.e., the size of
|
||||
# MPI_STATUS, expressed in units of Fortran INTEGERs). The C
|
||||
# equivalent of MPI_Status contains 4 C ints and a size_t.
|
||||
# MPI_Status struct contains 4 C ints and a size_t.
|
||||
OMPI_FORTRAN_STATUS_SIZE=0
|
||||
AC_MSG_CHECKING([for the value of MPI_STATUS_SIZE])
|
||||
|
||||
# Calculate how many C int's can fit in sizeof(MPI_Status). Yes,
|
||||
# I do mean C ints -- not Fortran INTEGERS. The reason is because
|
||||
# an mpif.h MPI_Status is an array of INTEGERS. But these
|
||||
# sizeof(INTEGER) may be larger than sizeof(int). Hence,
|
||||
# MPI_Status_ctof() basically does this:
|
||||
#
|
||||
# MPI_Fint *f_status = ...;
|
||||
# int *s = (int*) &c_status;
|
||||
# for i=0..sizeof(MPI_Status)/sizeof(int)
|
||||
# f_status[i] = c_status[i];
|
||||
#
|
||||
# Meaning: we have to have as many Fortran INTEGERs in the array
|
||||
# as int's will fit in a C MPI_Status (vs. just having a Fortran
|
||||
# array of INTEGERs that has enough bytes to hold a C MPI_Status).
|
||||
bytes=`expr 4 \* $ac_cv_sizeof_int + $ac_cv_sizeof_size_t`
|
||||
num_integers=`expr $bytes / $ac_cv_sizeof_int`
|
||||
sanity=`expr $num_integers \* $ac_cv_sizeof_int`
|
||||
AC_MSG_NOTICE([C MPI_Status is $bytes bytes long])
|
||||
AC_MSG_CHECKING([for the value of MPI_STATUS_SIZE])
|
||||
num_ints=`expr $bytes / $ac_cv_sizeof_int`
|
||||
sanity=`expr $num_ints \* $ac_cv_sizeof_int`
|
||||
AS_IF([test "$sanity" != "$bytes"],
|
||||
[AC_MSG_RESULT([unknown!])
|
||||
AC_MSG_WARN([WARNING: Size of C int: $ac_cv_sizeof_int])
|
||||
@ -257,7 +273,7 @@ AC_DEFUN([OMPI_SETUP_MPI_FORTRAN],[
|
||||
AC_MSG_WARN([WARNING: Size of Fortran INTEGER: $OMPI_SIZEOF_FORTRAN_INTEGER])
|
||||
AC_MSG_WARN([Could not make this work out evenly...!])
|
||||
AC_MSG_ERROR([Cannot continue])])
|
||||
OMPI_FORTRAN_STATUS_SIZE=$num_integers
|
||||
OMPI_FORTRAN_STATUS_SIZE=$num_ints
|
||||
AC_MSG_RESULT([$OMPI_FORTRAN_STATUS_SIZE Fortran INTEGERs])
|
||||
AC_SUBST(OMPI_FORTRAN_STATUS_SIZE)
|
||||
|
||||
|
@ -74,8 +74,18 @@ module mpi_f08_types
|
||||
integer :: MPI_SOURCE
|
||||
integer :: MPI_TAG
|
||||
integer :: MPI_ERROR
|
||||
integer(C_INT) OMPI_PRIVATE :: c_cancelled
|
||||
integer(C_SIZE_T) OMPI_PRIVATE :: c_count
|
||||
! The mpif.h interface uses MPI_STATUS_SIZE to know how long of
|
||||
! an array of INTEGERs is necessary to hold a C MPI_Status.
|
||||
! Effectively do the same thing here: pad out this datatype with
|
||||
! as many INTEGERs as there are C int's can fit in
|
||||
! sizeof(MPI_Status) bytes -- see MPI_Status_ctof() for an
|
||||
! explanation why.
|
||||
!
|
||||
! This padding makes this F08 Type(MPI_Status) be the same size
|
||||
! as the mpif.h status (i.e., an array of MPI_STATUS_SIZE
|
||||
! INTEGERs), which is critical for MPI_Status_ctof() to not
|
||||
! overwrite memory.
|
||||
integer OMPI_PRIVATE :: internal(MPI_STATUS_SIZE - 3)
|
||||
end type MPI_Status
|
||||
|
||||
!
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user