Actual source code: sfneighbor.c

petsc-3.12.5 2020-03-29
Report Typos and Errors
  1:  #include <../src/vec/is/sf/impls/basic/sfpack.h>
  2:  #include <../src/vec/is/sf/impls/basic/sfbasic.h>

  4: #if defined(PETSC_HAVE_MPI_NEIGHBORHOOD_COLLECTIVES)

  6: typedef struct {
  7:   SFBASICHEADER;
  8:   MPI_Comm      comms[2];       /* Communicators with distributed topology in both directions */
  9:   PetscBool     initialized[2]; /* Are the two communicators initialized? */
 10:   PetscMPIInt   *rootdispls,*rootcounts,*leafdispls,*leafcounts; /* displs/counts for non-distinguished ranks */
 11:   PetscInt      rootdegree,leafdegree; /* Number of non-distinguished root/leaf ranks, equal to outdegree or indegree in neigborhood collectives, depending on PetscSFDirection */
 12: } PetscSF_Neighbor;

 14: /*===================================================================================*/
 15: /*              Internal utility routines                                            */
 16: /*===================================================================================*/

 18: /* Get the communicator with distributed graph topology, which is not cheap to build so we do it on demand (instead of at PetscSFSetUp time) */
 19: static PetscErrorCode PetscSFGetDistComm_Neighbor(PetscSF sf,PetscSFDirection direction,MPI_Comm *distcomm)
 20: {
 21:   PetscErrorCode    ierr;
 22:   PetscSF_Neighbor  *dat = (PetscSF_Neighbor*)sf->data;
 23:   PetscInt          nrootranks,ndrootranks,nleafranks,ndleafranks;
 24:   const PetscMPIInt *rootranks,*leafranks;
 25:   MPI_Comm          comm;

 28:   PetscSFGetRootInfo_Basic(sf,&nrootranks,&ndrootranks,&rootranks,NULL,NULL);      /* Which ranks will access my roots (I am a destination) */
 29:   PetscSFGetLeafInfo_Basic(sf,&nleafranks,&ndleafranks,&leafranks,NULL,NULL,NULL); /* My leaves will access whose roots (I am a source) */

 31:   if (!dat->initialized[direction]) {
 32:     const PetscMPIInt indegree  = nrootranks-ndrootranks,*sources      = rootranks+ndrootranks;
 33:     const PetscMPIInt outdegree = nleafranks-ndleafranks,*destinations = leafranks+ndleafranks;
 34:     MPI_Comm          *mycomm   = &dat->comms[direction];
 35:     PetscObjectGetComm((PetscObject)sf,&comm);
 36:     if (direction == PETSCSF_LEAF2../../../../../.._REDUCE) {
 37:       MPI_Dist_graph_create_adjacent(comm,indegree,sources,dat->rootcounts/*src weights*/,outdegree,destinations,dat->leafcounts/*dest weights*/,MPI_INFO_NULL,1/*reorder*/,mycomm);
 38:     } else { /* PETSCSF_../../../../../..2LEAF_BCAST, reverse src & dest */
 39:       MPI_Dist_graph_create_adjacent(comm,outdegree,destinations,dat->leafcounts/*src weights*/,indegree,sources,dat->rootcounts/*dest weights*/,MPI_INFO_NULL,1/*reorder*/,mycomm);
 40:     }
 41:     dat->initialized[direction] = PETSC_TRUE;
 42:   }
 43:   *distcomm = dat->comms[direction];
 44:   return(0);
 45: }

 47: static PetscErrorCode PetscSFPackGet_Neighbor(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,const void *rootdata,PetscMemType leafmtype,const void *leafdata,PetscSFPack *mylink)
 48: {
 49:   PetscErrorCode       ierr;

 52:   PetscSFPackGet_Basic_Common(sf,unit,rootmtype,rootdata,leafmtype,leafdata,1/*nrootreqs*/,1/*nleafreqs*/,mylink);
 53:   return(0);
 54: }

 56: /*===================================================================================*/
 57: /*              Implementations of SF public APIs                                    */
 58: /*===================================================================================*/
 59: static PetscErrorCode PetscSFSetUp_Neighbor(PetscSF sf)
 60: {
 61:   PetscErrorCode   ierr;
 62:   PetscSF_Neighbor *dat = (PetscSF_Neighbor*)sf->data;
 63:   PetscInt         i,j,nrootranks,ndrootranks,nleafranks,ndleafranks;
 64:   const PetscInt   *rootoffset,*leafoffset;
 65:   PetscMPIInt      m,n;

 68:   PetscSFSetUp_Basic(sf);
 69:   PetscSFGetRootInfo_Basic(sf,&nrootranks,&ndrootranks,NULL,&rootoffset,NULL);
 70:   PetscSFGetLeafInfo_Basic(sf,&nleafranks,&ndleafranks,NULL,&leafoffset,NULL,NULL);

 72:   dat->rootdegree = nrootranks-ndrootranks;
 73:   dat->leafdegree = nleafranks-ndleafranks;

 75:   /* Only setup MPI displs/counts for non-distinguished ranks. Distinguished ranks use shared memory */
 76:   PetscMalloc4(dat->rootdegree,&dat->rootdispls,dat->rootdegree,&dat->rootcounts,dat->leafdegree,&dat->leafdispls,dat->leafdegree,&dat->leafcounts);
 77:   for (i=ndrootranks,j=0; i<nrootranks; i++,j++) {
 78:     PetscMPIIntCast(rootoffset[i]-rootoffset[ndrootranks],&m); dat->rootdispls[j] = m;
 79:     PetscMPIIntCast(rootoffset[i+1]-rootoffset[i],        &n); dat->rootcounts[j] = n;
 80:   }

 82:   for (i=ndleafranks,j=0; i<nleafranks; i++,j++) {
 83:     PetscMPIIntCast(leafoffset[i]-leafoffset[ndleafranks],&m); dat->leafdispls[j] = m;
 84:     PetscMPIIntCast(leafoffset[i+1]-leafoffset[i],        &n); dat->leafcounts[j] = n;
 85:   }
 86:   return(0);
 87: }

 89: static PetscErrorCode PetscSFReset_Neighbor(PetscSF sf)
 90: {
 91:   PetscErrorCode       ierr;
 92:   PetscInt             i;
 93:   PetscSF_Neighbor     *dat = (PetscSF_Neighbor*)sf->data;

 96:   if (dat->inuse) SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_ARG_WRONGSTATE,"Outstanding operation has not been completed");
 97:   PetscFree4(dat->rootdispls,dat->rootcounts,dat->leafdispls,dat->leafcounts);
 98:   for (i=0; i<2; i++) {
 99:     if (dat->initialized[i]) {
100:       MPI_Comm_free(&dat->comms[i]);
101:       dat->initialized[i] = PETSC_FALSE;
102:     }
103:   }
104:   PetscSFReset_Basic(sf); /* Common part */
105:   return(0);
106: }

