我正在尝试使用MPI_TYPE_VECTOR以便在2D计算域的重影单元之间交换信息。测试用例如下:
拓扑由垂直方向上的两个块和其他方向上的一个块组成。目标是用相邻块的相应单元填充每个块的重影单元。
如果我不使用MPI中的派生类型,通信就可以了。
PROGRAM test
USE mpi
IMPLICIT NONE
INTEGER*4, PARAMETER :: kim = 3 ! Number of cells (horizontal)
& , kjm = 2 ! Number of cells (vertical)
& , is = 1 ! Number of ghost cells
INTEGER*4, DIMENSION(1-is:kim+is,1-is:kjm+is)
& :: vect2d ! 2D vector representing the computational domain
INTEGER*4 :: i, j
! MPI Parameters
INTEGER*4, PARAMETER :: ndims = 2
INTEGER*4 :: mpicode
INTEGER*4 :: nb_procs
INTEGER*4 :: rank
INTEGER*4 :: comm
INTEGER*4 :: etiquette = 100
INTEGER*4, DIMENSION (ndims) :: dims
INTEGER*4, DIMENSION (ndims) :: coords
LOGICAL, DIMENSION (ndims) :: periods
LOGICAL :: reorganisation
INTEGER, DIMENSION(MPI_STATUS_SIZE) :: statut
INTEGER*4, DIMENSION (2*ndims) :: neighbors
INTEGER*4 :: type_column
! Initialisation MPI
CALL MPI_INIT (mpicode)
CALL MPI_COMM_SIZE (MPI_COMM_WORLD, nb_procs, mpicode)
CALL MPI_COMM_RANK (MPI_COMM_WORLD, rank, mpicode)
dims(1) = 1
dims(2) = 2
periods = .FALSE.
reorganisation = .FALSE.
CALL MPI_CART_CREATE (MPI_COMM_WORLD, ndims, dims, periods,
& reorganisation, comm, mpicode)
CALL MPI_CART_COORDS (comm, rank, ndims, coords, mpicode)
CALL MPI_CART_SHIFT (comm, 0, 1, neighbors(1), neighbors(2),
& mpicode)
CALL MPI_CART_SHIFT (comm, 1, 1, neighbors(3), neighbors(4),
& mpicode)
! Initialisation domain
DO i = 1-is, kim+is
DO j = 1-is, kjm +is
vect2d(i,j) = rank
END DO
END DO
! Communications
! Without vector type
DO i = 1, kim
CALL MPI_RECV (vect2d(i,1-is:0),
& size(vect2d(i,1-is:0)),
& MPI_INTEGER, neighbors(3), etiquette, comm,
& statut, mpicode)
CALL MPI_SEND (vect2d(i,kjm+1-is:kjm),
& size(vect2d(i,kjm+1-is:kjm)),
& MPI_INTEGER, neighbors(4), etiquette, comm,
& mpicode)
CALL MPI_RECV (vect2d(i,kjm+1:kjm+is),
& size(vect2d(i,kjm+1:kjm+is)),
& MPI_INTEGER, neighbors(4), etiquette, comm,
& statut, mpicode)
CALL MPI_SEND (vect2d(i,1:is),
& size(vect2d(i,1:is)),
& MPI_INTEGER, neighbors(3), etiquette, comm,
& mpicode)
END DO
! Write
OPEN (10,
& file = "test.dat",
& form = "formatted",
& status = "unknown")
IF (rank .EQ.1 ) WRITE(10,*) vect2D
CLOSE(10)
CALL MPI_FINALIZE(mpicode)
END PROGRAM test
在这种情况下,上部块的第一行是[10001],因此重影单元用下部块的值填充。
使用MPI_TYPE_VECTOR
PROGRAM test
USE mpi
IMPLICIT NONE
INTEGER*4, PARAMETER :: kim = 3 ! Number of cells (horizontal)
& , kjm = 2 ! Number of cells (vertical)
& , is = 1 ! Number of ghost cells
INTEGER*4, DIMENSION(1-is:kim+is,1-is:kjm+is)
& :: vect2d ! 2D vector representing the computational domain
INTEGER*4 :: i, j
! MPI Parameters
INTEGER*4, PARAMETER :: ndims = 2
INTEGER*4 :: mpicode
INTEGER*4 :: nb_procs
INTEGER*4 :: rank
INTEGER*4 :: comm
INTEGER*4 :: etiquette = 100
INTEGER*4, DIMENSION (ndims) :: dims
INTEGER*4, DIMENSION (ndims) :: coords
LOGICAL, DIMENSION (ndims) :: periods
LOGICAL :: reorganisation
INTEGER, DIMENSION(MPI_STATUS_SIZE) :: statut
INTEGER*4, DIMENSION (2*ndims) :: neighbors
INTEGER*4 :: type_column
!------------------------------------------------------------------------------
! Initialisation MPI
CALL MPI_INIT (mpicode)
CALL MPI_COMM_SIZE (MPI_COMM_WORLD, nb_procs, mpicode)
CALL MPI_COMM_RANK (MPI_COMM_WORLD, rank, mpicode)
dims(1) = 1
dims(2) = 2
periods = .FALSE.
reorganisation = .FALSE.
CALL MPI_CART_CREATE (MPI_COMM_WORLD, ndims, dims, periods,
& reorganisation, comm, mpicode)
CALL MPI_CART_COORDS (comm, rank, ndims, coords, mpicode)
CALL MPI_CART_SHIFT (comm, 0, 1, neighbors(1), neighbors(2),
& mpicode)
CALL MPI_CART_SHIFT (comm, 1, 1, neighbors(3), neighbors(4),
& mpicode)
CALL MPI_TYPE_VECTOR(is, 1, (kim+2*is),
& MPI_INTEGER, type_column, mpicode)
CALL MPI_TYPE_COMMIT(type_column, mpicode)
!------------------------------------------------------------------------------
! Initialisation domain
DO i = 1-is, kim+is
DO j = 1-is, kjm +is
vect2d(i,j) = rank
END DO
END DO
!------------------------------------------------------------------------------
! Communications
! With vector type
DO i = 1, kim
CALL MPI_RECV (vect2d(j,1-is),
& 1,
& type_column, neighbors(3), etiquette, comm,
& statut, mpicode)
CALL MPI_SEND (vect2d(i,kjm+1-is),
& 1,
& type_column, neighbors(4), etiquette, comm,
& mpicode)
CALL MPI_RECV (vect2d(i,kjm+1),
& 1,
& type_column, neighbors(4), etiquette, comm,
& statut, mpicode)
CALL MPI_SEND (vect2d(i,1),
& 1,
& type_column, neighbors(3), etiquette, comm,
& mpicode)
END DO
!------------------------------------------------------------------------------
! Write
OPEN (10,
& file = "test.dat",
& form = "formatted",
& status = "unknown")
IF (rank .EQ.1 ) WRITE(10,*) vect2D
CLOSE(10)
CALL MPI_FINALIZE(mpicode)
END PROGRAM test
在这种情况下,输出不是预期的输出,因为我得到:[11110] 我想这是我的type_column的定义,但我无法弄明白......所以欢迎任何帮助和解释!
谢谢
编辑:这是与测试用例中的矩阵相关联的域
(0,3)| (1,3)| (2,3)| (3,3)| (4,3)
(0,2)| (1,2)| (2,2)| (3,2) | (4,2)
(0,1)| (1,1)| (2,1)| (3,1) | (4,1)
(0,0)| (1,0)| (2,0)| (3,0)| (4,0)
根据我的理解,与此矩阵相关的记忆处置是:
(0,0)| (1,0)| (2,0)| (3,0)| (4,0) | (0,1)| (1,1)| (2,1)| (3,1) | (4,1) ......
答案 0 :(得分:1)
这里的主要困惑是您使用了术语“列”,但是绘制数组的方式意味着您实际上正在交换行。让我们坚持你的绘制数组的约定,并调用方向“水平”(增加第一个索引“i”的值)和“垂直”(增加第二个索引“j”的值),以避免混淆。
如果我们修复您的i< - >在评论中提到的j bug然后你的代码工作。但是,关于使用向量的重点是避免多次发送,因此,如上所述,使用基本数据类型时,向量代码不会改进。对于上面显示的模式,至少对于单深度光环,您可以使用count = kim发送连续数据。对于更深的晕圈,你需要一个矢量类型,其中count = is,blocksize = kim和stride = kim + 2 * is。完成此操作后,您将在发送和接收时使用count = 1,并通过一次调用传输所有光环。
对于水平方向上的光环交换(即交换垂直光晕),你总是需要一个count = kjm,blocksize = is和stride = km + 2 *的矢量类型。再次,在发送和接收时使用count = 1.
首先发出receive(周期性边界条件的潜在死锁)还有其他问题,这些问题不能通过先发送(因为MPI_Send可以同步实现)来完全解决,但对于您的特定测试代码,解决方案在于与术语一致并使用适当的矢量类型。