Actual source code: sfneighbor.c

petsc-master 2020-02-25
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;
125:   PetscMemType         rootmtype_mpi,leafmtype_mpi; /* memtypes seen by MPI */

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

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

146: static PetscErrorCode PetscSFReduceBegin_Neighbor(PetscSF sf,MPI_Datatype unit,PetscMemType leafmtype,const void *leafdata,PetscMemType rootmtype,void *rootdata,MPI_Op op)
147: {
148:   PetscErrorCode       ierr;
149:   const PetscInt       *leafloc = NULL;
150:   PetscSFPack          link;
151:   PetscSF_Neighbor     *dat = (PetscSF_Neighbor*)sf->data;
152:   MPI_Comm             distcomm = MPI_COMM_NULL;
153:   PetscMemType         rootmtype_mpi,leafmtype_mpi; /* memtypes seen by MPI */

156:   PetscSFGetLeafIndicesWithMemType_Basic(sf,leafmtype,&leafloc);
157:   PetscSFPackGet_Neighbor(sf,unit,rootmtype,rootdata,leafmtype,leafdata,&link);
158:   PetscSFPackLeafData(sf,link,leafloc,leafdata,PETSC_TRUE);

160:   /* Do neighborhood alltoallv for non-distinguished ranks */
161:   PetscSFGetDistComm_Neighbor(sf,PETSCSF_LEAF2../../../../../.._REDUCE,&distcomm);
162:   if (use_gpu_aware_mpi) {
163:     rootmtype_mpi = rootmtype;
164:     leafmtype_mpi = leafmtype;
165:   } else {
166:     rootmtype_mpi = PETSC_MEMTYPE_HOST;
167:     leafmtype_mpi = PETSC_MEMTYPE_HOST;
168:   }
169:   MPI_Start_ineighbor_alltoallv(dat->leafdegree,dat->rootdegree,link->leafbuf[leafmtype_mpi],dat->leafcounts,dat->leafdispls,unit,link->rootbuf[rootmtype_mpi],dat->rootcounts,dat->rootdispls,unit,distcomm,link->rootreqs[PETSCSF_LEAF2../../../../../.._REDUCE][rootmtype_mpi]);
170:   if (rootmtype != leafmtype) {PetscMemcpyWithMemType(rootmtype,leafmtype,link->selfbuf[rootmtype],link->selfbuf[leafmtype],link->selfbuflen*link->unitbytes);}
171:   return(0);
172: }

174: static PetscErrorCode PetscSFFetchAndOpEnd_Neighbor(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,void *rootdata,PetscMemType leafmtype,const void *leafdata,void *leafupdate,MPI_Op op)
175: {
176:   PetscErrorCode       ierr;
177:   PetscSFPack          link;
178:   const PetscInt       *rootloc = NULL,*leafloc = NULL;
179:   PetscSF_Neighbor     *dat = (PetscSF_Neighbor*)sf->data;
180:   PetscMemType         rootmtype_mpi,leafmtype_mpi; /* memtypes seen by MPI */
181:   MPI_Comm             distcomm = MPI_COMM_NULL;

184:   PetscSFPackGetInUse(sf,unit,rootdata,leafdata,PETSC_OWN_POINTER,&link);
185:   PetscSFPackWaitall(link,PETSCSF_LEAF2../../../../../.._REDUCE);
186:   PetscSFGetRootIndicesWithMemType_Basic(sf,rootmtype,&rootloc);
187:   PetscSFGetLeafIndicesWithMemType_Basic(sf,leafmtype,&leafloc);
188:   /* Process local fetch-and-op */
189:   PetscSFFetchAndOpRootData(sf,link,rootloc,rootdata,op,PETSC_TRUE);

191:   /* Bcast the updated rootbuf back to leaves */
192:   PetscSFGetDistComm_Neighbor(sf,PETSCSF_../../../../../..2LEAF_BCAST,&distcomm);
193:   if (use_gpu_aware_mpi) {
194:     rootmtype_mpi = rootmtype;
195:     leafmtype_mpi = leafmtype;
196:   } else {
197:     rootmtype_mpi = PETSC_MEMTYPE_HOST;
198:     leafmtype_mpi = PETSC_MEMTYPE_HOST;
199:   }
200:   MPI_Start_neighbor_alltoallv(dat->rootdegree,dat->leafdegree,link->rootbuf[rootmtype_mpi],dat->rootcounts,dat->rootdispls,unit,link->leafbuf[leafmtype_mpi],dat->leafcounts,dat->leafdispls,unit,distcomm);
201:   if (rootmtype != leafmtype) {PetscMemcpyWithMemType(leafmtype,rootmtype,link->selfbuf[leafmtype],link->selfbuf[rootmtype],link->selfbuflen*link->unitbytes);}
202:   PetscSFUnpackAndOpLeafData(sf,link,leafloc,leafupdate,MPIU_REPLACE,PETSC_TRUE);
203:   PetscSFPackReclaim(sf,&link);
204:   return(0);
205: }

207: PETSC_INTERN PetscErrorCode PetscSFCreate_Neighbor(PetscSF sf)
208: {
209:   PetscErrorCode   ierr;
210:   PetscSF_Neighbor *dat;

213:   sf->ops->CreateEmbeddedSF     = PetscSFCreateEmbeddedSF_Basic;
214:   sf->ops->CreateEmbeddedLeafSF = PetscSFCreateEmbeddedLeafSF_Basic;
215:   sf->ops->BcastAndOpEnd        = PetscSFBcastAndOpEnd_Basic;
216:   sf->ops->ReduceEnd            = PetscSFReduceEnd_Basic;
217:   sf->ops->FetchAndOpBegin      = PetscSFFetchAndOpBegin_Basic;
218:   sf->ops->GetLeafRanks         = PetscSFGetLeafRanks_Basic;
219:   sf->ops->View                 = PetscSFView_Basic;
220:   sf->ops->SetFromOptions       = PetscSFSetFromOptions_Basic;

222:   sf->ops->SetUp                = PetscSFSetUp_Neighbor;
223:   sf->ops->Reset                = PetscSFReset_Neighbor;
224:   sf->ops->Destroy              = PetscSFDestroy_Neighbor;
225:   sf->ops->BcastAndOpBegin      = PetscSFBcastAndOpBegin_Neighbor;
226:   sf->ops->ReduceBegin          = PetscSFReduceBegin_Neighbor;
227:   sf->ops->FetchAndOpEnd        = PetscSFFetchAndOpEnd_Neighbor;

229:   PetscNewLog(sf,&dat);
230:   sf->data = (void*)dat;
231:   return(0);
232: }
233: #endif