108: static PetscErrorCode PetscSFDestroy_Neighbor(PetscSF sf)
109: {

113:   PetscSFReset_Neighbor(sf);
114:   PetscFree(sf->data);
115:   return(0);
116: }

118: static PetscErrorCode PetscSFBcastAndOpBegin_Neighbor(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,const void *rootdata,PetscMemType leafmtype,void *leafdata,MPI_Op op)
119: {
120:   PetscErrorCode       ierr;
121:   PetscSFPack          link;
122:   const PetscInt       *rootloc = NULL;
123:   PetscSF_Neighbor     *dat = (PetscSF_Neighbor*)sf->data;
124:   MPI_Comm             distcomm;

127:   PetscSFPackGet_Neighbor(sf,unit,rootmtype,rootdata,leafmtype,leafdata,&link);
128:   PetscSFGetRootIndicesWithMemType_Basic(sf,rootmtype,&rootloc);
129:   PetscSFPackRootData(sf,link,rootloc,rootdata,PETSC_TRUE);

131:   /* Do neighborhood alltoallv for non-distinguished ranks */
132:   PetscSFGetDistComm_Neighbor(sf,PETSCSF_../../../../../..2LEAF_BCAST,&distcomm);
133:   MPI_Start_ineighbor_alltoallv(dat->rootdegree,dat->leafdegree,link->rootbuf[rootmtype],dat->rootcounts,dat->rootdispls,unit,link->leafbuf[leafmtype],dat->leafcounts,dat->leafdispls,unit,distcomm,link->rootreqs[PETSCSF_../../../../../..2LEAF_BCAST][rootmtype]);
134:   if (rootmtype != leafmtype) {PetscMemcpyWithMemType(leafmtype,rootmtype,link->selfbuf[leafmtype],link->selfbuf[rootmtype],link->selfbuflen*link->unitbytes);}
135:   return(0);
136: }

