I have that each processor has its own unique matrix, A
, of size Nx2
where N varies with processor. I want to collect all these matrices into one single buff (NxP)x2
matrix, where P is the number of processors.
Size wise in Fortran they are allocated like,
A(N,2)
buff(N*P,2)
As an example, let P = 2
and the A matrices for each processor be,
for Proc-1
10 11
10 11
for Proc-2
20 21
20 21
To this end I use MPI_GATHERV
and save the individual matrices in the buff matrix. If I do this then buff will look like this,
10 20
10 20
11 21
11 21
But what I want is the matrix to look like this,
10 11
10 11
20 21
20 21
In memory (I think) Buff : |10 , 10 , 20, 20 , 11 , 11 , 21 , 21|
Sample code is below,
...
! size = 2
root = 0
ALLOCATE ( count(size), num(size) )
! -----------------------------------------------------------
! Mock data
! -----------------------------------------------------------
IF(rank.eq.0) THEN
m = 2
mm = m*2
allocate(A(m,2))
A(1,1) = 10
A(1,2) = 11
A(2,1) = 10
A(2,2) = 11
ELSE
m = 2
mm = m*2
allocate(A(m,2))
A(1,1) = 20
A(1,2) = 21
A(2,1) = 20
A(2,2) = 21
END IF
! -----------------------------------------------------------
! send number of elements
! -----------------------------------------------------------
CALL MPI_GATHER(mm,1,MPI_INTEGER,count,1,MPI_INTEGER,root,cworld,ierr)
! -----------------------------------------------------------
! Figure out displacement vector needed for gatherv
! -----------------------------------------------------------
if(rank.eq.0) THEN
ALLOCATE (buff(SUM(count)/2,2), disp(size), rdisp(size))
rdisp = count
disp(1) = 0
DO i = 2,size
disp(i) = disp(i-1) + count(i-1)
END DO
END IF
! -----------------------------------------------------------
! Rank-0 gathers msg
! -----------------------------------------------------------
CALL MPI_GATHERV(A,mm,MPI_INTEGER,buff,rdisp,disp,MPI_INTEGER,root,cworld,ierr)
! -----------------------------------------------------------
! Print buff
! -----------------------------------------------------------
if(rank.eq.0) THEN
DO i = 1,sum(count)/2
print*, buff(i,:)
end do
END IF
I have looked at Using Gatherv for 2d Arrays in Fortran but am a little confused with the explanation.
I’m not very familiar with the MPI details, but is there a "simple" way to gather all the matrices and place them in the correct memory position in buff?
**** Edit ****
Fallowing what Gilles Gouaillardet suggested. I'm trying to figure how to do that,
The derived type for sending the rows should look something like this (I think),
CALL MPI_TYPE_vector(2,1,2,MPI_INTEGER,MPI_ROWS,ierr)
CALL MPI_TYPE_COMMIT(MPI_ROWS,ierr)
Then I extend,
call MPI_Type_size(MPI_INTEGER, msg_size, ierr)
lb = 0
extent = 2*msg_size
call MPI_Type_create_resized(MPI_ROWS, lb, extent , MPI_ROWS_extend, ierr)
CALL MPI_TYPE_COMMIT(, MPI_ROWS_extend,ierr)
I’m trying to understand why I need the second derived type for receiving. I’m not sure how that one should look like.