为什么此示例代码(f90、MPI、派生类型)会导致无效 read/write(valgrind 或 dmalloc)?
Why does this sample code (f90, MPI, derived types) causes invalid read/write (valgrind or dmalloc)?
这是被控代码(与我问的另一个问题有关):
program foo
use mpi
implicit none
type double_st
sequence
real(kind(0.d0)) :: x,y,z
integer :: acc
end type double_st
integer, parameter :: n=8
INTEGER :: MPI_CADNA_DST
integer :: nproc, iprank
INTEGER :: IERR, STAT(MPI_STATUS_SIZE)
INTEGER :: MPI_CADNA_DST_TMP
INTEGER ::&
COUNT=4,&
BLOCKLENGTHS(4)=(/1,1,1,1/),&
TYPES(4)=(/MPI_DOUBLE_PRECISION,&
MPI_DOUBLE_PRECISION,&
MPI_DOUBLE_PRECISION,&
MPI_INTEGER/)
INTEGER(KIND=MPI_ADDRESS_KIND) :: DISPLS(4), LB, EXTENT
TYPE(DOUBLE_ST) :: DST
INTEGER :: I
type(double_st), allocatable :: bufs(:), bufr(:)
allocate(bufs(n), bufr(n))
CALL MPI_INIT(IERR)
CALL MPI_COMM_SIZE(MPI_COMM_WORLD, NPROC, IERR)
CALL MPI_COMM_RANK(MPI_COMM_WORLD, IPRANK, IERR)
CALL MPI_GET_ADDRESS(DST%X, DISPLS(1))
CALL MPI_GET_ADDRESS(DST%Y, DISPLS(2))
CALL MPI_GET_ADDRESS(DST%Z, DISPLS(3))
CALL MPI_GET_ADDRESS(DST%ACC, DISPLS(4))
DO I=4,1,-1
DISPLS(I)=DISPLS(I)-DISPLS(1)
ENDDO
CALL MPI_TYPE_CREATE_STRUCT(4,BLOCKLENGTHS,DISPLS,TYPES, MPI_CADNA_DST_TMP,IERR)
CALL MPI_TYPE_COMMIT(MPI_CADNA_DST_TMP,IERR)
CALL MPI_TYPE_GET_EXTENT(MPI_CADNA_DST_TMP, LB, EXTENT, IERR)
CALL MPI_TYPE_CREATE_RESIZED(MPI_CADNA_DST_TMP, LB, EXTENT, MPI_CADNA_DST, IERR)
CALL MPI_TYPE_COMMIT(MPI_CADNA_DST,IERR)
bufs(:)%x=iprank
bufs(:)%y=iprank
bufs(:)%z=iprank
bufs(:)%acc=iprank
call mpi_send(bufs(1), n, mpi_cadna_dst, 1-iprank, 0, mpi_comm_world, ierr)
call mpi_recv(bufr(1), n, mpi_cadna_dst, 1-iprank, 0, mpi_comm_world, stat, ierr)
deallocate(bufs, bufr)
end program foo
使用 4.0 或 5.0 版的 intelMPI 编译,我在发送时遇到 valgrind 或 dmalloc 的无效 read/write 错误。对于 openMPI,最小示例并不清楚,但我在提取它的大代码中遇到了与此通信类似的问题。
感谢您的帮助!
看起来 sequence
的使用是这里的罪魁祸首。由于您的数据没有以相同的方式对齐,因此使用 sequence
关键字强制线性打包会产生一些未对齐的访问,可能是在写入其中一个数组时。删除它就可以了。
我认为他使用带序列的派生类型定义(编写代码的人)。SEQUENCE 导致派生类型的组件存储在与类型定义中列出的相同序列中。如果指定了序列,组件定义中指定的所有派生类型都必须是序列types.You应该告诉我们更多关于编译的信息,你是在Linux还是Windows。
这是被控代码(与我问的另一个问题
program foo
use mpi
implicit none
type double_st
sequence
real(kind(0.d0)) :: x,y,z
integer :: acc
end type double_st
integer, parameter :: n=8
INTEGER :: MPI_CADNA_DST
integer :: nproc, iprank
INTEGER :: IERR, STAT(MPI_STATUS_SIZE)
INTEGER :: MPI_CADNA_DST_TMP
INTEGER ::&
COUNT=4,&
BLOCKLENGTHS(4)=(/1,1,1,1/),&
TYPES(4)=(/MPI_DOUBLE_PRECISION,&
MPI_DOUBLE_PRECISION,&
MPI_DOUBLE_PRECISION,&
MPI_INTEGER/)
INTEGER(KIND=MPI_ADDRESS_KIND) :: DISPLS(4), LB, EXTENT
TYPE(DOUBLE_ST) :: DST
INTEGER :: I
type(double_st), allocatable :: bufs(:), bufr(:)
allocate(bufs(n), bufr(n))
CALL MPI_INIT(IERR)
CALL MPI_COMM_SIZE(MPI_COMM_WORLD, NPROC, IERR)
CALL MPI_COMM_RANK(MPI_COMM_WORLD, IPRANK, IERR)
CALL MPI_GET_ADDRESS(DST%X, DISPLS(1))
CALL MPI_GET_ADDRESS(DST%Y, DISPLS(2))
CALL MPI_GET_ADDRESS(DST%Z, DISPLS(3))
CALL MPI_GET_ADDRESS(DST%ACC, DISPLS(4))
DO I=4,1,-1
DISPLS(I)=DISPLS(I)-DISPLS(1)
ENDDO
CALL MPI_TYPE_CREATE_STRUCT(4,BLOCKLENGTHS,DISPLS,TYPES, MPI_CADNA_DST_TMP,IERR)
CALL MPI_TYPE_COMMIT(MPI_CADNA_DST_TMP,IERR)
CALL MPI_TYPE_GET_EXTENT(MPI_CADNA_DST_TMP, LB, EXTENT, IERR)
CALL MPI_TYPE_CREATE_RESIZED(MPI_CADNA_DST_TMP, LB, EXTENT, MPI_CADNA_DST, IERR)
CALL MPI_TYPE_COMMIT(MPI_CADNA_DST,IERR)
bufs(:)%x=iprank
bufs(:)%y=iprank
bufs(:)%z=iprank
bufs(:)%acc=iprank
call mpi_send(bufs(1), n, mpi_cadna_dst, 1-iprank, 0, mpi_comm_world, ierr)
call mpi_recv(bufr(1), n, mpi_cadna_dst, 1-iprank, 0, mpi_comm_world, stat, ierr)
deallocate(bufs, bufr)
end program foo
使用 4.0 或 5.0 版的 intelMPI 编译,我在发送时遇到 valgrind 或 dmalloc 的无效 read/write 错误。对于 openMPI,最小示例并不清楚,但我在提取它的大代码中遇到了与此通信类似的问题。
感谢您的帮助!
看起来 sequence
的使用是这里的罪魁祸首。由于您的数据没有以相同的方式对齐,因此使用 sequence
关键字强制线性打包会产生一些未对齐的访问,可能是在写入其中一个数组时。删除它就可以了。
我认为他使用带序列的派生类型定义(编写代码的人)。SEQUENCE 导致派生类型的组件存储在与类型定义中列出的相同序列中。如果指定了序列,组件定义中指定的所有派生类型都必须是序列types.You应该告诉我们更多关于编译的信息,你是在Linux还是Windows。