/* makeSendRecvIVLs.c */
#include "../spoolesMPI.h"
/*--------------------------------------------------------------------*/
/*
-----------------------------------------------------------------
purpose -- to analyze and organize communication. it was written
in support of a distributed matrix-vector multiply but can be
used for other applications.
each processor has a list of items it "supports" or needs found
in the supportedIV object. the globalmapIV object contains the
map from items to owning processors. we need to figure out what
items this processor will send to and receive from each other
processor. this information is found in the sendIVL and recvIVL
objects.
on return, list jproc of sendIVL contains the items owned by
this processor and needed by jproc.
on return, list jproc of recvIVL contains the items needed by
this processor and owned by jproc.
as a concrete example, consider a distributed Y = A * X.
the matrix A, the right hand side X and the vector Y are
distributed among processors.
consider the case where the supportedIV object contains the rows
of X that are needed by this processor to perform its part of the
matrix-vector multiply. globalmapIV contains the map from rows
of X to the owning processors. on return, list jproc of sendIVL
contains the row indices of X owned by this processor that are
needed by processor jproc. on return, list jproc of recvIVL
contains the row indices of X needed by this processor that are
owned by processor jproc.
consider the case where the supportedIV object contains the rows
of Y that will be updated by this processor when it performs it
part of the matrix-vector multiply. globalmapIV contains the map
from rows of Y to their owning processors. on return, list jproc
of recvIVL contains the row indices of Y on this processor that
need to be sent to their owner, processor jproc. on return, list
jproc of sendIVL contains the row indices of Y owned by this
processor that will be sent by processor jproc to this processor.
created -- 98aug01, cca
-----------------------------------------------------------------
*/
void
makeSendRecvIVLs (
IV *supportedIV,
IV *globalmapIV,
IVL *sendIVL,
IVL *recvIVL,
int stats[],
int msglvl,
FILE *msgFile,
int firsttag,
MPI_Comm comm
) {
int count, ii, item, jproc, maxitem, myid, nitem, nproc ;
int *head, *items, *link, *list, *map ;
/*
---------------
check the input
---------------
*/
if ( supportedIV == NULL || globalmapIV == NULL
|| sendIVL == NULL || recvIVL == NULL
|| stats == NULL || (msglvl > 0 && msgFile == NULL) ) {
fprintf(stderr, "\n fatal error in makeSendRecvIVLs()"
"\n bad input\n") ;
exit(-1) ;
}
IV_sizeAndEntries(supportedIV, &nitem, &items) ;
if ( nitem == 0 ) {
maxitem = 0 ;
} else {
maxitem = items[nitem-1] ;
}
map = IV_entries(globalmapIV) ;
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n inside makeSendRecvIVLs()"
"\n supportedIV") ;
IV_writeForHumanEye(supportedIV, msgFile) ;
fprintf(msgFile, "\n globalmapIV") ;
IV_writeForHumanEye(globalmapIV, msgFile) ;
fflush(msgFile) ;
}
/*
---------------------------------------
get id of self and number of processors
---------------------------------------
*/
MPI_Comm_rank(comm, &myid) ;
MPI_Comm_size(comm, &nproc) ;
/*
----------------------------------------------------
link the items into lists via their owning processor
----------------------------------------------------
*/
head = IVinit(nproc, -1) ;
link = IVinit(1 + maxitem, -1) ;
for ( ii = 0 ; ii < nitem ; ii++ ) {
item = items[ii] ;
jproc = map[item] ;
link[item] = head[jproc] ;
head[jproc] = item ;
}
if ( msglvl > 2 ) {
fprintf(msgFile, "\n\n items linked by owning processor") ;
fflush(msgFile) ;
}
/*
---------------------------------------
initialize and fill the recvIVL object.
list jproc contains the items that
this processor needs from jproc.
---------------------------------------
*/
IVL_init1(recvIVL, IVL_CHUNKED, nproc) ;
if ( nitem > 0 ) {
list = IVinit(nitem, -1) ;
for ( jproc = 0 ; jproc < nproc ; jproc++ ) {
count = 0 ;
for ( item = head[jproc] ; item != -1 ; item = link[item] ) {
list[count++] = item ;
}
IVqsortUp(count, list) ;
IVL_setList(recvIVL, jproc, count, list) ;
}
IVfree(list) ;
IVfree(head) ;
IVfree(link) ;
}
if ( msglvl > 5 ) {
fprintf(msgFile, "\n\n recvIVL") ;
IVL_writeForHumanEye(recvIVL, msgFile) ;
fflush(msgFile) ;
}
/*
----------------------------------------------------------
compute the sendIVL object via an all-to-all communication
----------------------------------------------------------
*/
IVL_MPI_alltoall(recvIVL, sendIVL, stats,
msglvl, msgFile, firsttag, comm) ;
return ; }
/*--------------------------------------------------------------------*/
syntax highlighted by Code2HTML, v. 0.9.1