138: static PetscErrorCode PetscSFReduceBegin_Neighbor(PetscSF sf,MPI_Datatype unit,PetscMemType leafmtype,const void *leafdata,PetscMemType rootmtype,void *rootdata,MPI_Op op)
139: {
140:   PetscErrorCode       ierr;
141:   const PetscInt       *leafloc = NULL;
142:   PetscSFPack          link;
143:   PetscSF_Neighbor     *dat = (PetscSF_Neighbor*)sf->data;
144:   MPI_Comm             distcomm = MPI_COMM_NULL;

147:   PetscSFGetLeafIndicesWithMemType_Basic(sf,leafmtype,&leafloc);
148:   PetscSFPackGet_Neighbor(sf,unit,rootmtype,rootdata,leafmtype,leafdata,&link);
149:   PetscSFPackLeafData(sf,link,leafloc,leafdata,PETSC_TRUE);

151:   /* Do neighborhood alltoallv for non-distinguished ranks */
152:   PetscSFGetDistComm_Neighbor(sf,PETSCSF_LEAF2../../../../../.._REDUCE,&distcomm);
153:   MPI_Start_ineighbor_alltoallv(dat->leafdegree,dat->rootdegree,link->leafbuf[leafmtype],dat->leafcounts,dat->leafdispls,unit,link->rootbuf[rootmtype],dat->rootcounts,dat->rootdispls,unit,distcomm,link->rootreqs[PETSCSF_LEAF2../../../../../.._REDUCE][rootmtype]);
154:   if (rootmtype != leafmtype) {PetscMemcpyWithMemType(rootmtype,leafmtype,link->selfbuf[rootmtype],link->selfbuf[leafmtype],link->selfbuflen*link->unitbytes);}
155:   return(0);
156: }

158: static PetscErrorCode PetscSFFetchAndOpEnd_Neighbor(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,void *rootdata,PetscMemType leafmtype,const void *leafdata,void *leafupdate,MPI_Op op)
159: {
160:   PetscErrorCode       ierr;
161:   PetscSFPack          link;
162:   const PetscInt       *rootloc = NULL,*leafloc = NULL;
163:   PetscSF_Neighbor     *dat = (PetscSF_Neighbor*)sf->data;
164:   MPI_Comm             distcomm = MPI_COMM_NULL;

167:   PetscSFPackGetInUse(sf,unit,rootdata,leafdata,PETSC_OWN_POINTER,&link);
168:   PetscSFPackWaitall_Basic(link,PETSCSF_LEAF2../../../../../.._REDUCE);
169:   PetscSFGetRootIndicesWithMemType_Basic(sf,rootmtype,&rootloc);
170:   PetscSFGetLeafIndicesWithMemType_Basic(sf,leafmtype,&leafloc);
171:   /* Process local fetch-and-op */
172:   PetscSFFetchAndOpRootData(sf,link,rootloc,rootdata,op,PETSC_TRUE);

174:   /* Bcast the updated root buffer back to leaves */
175:   PetscSFGetDistComm_Neighbor(sf,PETSCSF_../../../../../..2LEAF_BCAST,&distcomm);
176:   MPI_Start_neighbor_alltoallv(dat->rootdegree,dat->leafdegree,link->rootbuf[rootmtype],dat->rootcounts,dat->rootdispls,unit,link->leafbuf[leafmtype],dat->leafcounts,dat->leafdispls,unit,distcomm);
177:   if (rootmtype != leafmtype) {PetscMemcpyWithMemType(leafmtype,rootmtype,link->selfbuf[leafmtype],link->selfbuf[rootmtype],link->selfbuflen*link->unitbytes);}
178:   PetscSFUnpackAndOpLeafData(sf,link,leafloc,leafupdate,MPIU_REPLACE,PETSC_TRUE);
179:   PetscSFPackReclaim(sf,&link);
180:   return(0);
181: }

183: PETSC_INTERN PetscErrorCode PetscSFCreate_Neighbor(PetscSF sf)
184: {
185:   PetscErrorCode   ierr;
186:   PetscSF_Neighbor *dat;

189:   sf->ops->CreateEmbeddedSF     = PetscSFCreateEmbeddedSF_Basic;
190:   sf->ops->CreateEmbeddedLeafSF = PetscSFCreateEmbeddedLeafSF_Basic;
191:   sf->ops->BcastAndOpEnd        = PetscSFBcastAndOpEnd_Basic;
192:   sf->ops->ReduceEnd            = PetscSFReduceEnd_Basic;
193:   sf->ops->FetchAndOpBegin      = PetscSFFetchAndOpBegin_Basic;
194:   sf->ops->GetLeafRanks         = PetscSFGetLeafRanks_Basic;
195:   sf->ops->View                 = PetscSFView_Basic;

197:   sf->ops->SetUp                = PetscSFSetUp_Neighbor;
198:   sf->ops->Reset                = PetscSFReset_Neighbor;
199:   sf->ops->Destroy              = PetscSFDestroy_Neighbor;
200:   sf->ops->BcastAndOpBegin      = PetscSFBcastAndOpBegin_Neighbor;
201:   sf->ops->ReduceBegin          = PetscSFReduceBegin_Neighbor;
202:   sf->ops->FetchAndOpEnd        = PetscSFFetchAndOpEnd_Neighbor;

204:   PetscNewLog(sf,&dat);
205:   sf->data = (void*)dat;
206:   return(0);
207: }
208: #endif