Actual source code: sfneighbor.c
petsc-3.12.5 2020-03-29
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