Search code examples
parallel-processingfortranmpi

MPI Scatterv error there is no specific subroutine for the generic ‘mpi_scatterv


I am trying to run this code, the error says 'there is no specific subroutine for the generic ‘mpi_scatterv'

program mpiscatterv
!implicit none
use mpi
real, dimension (:,:), allocatable :: r, rcv_buf
integer :: ierr, my_id, n_proc, rcv_id, snd_id, counter
integer, dimension (:), allocatable :: sendcounts, displs, rcv_count
integer, parameter :: master = 0
integer :: i,j,k
integer :: n = 0
integer :: ios_read = 0
integer :: rem ! remaining data 
integer :: div
integer :: summ = 0




open (unit=99, file ='datatest1.dat',iostat=ios_read)
if (ios_read /=0) then
        print*, 'could not be opened'
end if

!open (unit=99, file='rawdata2.dat',iostat=ios_read)
do
  read (99, *, iostat=ios_read) i,x,y

    if (ios_read > 0) then
        print*,'something is wrong'
        print*,ios_read
        stop
   else if (ios_read < 0) then
        print*, 'end of file is reached'
        exit
   else
        n = n+1
   end if
end do
rewind(99)
open(unit=98, file='rawdata2.dat')
allocate(r(2,n))

do i=1,n
read(99,*, iostat=ios_read)j,x,y
r(1,j)= x
r(2,j)= y
write (98,*) x, y
end do

close (99)
close (98)

call mpi_init(ierr)
call mpi_comm_rank(mpi_comm_world, my_id, ierr)
call mpi_comm_size(mpi_comm_world, n_proc, ierr)

rem = mod(2*n,n_proc)

allocate (sendcounts(n_proc))
allocate (displs(n_proc))
allocate (rcv_count(n_proc))
allocate (rcv_buf(2,n_proc))


counter = 1

do while (counter<=n_proc)
sendcounts(counter) = int(2*n/n_proc)
  if (rem > 0) then
      sendcounts(counter)=int(2*n/n_proc)+2
    rem = rem-2
  end if
rcv_count=sendcounts
displs(counter)=summ
summ=summ+sendcounts(counter)
counter = counter + 1
end do

counter = 1
if (my_id==0) then
   do while (counter<n_proc)
     print*,sendcounts, displs
     counter = counter + 1
   end do
end if


call MPI_Scatterv(r,sendcounts,displs,mpi_real,rcv_buf,rcv_count,mpi_real,0,mpi_comm_world,ierr)

call mpi_finalize(ierr)
end program

I have r data that I want to scatter. r is a 2 coumns and n row. I use scatterv because the data is not divisable by n_proc. When I want to compile it, it shows error, as far as I concern I already do it according to the limited guidance that I got from internet, any website. Which parameter is wrong ?


Solution

  • There are several issues with your code. I managed to reproduce your error by trying to compile your code (main.f90) with gfortran v6.3 and openMPI v3.1.4

    mpifort main.f90                                                                         
    test3.f90:85:106:                                                                                                                           
                                                                                                                                                
     call MPI_Scatterv(r(1,:),sendcounts,displs,mpi_real,rcv_buf(1,:),rcv_count,mpi_real,0,mpi_comm_world,ierr)                                 
                                                                                                              1                                 
    Error: There is no specific subroutine for the generic ‘mpi_scatterv’ at (1)
    

    On openMPI's website you can see that MPI_Scatterv requires the following:

    Input Parameters
    
    sendbuf
        Address of send buffer (choice, significant only at root). 
    sendcounts
        Integer array (of length group size) specifying the number of elements to send to each processor. 
    displs
        Integer array (of length group size). Entry i specifies the displacement (relative to sendbuf) from which to take the outgoing data to process i. 
    sendtype
        Datatype of send buffer elements (handle). 
    recvcount
        Number of elements in receive buffer (integer). 
    recvtype
        Datatype of receive buffer elements (handle). 
    root
        Rank of sending process (integer). 
    comm
        Communicator (handle). 
    

    The problems is recvcount (or in your case rcv_count) should just be a single integer.

    I should point out there are several other issues you should address:

    • As suggested by others you should uncomment implicit none
    • x and y will be undefined when you do this
    • You really should avoid sending N-dimensional arrays in MPI
    • Your rcv_buf is almost certainly the wrong size. I think it should be n/n_proc at least.

    The following code compiles, but you need to check carefully. It probably doesn't work.

    program mpiscatterv
      use mpi
      implicit none
      real, dimension (:,:), allocatable :: r, rcv_buf
      integer :: ierr, my_id, n_proc, rcv_id, snd_id, counter
      integer, dimension (:), allocatable :: sendcounts, displs
      integer, parameter :: master = 0
      integer :: i,j,k, rcv_count
      real    :: x, y
      integer :: n = 0
      integer :: ios_read = 0
      integer :: rem ! remaining data 
      integer :: div
      integer :: summ = 0
    
      open (unit=99, file ='datatest1.dat',iostat=ios_read)
      if (ios_read /=0) then
        print*, 'could not be opened'
      end if
    
      !open (unit=99, file='rawdata2.dat',iostat=ios_read)
      do
        read (99, *, iostat=ios_read) i,x,y
    
        if (ios_read > 0) then
          print*,'something is wrong'
          print*,ios_read
          stop
        else if (ios_read < 0) then
          print*, 'end of file is reached'
          exit
        else
          n = n+1
        end if
      end do
      rewind(99)
      open(unit=98, file='rawdata2.dat')
      allocate(r(2,n))
    
      do i=1,n
        read(99,*, iostat=ios_read)j,x,y
        r(1,j)= x
        r(2,j)= y
        write (98,*) x, y
      end do
    
      close (99)
      close (98)
    
      call mpi_init(ierr)
      call mpi_comm_rank(mpi_comm_world, my_id, ierr)
      call mpi_comm_size(mpi_comm_world, n_proc, ierr)
    
      rem = mod(2*n,n_proc)
    
      allocate (sendcounts(n_proc))
      allocate (displs(n_proc))
      allocate (rcv_buf(2,n/n_proc))
    
    
      counter = 1
    
      do while (counter<=n_proc)
        sendcounts(counter) = int(2*n/n_proc)
        if (rem > 0) then
          sendcounts(counter)=int(2*n/n_proc)+2
          rem = rem-2
        end if
        displs(counter)=summ
        summ=summ+sendcounts(counter)
        counter = counter + 1
      end do
    
      counter = 1
      if (my_id==0) then
        do while (counter<n_proc)
          print*,sendcounts, displs
          counter = counter + 1
        end do
      end if
    
    
      call MPI_Scatterv(r(1,:),sendcounts,displs,mpi_real,rcv_buf(1,:),rcv_count,mpi_real,0,mpi_comm_world,ierr)
    
      call mpi_finalize(ierr)
    end program