您何时会使用不同的计数或类型来发送和接收进程?

时间:2015-05-11 09:09:22

标签: mpi

MPI中描述发送和接收的许多例程--MPI_Sendrecv,MPI_Scatter等 - 都具有发送和接收的计数和类型的参数。例如,在Fortran中,MPI_Scatter的签名是:

MPI_SCATTER(SENDBUF, SENDCOUNT, SENDTYPE, 
            RECVBUF, RECVCOUNT, RECVTYPE, ROOT, COMM, IERROR)

如果发送的数据量必须与收到的数量相同,为什么还需要?这不仅仅是引入不一致的可能性吗?

需要不同计数/类型的用例是什么?

3 个答案:

答案 0 :(得分:7)

MPI要求发送和接收过程就数据类型和数量达成一致(对于点对点通信接收器可以请求更多而不是发送)。但MPI数据类型还描述了数据的内存布局,这是需要为发送方和接收方使用不同类型的一个非常常见的原因。

您特别询问Scatter和Fortran,让我们来看看这个案例。让我们考虑按行将size*n矩阵散布到不同的进程

    |---n---|  ---
     0 0 0 0    |
a =  1 1 1 1   size
     2 2 2 2    |
               ---

因此等级0获得[0 0 0 0],等级1获得[1 1 1 1]等等。

在Fortran中,那些在记忆中并不连续;所以要描述一行,你必须使用MPI_Type_vector

    call MPI_Type_vector(n, 1, size, MPI_REAL, row_type, ierr)

它描述了n个实数,但每个实例之间用大小实数分隔。

另一方面,如果接收过程只是将数据接收到一维数组中:

    real, dimension(n) :: b

然后它使用该类型来描述数据; b没有足够的空间来容纳n个实体,每个实体之间的差距为size!它希望像n * MPI_REAL一样接收数据。如果你必须发送数据列,那么这种不匹配在C中是相同的。

因此,这是以不同方式指定数据类型(以及数据)的常见原因;对于分散器,必须用数据类型描述数据,该数据类型包括保存要发送的值的较大数据结构的布局;但是分散的ee可能正在将数据接收到具有不同布局的不同数据结构中。

下面是一个简单的例子。

program scatterdemo
    use mpi
    implicit none
    real, allocatable, dimension(:,:) :: a
    real, allocatable, dimension(:) :: b
    integer :: ierr, rank, comsize
    integer, parameter :: n=4
    integer :: i
    integer :: row_type, row_type_sized, real_size
    integer(kind=MPI_ADDRESS_KIND) :: lb=0, extent

    call MPI_Init(ierr)
    call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr)
    call MPI_Comm_size(MPI_COMM_WORLD, comsize, ierr)

    if (rank == 0) then
        allocate( a(comsize, n) )
        do i=1,comsize
            a(i,:) = i-1
        enddo
    endif

    allocate( b(n) )

    call MPI_Type_size(MPI_REAL, real_size, ierr)

    call MPI_Type_vector(n, 1, comsize, MPI_REAL, row_type, ierr)
    extent = real_size*1
    call MPI_Type_create_resized(row_type, lb, extent, row_type_sized, ierr)
    call MPI_Type_commit(row_type_sized, ierr)

    call MPI_Scatter(a, 1, row_type_sized, b, n, MPI_REAL, 0, MPI_COMM_WORLD, ierr)

    print *, rank, b

    if (rank == 0) deallocate (a)
    deallocate(b)

    call MPI_Finalize(ierr)

end program scatterdemo

并使用六个处理器运行

$ mpirun -np 6 ./scatter
           0  0.0000000E+00  0.0000000E+00  0.0000000E+00  0.0000000E+00
           3   3.000000       3.000000       3.000000       3.000000
           1   1.000000       1.000000       1.000000       1.000000
           5   5.000000       5.000000       5.000000       5.000000
           2   2.000000       2.000000       2.000000       2.000000
           4   4.000000       4.000000       4.000000       4.000000

答案 1 :(得分:2)

使用MPI派生类型时,可以将数组视为某些基本数值类型的n元素,也可以将其视为某些MPI派生类型的一个或多个元素。在这种情况下,不仅计数而且数据类型可以不同,尽管它们对应于相同的缓冲区。

另一方面,它不受通信器中进程数量的影响。通信器大小始终是隐式的,并且在调用集合体时不会直接输入它。

答案 2 :(得分:0)

对于发件人,这两者是相同的,但接收者可能不知道收到了多少元素。