【问题标题】:MPI -Scatterv increasing segmentation orderMPI -Scatterv 增加分段顺序
【发布时间】:2018-03-02 12:44:24
【问题描述】:

我想通过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

仅对根进行分段

 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


    【解决方案1】:

    你的代码有两个问题。

    首先,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,但循环从0 运行到siz,这是数组末尾的一个元素。一些编译器具有启用运行时越界访问检查的选项。例如,对于 Intel Fortran,选项是 -check bounds。对于 Gfortran,选项是 -fcheck=bounds。访问结束后的数组可能会覆盖并因此改变其他数组中的值(最坏的情况,难以发现)或破坏堆指针并使程序崩溃(最好的情况,容易发现)。

    正如 Gilles Gouaillardet 所注意到的,不要使用 mpif.h。相反,use mpi 甚至更好的use mpi_f08 应该用于新开发的程序中。

    【讨论】:

    • 另外,由于MPI 任务从零开始,您可能希望countsdispls 数组从索引零开始(并相应地更新其余代码)以提高可读性(例如,counts(i) 是 MPI 任务 i 的计数)。本着同样的精神,send_ray 可能从默认索引 1 开始,除非从索引 0 开始有一些价值。
    猜你喜欢
    • 2014-06-03
    • 2016-08-03
    • 2012-05-25
    • 2012-05-27
    • 2016-12-30
    • 2012-05-21
    • 1970-01-01
    • 2011-12-24
    • 1970-01-01
    相关资源
    最近更新 更多