mpi -scatterv增加分割顺序



我想通过 MPI_Scatterv在不同大小向量的向量分配一个。当我选择以减少顺序进行的分区时,代码运行正常,但是当我选择增加的顺序时,失败就会失败。MPI_Scatterv是否仅用于减少顺序进行分区?我不知道错误在哪里。可以的代码和错误的变化。

program scatt
   include 'mpif.h'
   integer idproc, num, ierr, tag,namelen, status(MPI_STATUS_SIZE),comm
    character *(MPI_MAX_PROCESSOR_NAME) processor_name
    integer, allocatable :: myray(:),send_ray(:)
    integer counts(3),displ(3)
    integer siz,mysize,i,k,j,total
   call MPI_INIT(ierror)
    comm = mpi_comm_world
   call MPI_COMM_SIZE(comm, num, ierror)
   call MPI_COMM_RANK(comm, idproc, ierror)
    siz=12
! create the segmentation in decreasing manner
    counts(1)=5
    counts(2)=4
    counts(3)=3
    displ(1)=0
    displ(2)=5
    displ(3)=9
   allocate(myray(counts(idproc+1)))
myray=0
! create the data to be sent on the root
    if(idproc == 0)then
        !size=count*num
        allocate(send_ray(0:siz-1))
        do i=0,siz
            send_ray(i)=i+1
        enddo
        write(*,*) send_ray
    endif
! send different data to each processor
    call MPI_Scatterv(  send_ray, counts, displ, MPI_INTEGER, &
                        myray, counts,  MPI_INTEGER, &
                        0,comm,ierr)
    write(*,*)"myid= ",idproc," ray= ",myray
   call MPI_FINALIZE(ierr)
   end

结果确定为:

myid=            1  ray=            6           7           8           9
myid=            0  ray=            1           2           3           4           5
myid=            2  ray=           10          11          12

当我以增加细分顺序编写相同的代码

 counts(1)=2
 counts(2)=4
 counts(3)=6
 displ(1)=0
 displ(2)=2
 displ(3)=6

分割仅针对root

 myid=            0  ray=            1           2

错误消息是:

Fatal error in PMPI_Scatterv: Message truncated, error stack:
PMPI_Scatterv(671)......................: MPI_Scatterv(sbuf=(nil), scnts=0x6b4da0, displs=0x6b4db0, MPI_INTEGER, rbuf=0x26024b0,
rcount=2, MPI_INTEGER, root=0, MPI_COMM_WORLD) failed
MPIR_Scatterv_impl(211).................: 
I_MPIR_Scatterv_intra(278)..............: Failure during collective
I_MPIR_Scatterv_intra(272)..............: 
MPIR_Scatterv(147)......................: 
MPIDI_CH3_PktHandler_EagerShortSend(441): Message from rank 0 and tag 6 truncated; 16 bytes received but buffer size is 8
Fatal error in PMPI_Scatterv: Message truncated, error stack:
PMPI_Scatterv(671)................: MPI_Scatterv(sbuf=(nil), scnts=0x6b4da0, displs=0x6b4db0, MPI_INTEGER, rbuf=0x251f4b0, rcount=2, MPI_INTEGER, root=0, MPI_COMM_WORLD) failed
MPIR_Scatterv_impl(211)...........: 
I_MPIR_Scatterv_intra(278)........: Failure during collective
I_MPIR_Scatterv_intra(272)........: 
MPIR_Scatterv(147)................: 
MPIDI_CH3U_Receive_data_found(131): Message from rank 0 and tag 6 truncated; 24 bytes received but buffer size is 8
forrtl: error (69): process interrupted (SIGINT)

您的代码中有两个问题。

首先,MPI_Scatterv的调用是错误的。接收缓冲区的大小必须是标量,而不是数组,并且仅在调用等级中给出数组的大小。在您的情况下,您需要将counts的第二次发生更改为counts(idproc+1)

call MPI_Scatterv(send_ray, counts, displ,    MPI_INTEGER, &
                  myray,    counts(idproc+1), MPI_INTEGER, &
                  0, comm, ierr)

同样适用于免费操作MPI_Gatherv-本地发送缓冲区的大小也是标量。

另一个问题是此初始化循环中的界外访问:

    allocate(send_ray(0:siz-1))
    do i=0,siz
        send_ray(i)=i+1
    enddo

此处的send_ray是用0:siz-1分配的,但是循环从0siz,这是段落末端的一个元素。一些编译器可以选择启用运行时间外部访问检查。例如,使用Intel Fortran,选项是-check bounds。对于Gfortran,该选项是-fcheck=bounds。访问阵列超越它们的末端可能会覆盖,从而改变其他阵列(最坏的情况,难以发现)或破坏堆指针并崩溃您的程序(最好的情况,易于发现)。

正如Gilles Gouaillardet所注意到的那样,请勿使用mpif.h。相反,use mpi甚至更好的use mpi_f08应在新开发的程序中使用。

最新更新