40typedef struct spm_req_manager_s {
41 MPI_Request *requests;
62 int rc, idx, flag = 0;
64 if ( reqmanager->nbreq == 0 ) {
69 rc = MPI_Testany( reqmanager->nbreq, reqmanager->requests,
70 &idx, &flag, &status );
71 assert( rc == MPI_SUCCESS );
73 if ( flag && (idx != MPI_UNDEFINED) )
75 assert( reqmanager->requests[idx] == MPI_REQUEST_NULL );
78 if ( idx < reqmanager->nbreq ) {
79 reqmanager->requests[idx] = reqmanager->requests[reqmanager->nbreq];
83 while ( (reqmanager->nbreq > 0) && flag && (idx != MPI_UNDEFINED) );
106 if ( reqmanager->nbreq == 0 ) {
111 rc = MPI_Waitany( reqmanager->nbreq, reqmanager->requests,
113 assert( rc == MPI_SUCCESS );
115 if ( idx != MPI_UNDEFINED )
117 assert( reqmanager->requests[idx] == MPI_REQUEST_NULL );
120 if ( idx < reqmanager->nbreq ) {
121 reqmanager->requests[idx] = reqmanager->requests[reqmanager->nbreq];
125 while ( (reqmanager->nbreq > 0) && (idx != MPI_UNDEFINED) );
164 newspm.
gN = oldspm->
gN;
229 size_t fltsize, valsize;
280 for ( j=0; j<oldspm->
n;
281 j++, oldl2g++, oldcol++, oldrow += nbrow, oldval += valsize )
284 nbrow = oldcol[1] - oldcol[0];
288 if ( fltsize != 0 ) {
289 spm_int_t dofj = ( dof > 0 ) ? dof : dofs[jg+1] - dofs[jg];
291 for ( i = 0; i < nbrow; i++ ) {
293 dofi += ( dof > 0 ) ? dof : dofs[ig+1] - dofs[ig];
297 valsize = nbval * fltsize;
300 if ( newg2l[jg] >= 0 ) {
304 for ( i = 0; i < nbrow; i++, newcol++ ) {
309 memcpy( newrow, oldrow, nbrow *
sizeof(
spm_int_t ) );
314 memcpy( newval, oldval, valsize );
319 owner = -newg2l[jg] - 1;
320 assert( owner != oldspm->
clustnum );
323 sendsizes[2*owner] += nbrow;
324 sendsizes[2*owner+1] += nbval;
328 for ( j=0; j < oldspm->
nnz; j++, oldcol++, oldrow++, oldval+=valsize )
334 if ( fltsize != 0 ) {
335 spm_int_t dofj = ( dof > 0 ) ? dof : dofs[jg+1] - dofs[jg];
336 spm_int_t dofi = ( dof > 0 ) ? dof : dofs[ig+1] - dofs[ig];
339 valsize = nbval * fltsize;
342 if ( newg2l[jg] >= 0 ) {
352 memcpy( newval, oldval, valsize );
356 owner = -newg2l[jg] - 1;
357 assert( owner != oldspm->
clustnum );
360 sendsizes[2*owner]++;
361 sendsizes[2*owner+1] += nbval;
373 for ( owner = 0; owner < newspm->
clustnbr; owner++ )
375 newspm->
nnz += recvsizes[ 2*owner ];
376 newspm->
nnzexp += recvsizes[ 2*owner+1 ];
421 MPI_Request *request;
424 size_t fltsize, nbval;
433 int nbcomm_max = ( newspm->
clustnbr - 1 ) * nbcomm_per_node;
439 reqmanager->requests = malloc( nbcomm_max *
sizeof( MPI_Request ) );
440 for (
int i = 0; i < nbcomm_max; i++ ) {
441 reqmanager->requests[i] = MPI_REQUEST_NULL;
443 reqmanager->nbreq_max = nbcomm_max;
458 nbelt = recvsizes[2 * newspm->
clustnum];
459 nbval = recvsizes[2 * newspm->
clustnum + 1] * fltsize;
464 request = reqmanager->requests;
465 for ( c = 0; c < newspm->
clustnbr; c++ )
470 nbelt = recvsizes[2 * c];
471 nbval = recvsizes[2 * c + 1] * fltsize;
474 assert( nbval == 0 );
487 if ( fltsize != 0 ) {
488 MPI_Irecv( values, nbval, MPI_CHAR, c,
498 reqmanager->nbreq = request - reqmanager->requests;
505struct spm_send_data_s {
510 size_t nbval, nbval_to_send;
536 struct spm_send_data_s *sendproc,
540 assert( sendproc->sent == 0 );
542 if ( sendproc->nbelt != sendproc->nbelt_to_send ) {
547 assert( reqmanager->nbreq < reqmanager->nbreq_max );
548 MPI_Isend( sendproc->colptr, sendproc->nbelt_to_send,
SPM_MPI_INT,
549 dest,
COLTAG, comm, reqmanager->requests + reqmanager->nbreq );
553 assert( reqmanager->nbreq < reqmanager->nbreq_max );
554 MPI_Isend( sendproc->rowptr, sendproc->nbelt_to_send,
SPM_MPI_INT,
555 dest,
ROWTAG, comm, reqmanager->requests + reqmanager->nbreq );
559 if ( sendproc->nbval_to_send > 0 ) {
560 assert( reqmanager->nbreq < reqmanager->nbreq_max );
561 MPI_Isend( sendproc->values, sendproc->nbval_to_send, MPI_CHAR,
562 dest,
VALTAG, comm, reqmanager->requests + reqmanager->nbreq );
600 struct spm_send_data_s *senddata,
603 struct spm_send_data_s *sendproc;
607 const char *oldval = oldspm->
values;
619 for ( j=0; j<oldspm->
n;
620 j++, oldl2g++, oldcol++, oldrow += nbrow, oldval += valsize )
623 nbrow = oldcol[1] - oldcol[0];
627 if ( fltsize != 0 ) {
628 spm_int_t dofj = (dof > 0) ? dof : dofs[jg+1] - dofs[jg];
630 for ( i = 0; i < nbrow; i++ ) {
632 dofi += (dof > 0) ? dof : dofs[ig+1] - dofs[ig];
636 valsize = nbval * fltsize;
639 if ( ( newg2l[jg] >= 0 ) ||
645 owner = -newg2l[jg] - 1;
646 assert( owner != oldspm->
clustnum );
648 sendproc = senddata + owner;
649 assert( sendproc->sent == 0 );
651 for ( i=0; i<nbrow; i++ ) {
652 sendproc->colptr[ sendproc->nbelt ] = jg;
653 sendproc->rowptr[ sendproc->nbelt ] = oldrow[i];
657 memcpy( sendproc->values + sendproc->nbval, oldval, valsize );
658 sendproc->nbval += valsize;
695 struct spm_send_data_s *senddata,
699 struct spm_send_data_s *sendproc;
703 const char *oldval = oldspm->
values;
714 for ( j=0; j<oldspm->
nnz; j++, oldcol++, oldrow++, oldval+=valsize )
720 if ( fltsize != 0 ) {
721 spm_int_t dofj = ( dof > 0 ) ? dof : dofs[jg+1] - dofs[jg];
722 spm_int_t dofi = ( dof > 0 ) ? dof : dofs[ig+1] - dofs[ig];
725 valsize = nbval * fltsize;
728 if ( newg2l[jg] >= 0 ) {
732 owner = -newg2l[jg] - 1;
733 assert( owner != oldspm->
clustnum );
735 sendproc = senddata + owner;
736 assert( sendproc->sent == 0 );
738 sendproc->colptr[sendproc->nbelt] = jg;
739 sendproc->rowptr[sendproc->nbelt] = ig;
742 memcpy( sendproc->values + sendproc->nbval, oldval, valsize );
743 sendproc->nbval += valsize;
782 struct spm_send_data_s *senddata = calloc( oldspm->
clustnbr,
sizeof(
struct spm_send_data_s ) );
788 for ( c = 0; c < oldspm->
clustnbr; c++ )
794 senddata[c].nbelt_to_send = sendsizes[2 * c];
797 senddata[c].rowptr = malloc( senddata[c].nbelt_to_send *
sizeof(
spm_int_t ) );
798 senddata[c].colptr = malloc( senddata[c].nbelt_to_send *
sizeof(
spm_int_t ) );
799 senddata[c].values = malloc( senddata[c].nbval_to_send );
812 for ( c = 0; c < oldspm->
clustnbr; c++ )
818 free( senddata[c].rowptr );
819 free( senddata[c].colptr );
820 free( senddata[c].values );
861 newspm->
dof = oldspm->
dof;
864 if ( oldspm->
dofs != NULL ) {
879 assert( (newspm->
gN == oldspm->
gN) &&
941 if ( newl2g == NULL ) {
952 return spmScatter( newspm, -1, spm, new_n, newl2g, distByColumn, spm->
comm );
967 sendsizes, recvsizes, newspm );
982 free( reqmanager.requests );
static size_t spm_size_of(spm_coeftype_t type)
Double datatype that is not converted through precision generator functions.
#define SpmDistByColumn
Distribution of the matrix storage.
int spmGather(const spmatrix_t *spm_scattered, int root, spmatrix_t *opt_spm_gathered)
Gather a distributed Sparse Matrix on a single node.
#define SPM_MPI_INT
The MPI type associated to spm_int_t.
void spmUpdateComputedFields(spmatrix_t *spm)
Update all the computed fields based on the static values stored.
int spmScatter(spmatrix_t *spm_scattered, int root, const spmatrix_t *opt_spm_gathered, spm_int_t opt_n, const spm_int_t *opt_loc2glob, int opt_distByColumn, SPM_Comm opt_comm)
Scatter the SPM thanks to loc2glob.
int spm_int_t
The main integer datatype used in spm arrays.
void spmInitDist(spmatrix_t *spm, SPM_Comm comm)
Init the spm structure with a specific communicator.
int spmConvert(int ofmttype, spmatrix_t *ospm)
Convert the storage format of the spm.
int spmRedistribute(const spmatrix_t *spm, spm_int_t new_n, const spm_int_t *newl2g, spmatrix_t *newspm)
Create a copy of a given SPM with a new distribution corresponding to the given loc2glob array.
int spmSort(spmatrix_t *spm)
Sort the subarray of edges of each vertex.
The sparse matrix data structure.
spm_int_t * spm_getandset_glob2loc(spmatrix_t *spm)
Computes the glob2loc array if needed, and returns it.
int spm_get_distribution(const spmatrix_t *spm)
Search the distribution pattern used in the spm structure.
#define VALTAG
Internal tag for values array communications.
static void spm_redist_reqmanager_test(spm_req_manager_t *reqmanager)
Make the communications progress in the request manager structure.
#define COLTAG
Internal tag for colptr array communications.
static void spm_redist_extract_local(const spmatrix_t *oldspm, const spm_int_t *newg2l, int distribution, spm_int_t *sendsizes, spm_int_t *recvsizes, spmatrix_t *newspm)
Extract the local information and compute the volumes to exchange.
static void spm_redist_send_loop_csx(const spmatrix_t *oldspm, const spm_int_t *newg2l, struct spm_send_data_s *senddata, spm_req_manager_t *reqmanager)
Fill all the send arrays from CSC/CSR format to IJV buffers and submit the send.
static void spm_redist_reqmanager_wait(spm_req_manager_t *reqmanager)
Wait for all the communications to be completed.
static void spm_redist_finalize(const spmatrix_t *oldspm, spmatrix_t *newspm, const spm_int_t *newg2l, const spm_int_t *newl2g, spm_int_t new_n)
Finalize the compuration of the newspm to correspond to oldspm redistributed thanks to newl2g.
static spm_int_t * spm_redist_get_newg2l(const spmatrix_t *oldspm, spm_int_t new_n, const spm_int_t *newl2g)
Get the new glob2loc array.
#define ROWTAG
Internal tag for rowptr array communications.
static void spm_redist_post_recv(spmatrix_t *newspm, const spm_int_t *recvsizes, int distribution, spm_req_manager_t *reqmanager)
Allocate the reqtab array and post all the required receptions for each process.
static void spm_redist_send_loop_ijv(const spmatrix_t *oldspm, const spm_int_t *newg2l, struct spm_send_data_s *senddata, spm_req_manager_t *reqmanager, int distribution)
Fill all the send arrays from IJV format to IJV buffers and submit the send.
struct spm_req_manager_s spm_req_manager_t
Data structure to manage the communication requests.
static void spm_redist_send(const spmatrix_t *oldspm, const spm_int_t *newg2l, const spm_int_t *sendsizes, spm_req_manager_t *reqmanager, int distribution)
Fill all the send arrays and send them.
static void spm_redist_reqmanager_try_sendone(spm_req_manager_t *reqmanager, struct spm_send_data_s *sendproc, int dest, MPI_Comm comm)
Submit the send request if the buffers are filled.