【发布时间】:2017-02-06 17:33:12
【问题描述】:
使用Fortran,我正在尝试为动态分配的结构构建派生数据类型,但它得到了新类型的错误范围,代码如下:
PROGRAM MAIN
IMPLICIT NONE
INCLUDE 'mpif.h'
INTEGER :: I
INTEGER :: MYID,NUMPROCS,IError
INTEGER :: Extent,Size,Disp(2)
INTEGER :: Status(MPI_STATUS_SIZE)
INTEGER :: New_Type, Blocks(3), Types(3), Offsets(3), POS(2)
INTEGER :: POS_(4)
INTEGER :: ElmOffset(3),Send_Type
INTEGER :: M
TYPE Struct
INTEGER :: N
REAL :: A
REAL :: B(2)
END TYPE Struct
TYPE(Struct),ALLOCATABLE :: Structs(:)
M=9
CALL MPI_INIT( IError )
CALL MPI_COMM_SIZE( MPI_COMM_WORLD, NUMPROCS, IError )
CALL MPI_COMM_RANK( MPI_COMM_WORLD, MYID, IError )
ALLOCATE( Structs(M) )
DO I=1,M
Structs(I)%N = I*1000 + MYID
Structs(I)%A = 250.0_8 + MYID*1.0
Structs(I)%B(1) = 10.0_8 + MYID*1.0
Structs(I)%B(2) = 20.0_8 + MYID*1.0
END DO
CALL MPI_GET_ADDRESS( Structs(1)%N, POS_(1), IError )
CALL MPI_GET_ADDRESS( Structs(1)%A, POS_(2), IError )
CALL MPI_GET_ADDRESS( Structs(1)%B(1), POS_(3), IError )
CALL MPI_GET_ADDRESS( Structs(1)%B(2), POS_(4), IError )
POS_=POS_ - POS_(1)
IF (MYID.EQ.0) THEN
WRITE(*,*) MYID, POS_
END IF
Types(1) = MPI_INTEGER
Types(2) = MPI_DOUBLE_PRECISION
Types(3) = MPI_DOUBLE_PRECISION
Offsets(1) = 0
CALL MPI_GET_ADDRESS( Structs(1)%N, Disp(1), IError )
CALL MPI_GET_ADDRESS( Structs(1)%A, Disp(2), IError )
Offsets(2) = Offsets(1) + Blocks(1)*( Disp(2)-Disp(1) )
Disp(1) = Disp(2)
CALL MPI_GET_ADDRESS( Structs(1)%B(1), Disp(2), IError )
Offsets(3) = Offsets(2) + Blocks(2)*( Disp(2)-Disp(1) )
CALL MPI_TYPE_STRUCT( 3, Blocks, Offsets, Types, New_Type, IError )
CALL MPI_TYPE_COMMIT( New_Type, IError )
CALL MPI_TYPE_EXTENT(New_Type, Extent, IError)
CALL MPI_TYPE_SIZE(New_Type, Size, IError)
IF (MYID.EQ.0) THEN
WRITE(*,*) 'New_Type extents = ', Extent
WRITE(*,*) 'New_Type size = ', Size
END IF
CALL MPI_GET_ADDRESS( Structs(1)%N, ElmOffset(1), IError )
CALL MPI_GET_ADDRESS( Structs(2)%N, ElmOffset(2), IError )
CALL MPI_GET_ADDRESS( Structs(3)%N, ElmOffset(3), IError )
ElmOffset=ElmOffset - ElmOffset(1)
IF (MYID.EQ.0) THEN
WRITE(*,*) MYID,ElmOffset
END IF
CALL MPI_TYPE_CREATE_HINDEXED_BLOCK( 3, 1, ElmOffset, New_Type, Send_Type, IError )
CALL MPI_TYPE_COMMIT( Send_Type, IError )
CALL MPI_TYPE_EXTENT( Send_Type, Extent, IError )
CALL MPI_TYPE_SIZE( Send_Type, Size, IError )
IF (MYID.EQ.0) THEN
WRITE(*,*) 'Send_Type extents = ', Extent
WRITE(*,*) 'Send_Type size = ', Size
END IF
CALL MPI_TYPE_FREE(Send_Type,IError)
CALL MPI_TYPE_FREE(New_Type,IError)
CALL MPI_FINALIZE(IError)
END PROGRAM MAIN
输出如下:
POS_ : 0 8 16 24
New_Type Extents : 32
New_Type Size : 28
以上结果显示没有问题
ElemOffsets : 0 32 64
Send_Type Extents : -32 <= Problem is here !!! It should be 96
Send_Type Size : 84
我实际上想使用派生数据类型发送 3 个结构块:Send_Type
IF (MYID.EQ.0) THEN
DO I=1,(NUMPROCS-1)
CALL MPI_SEND( Structs(1)%N, 1, Send_Type, I, 0, MPI_COMM_WORLD, IError)
ELSE
CALL MPI_RECV( Structs(1)%N, 1, Send_Type, 0, 0, MPI_COMM_WORLD, Status, IError)
END IF
WRITE( (MYID+10),*) Structs(1)%N, Structs(1)%A
WRITE( (MYID+10),*) Structs(1)%B(1), Structs(1)%B(2)
WRITE( (MYID+100),*) Structs(3)%N, Structs(3)%A
WRITE( (MYID+100),*) Structs(3)%B(1), Structs(3)%B(2)
但是,出现错误:程序异常 - 访问冲突
我不知道怎么了... 但肯定是Send_Type没有正确创建
这样的问题怎么解决?
【问题讨论】: