Fortran中的MPI_SCATTERV - 发送2D数组行

时间:2017-06-19 20:44:42

标签: fortran mpi

我有一个2D整数数组,我想将它的行发送到每个单独的进程。我假设行数(M = 5)不能被进程数整除(size = 4),所以在我的情况下,进程0将获得额外的行。 2D阵列A的大小是MxN(5x10)。

这是我的代码

PROGRAM SCATTERV_MATRIX

INCLUDE 'mpif.h'

integer :: rank, size, ierr, dest, src, tag     !MPI variables
integer :: status(MPI_STATUS_SIZE)              !MPI variables

INTEGER, PARAMETER :: N = 10                    !number of columns
INTEGER, PARAMETER :: M = 5                     !number of rows
INTEGER,  ALLOCATABLE, DIMENSION(:,:) :: A      !MxN matrix A

INTEGER :: NEWTYPE, RESIZEDTYPE                 !MPI derived data types
INTEGER,  ALLOCATABLE, DIMENSION(:,:) :: LOCAL
INTEGER,  ALLOCATABLE :: SENDCOUNTS(:), DISPLS(:)
INTEGER :: RECVCOUNT, NRBUF
INTEGER :: MMIN, MEXTRA, INTSIZE, K, I, J
INTEGER :: START, EXTENT                        !(KIND=MPI_ADRESS_KIND)

CALL MPI_INIT(ierr)
CALL MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr)
CALL MPI_COMM_SIZE(MPI_COMM_WORLD, size, ierr)

IF ( rank == 0 ) THEN                           !allocate and create 2Darray
     ALLOCATE( A (M, N) )
     K = 1
     DO I = 1, M
        DO J = 1, N
           A(I, J) = K
           K = K + 1
        END DO
     END DO
END IF

ALLOCATE( SENDCOUNTS(0:size-1), DISPLS(0:size-1) )

MMIN = M/size               !number of rows divided by number of processors
MEXTRA = MOD(M, size)       !extra rows

K = 0
DO I = 0, size-1
   IF (I < MEXTRA) THEN             !SENDCOUNTS=(/2,1,1,1/)
       SENDCOUNTS(I) = MMIN + 1
   ELSE
       SENDCOUNTS(I) = MMIN
   END IF
   DISPLS(I) = K                    !DISPLS=(/0,2,3,4/)
   K = K + SENDCOUNTS(I)
END DO

RECVCOUNT = SENDCOUNTS(rank)
ALLOCATE( LOCAL(RECVCOUNT,N) )

CALL MPI_TYPE_VECTOR(N, 1, M, MPI_INTEGER, NEWTYPE, ierr)
CALL MPI_TYPE_COMMIT(NEWTYPE, ierr)

START = 0
CALL MPI_TYPE_SIZE(MPI_INTEGER, INTSIZE, ierr)
EXTENT = 1*INTSIZE
CALL MPI_TYPE_CREATE_RESIZED(NEWTYPE, START, EXTENT, RESIZEDTYPE, ierr)
CALL MPI_TYPE_COMMIT(RESIZEDTYPE, ierr)

LOCAL(:, :) = 0

CALL MPI_SCATTERV(                        &
A, SENDCOUNTS, DISPLS, RESIZEDTYPE,       &        
LOCAL, RECVCOUNT*N, MPI_INTEGER,          &        
0, MPI_COMM_WORLD, ierr)

WRITE(*,*) rank, ':', LOCAL

CALL MPI_FINALIZE(ierr)

END PROGRAM SCATTERV_MATRIX

在成功编译后,我得到了#34;程序异常 - 访问违规&#34;错误。我以前的所有Fortan MPI程序都运行良好。代码中必定存在一些错误,可能在 MPI_SCATTERV 中。 我主要关注answer。我会感激任何建议。谢谢。

1 个答案:

答案 0 :(得分:1)

您的代码中存在错误:

INTEGER :: START, EXTENT                        !(KIND=MPI_ADRESS_KIND)

这一行应该是:

INTEGER(KIND=MPI_ADDRESS_KIND) :: START, EXTENT

在MPI中,任何与内存地址或内存位移,文件大小,文件光标等类似概念相关的内容都不能是普通整数。一些如何在评论中提供此信息,您也拼错了MPI_ADDRESS_KIND。

Vladimir F正确地指出你应该'使用MPI'而不是'INCLUDE'mpif.h''。这使编译器有机会检查数据类型。例如,gfortran提供以下错误消息:

test.f90:59:71:

 CALL MPI_TYPE_CREATE_RESIZED(NEWTYPE, START, EXTENT, RESIZEDTYPE, ierr)
                                                                       1
Error: There is no specific subroutine for the generic 

‘mpi_type_create_resized’ at (1)