18cd53115SBarry Smith 240e23c03SJunchao Zhang #include <../src/vec/is/sf/impls/basic/sfbasic.h> 395fce210SBarry Smith 440e23c03SJunchao Zhang /*===================================================================================*/ 5eb02082bSJunchao Zhang /* Internal routines for PetscSFPack */ 640e23c03SJunchao Zhang /*===================================================================================*/ 795fce210SBarry Smith 840e23c03SJunchao Zhang /* Return root and leaf MPI requests for communication in the given direction. If the requests have not been 940e23c03SJunchao Zhang initialized (since we use persistent requests), then initialize them. 1095fce210SBarry Smith */ 11eb02082bSJunchao Zhang static PetscErrorCode PetscSFPackGetReqs_Basic(PetscSF sf,PetscSFPack link,PetscSFDirection direction,MPI_Request **rootreqs,MPI_Request **leafreqs) 1240e23c03SJunchao Zhang { 13b23bfdefSJunchao Zhang PetscErrorCode ierr; 1440e23c03SJunchao Zhang PetscSF_Basic *bas = (PetscSF_Basic*)sf->data; 15b23bfdefSJunchao Zhang PetscInt i,j,nrootranks,ndrootranks,nleafranks,ndleafranks,disp; 1640e23c03SJunchao Zhang const PetscInt *rootoffset,*leafoffset; 1740e23c03SJunchao Zhang PetscMPIInt n; 1840e23c03SJunchao Zhang MPI_Comm comm = PetscObjectComm((PetscObject)sf); 19eb02082bSJunchao Zhang MPI_Datatype unit = link->unit; 20120a1823SJunchao Zhang PetscMemType rootmtype,leafmtype; 2195fce210SBarry Smith 2240e23c03SJunchao Zhang PetscFunctionBegin; 23120a1823SJunchao Zhang if (use_gpu_aware_mpi) { 24120a1823SJunchao Zhang rootmtype = link->rootmtype; 25120a1823SJunchao Zhang leafmtype = link->leafmtype; 26120a1823SJunchao Zhang } else { 27120a1823SJunchao Zhang rootmtype = PETSC_MEMTYPE_HOST; 28120a1823SJunchao Zhang leafmtype = PETSC_MEMTYPE_HOST; 29120a1823SJunchao Zhang } 30120a1823SJunchao Zhang 31eb02082bSJunchao Zhang if (rootreqs && !link->rootreqsinited[direction][rootmtype]) { 3240e23c03SJunchao Zhang ierr = PetscSFGetRootInfo_Basic(sf,&nrootranks,&ndrootranks,NULL,&rootoffset,NULL);CHKERRQ(ierr); 3340e23c03SJunchao Zhang if (direction == PETSCSF_LEAF2ROOT_REDUCE) { 34eb02082bSJunchao Zhang for (i=ndrootranks,j=0; i<nrootranks; i++,j++) { 35b23bfdefSJunchao Zhang disp = (rootoffset[i] - rootoffset[ndrootranks])*link->unitbytes; 3640e23c03SJunchao Zhang ierr = PetscMPIIntCast(rootoffset[i+1]-rootoffset[i],&n);CHKERRQ(ierr); 37eb02082bSJunchao Zhang ierr = MPI_Recv_init(link->rootbuf[rootmtype]+disp,n,unit,bas->iranks[i],link->tag,comm,&link->rootreqs[direction][rootmtype][j]);CHKERRQ(ierr); 3840e23c03SJunchao Zhang } 3940e23c03SJunchao Zhang } else if (direction == PETSCSF_ROOT2LEAF_BCAST) { 40eb02082bSJunchao Zhang for (i=ndrootranks,j=0; i<nrootranks; i++,j++) { 41b23bfdefSJunchao Zhang disp = (rootoffset[i] - rootoffset[ndrootranks])*link->unitbytes; 4240e23c03SJunchao Zhang ierr = PetscMPIIntCast(rootoffset[i+1]-rootoffset[i],&n);CHKERRQ(ierr); 43eb02082bSJunchao Zhang ierr = MPI_Send_init(link->rootbuf[rootmtype]+disp,n,unit,bas->iranks[i],link->tag,comm,&link->rootreqs[direction][rootmtype][j]);CHKERRQ(ierr); 4440e23c03SJunchao Zhang } 45eb02082bSJunchao Zhang } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Out-of-range PetscSFDirection = %d\n",(int)direction); 46eb02082bSJunchao Zhang link->rootreqsinited[direction][rootmtype] = PETSC_TRUE; 47eb02082bSJunchao Zhang } 48eb02082bSJunchao Zhang 49eb02082bSJunchao Zhang if (leafreqs && !link->leafreqsinited[direction][leafmtype]) { 50eb02082bSJunchao Zhang ierr = PetscSFGetLeafInfo_Basic(sf,&nleafranks,&ndleafranks,NULL,&leafoffset,NULL,NULL);CHKERRQ(ierr); 51eb02082bSJunchao Zhang if (direction == PETSCSF_LEAF2ROOT_REDUCE) { 52eb02082bSJunchao Zhang for (i=ndleafranks,j=0; i<nleafranks; i++,j++) { 53b23bfdefSJunchao Zhang disp = (leafoffset[i] - leafoffset[ndleafranks])*link->unitbytes; 5440e23c03SJunchao Zhang ierr = PetscMPIIntCast(leafoffset[i+1]-leafoffset[i],&n);CHKERRQ(ierr); 55eb02082bSJunchao Zhang ierr = MPI_Send_init(link->leafbuf[leafmtype]+disp,n,unit,sf->ranks[i],link->tag,comm,&link->leafreqs[direction][leafmtype][j]);CHKERRQ(ierr); 5640e23c03SJunchao Zhang } 57eb02082bSJunchao Zhang } else if (direction == PETSCSF_ROOT2LEAF_BCAST) { 58eb02082bSJunchao Zhang for (i=ndleafranks,j=0; i<nleafranks; i++,j++) { 59eb02082bSJunchao Zhang disp = (leafoffset[i] - leafoffset[ndleafranks])*link->unitbytes; 60eb02082bSJunchao Zhang ierr = PetscMPIIntCast(leafoffset[i+1]-leafoffset[i],&n);CHKERRQ(ierr); 61eb02082bSJunchao Zhang ierr = MPI_Recv_init(link->leafbuf[leafmtype]+disp,n,unit,sf->ranks[i],link->tag,comm,&link->leafreqs[direction][leafmtype][j]);CHKERRQ(ierr); 62eb02082bSJunchao Zhang } 63eb02082bSJunchao Zhang } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Out-of-range PetscSFDirection = %d\n",(int)direction); 64eb02082bSJunchao Zhang link->leafreqsinited[direction][leafmtype] = PETSC_TRUE; 6595fce210SBarry Smith } 6695fce210SBarry Smith 67eb02082bSJunchao Zhang if (rootreqs) *rootreqs = link->rootreqs[direction][rootmtype]; 68eb02082bSJunchao Zhang if (leafreqs) *leafreqs = link->leafreqs[direction][leafmtype]; 6940e23c03SJunchao Zhang PetscFunctionReturn(0); 7095fce210SBarry Smith } 7195fce210SBarry Smith 72b23bfdefSJunchao Zhang /* Common part shared by SFBasic and SFNeighbor based on the fact they all deal with sparse graphs. */ 73eb02082bSJunchao Zhang PETSC_INTERN PetscErrorCode PetscSFPackGet_Basic_Common(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,const void *rootdata,PetscMemType leafmtype,const void *leafdata,PetscInt nrootreqs,PetscInt nleafreqs,PetscSFPack *mylink) 7440e23c03SJunchao Zhang { 7540e23c03SJunchao Zhang PetscErrorCode ierr; 76b23bfdefSJunchao Zhang PetscSF_Basic *bas = (PetscSF_Basic*)sf->data; 77eb02082bSJunchao Zhang PetscInt i,j,nreqs,nrootranks,ndrootranks,nleafranks,ndleafranks; 7840e23c03SJunchao Zhang const PetscInt *rootoffset,*leafoffset; 79eb02082bSJunchao Zhang PetscSFPack *p,link; 80b23bfdefSJunchao Zhang PetscBool match; 8140e23c03SJunchao Zhang 8240e23c03SJunchao Zhang PetscFunctionBegin; 83b23bfdefSJunchao Zhang ierr = PetscSFPackSetErrorOnUnsupportedOverlap(sf,unit,rootdata,leafdata);CHKERRQ(ierr); 849d1c8addSJunchao Zhang 8540e23c03SJunchao Zhang /* Look for types in cache */ 86eb02082bSJunchao Zhang for (p=&bas->avail; (link=*p); p=&link->next) { 8740e23c03SJunchao Zhang ierr = MPIPetsc_Type_compare(unit,link->unit,&match);CHKERRQ(ierr); 8840e23c03SJunchao Zhang if (match) { 8940e23c03SJunchao Zhang *p = link->next; /* Remove from available list */ 9040e23c03SJunchao Zhang goto found; 9140e23c03SJunchao Zhang } 9253deab39SPeter Brune } 9353deab39SPeter Brune 9440e23c03SJunchao Zhang ierr = PetscSFGetRootInfo_Basic(sf,&nrootranks,&ndrootranks,NULL,&rootoffset,NULL);CHKERRQ(ierr); 9540e23c03SJunchao Zhang ierr = PetscSFGetLeafInfo_Basic(sf,&nleafranks,&ndleafranks,NULL,&leafoffset,NULL,NULL);CHKERRQ(ierr); 9640e23c03SJunchao Zhang ierr = PetscNew(&link);CHKERRQ(ierr); 97eb02082bSJunchao Zhang ierr = PetscSFPackSetUp_Host(sf,link,unit);CHKERRQ(ierr); 98b23bfdefSJunchao Zhang ierr = PetscCommGetNewTag(PetscObjectComm((PetscObject)sf),&link->tag);CHKERRQ(ierr); /* One tag per link */ 9953deab39SPeter Brune 100eb02082bSJunchao Zhang /* Allocate root, leaf, self buffers, and MPI requests */ 101eb02082bSJunchao Zhang link->rootbuflen = rootoffset[nrootranks]-rootoffset[ndrootranks]; 102eb02082bSJunchao Zhang link->leafbuflen = leafoffset[nleafranks]-leafoffset[ndleafranks]; 103ca0da9f8SJunchao Zhang link->selfbuflen = rootoffset[ndrootranks]; 104eb02082bSJunchao Zhang link->nrootreqs = nrootreqs; 105eb02082bSJunchao Zhang link->nleafreqs = nleafreqs; 106eb02082bSJunchao Zhang nreqs = (nrootreqs+nleafreqs)*4; /* Quadruple the requests since there are two communication directions and two memory types */ 107eb02082bSJunchao Zhang ierr = PetscMalloc1(nreqs,&link->reqs);CHKERRQ(ierr); 108eb02082bSJunchao Zhang for (i=0; i<nreqs; i++) link->reqs[i] = MPI_REQUEST_NULL; /* Initialized to NULL so that we know which need to be freed in Destroy */ 109eb02082bSJunchao Zhang 110eb02082bSJunchao Zhang for (i=0; i<2; i++) { /* Two communication directions */ 111eb02082bSJunchao Zhang for (j=0; j<2; j++) { /* Two memory types */ 112eb02082bSJunchao Zhang link->rootreqs[i][j] = link->reqs + nrootreqs*(2*i+j); 113eb02082bSJunchao Zhang link->leafreqs[i][j] = link->reqs + nrootreqs*4 + nleafreqs*(2*i+j); 114eb02082bSJunchao Zhang } 115eb02082bSJunchao Zhang } 11653deab39SPeter Brune 11740e23c03SJunchao Zhang found: 118eb02082bSJunchao Zhang link->rootmtype = rootmtype; 119eb02082bSJunchao Zhang link->leafmtype = leafmtype; 120eb02082bSJunchao Zhang #if defined(PETSC_HAVE_CUDA) 121120a1823SJunchao Zhang ierr = PetscSFPackSetUp_Device(sf,link,unit);CHKERRQ(ierr); 122120a1823SJunchao Zhang if (!use_gpu_aware_mpi) { 123120a1823SJunchao Zhang /* If not using GPU aware MPI, we always need buffers on host. In case root/leafdata is on device, we copy root/leafdata to/from 124120a1823SJunchao Zhang these buffers for MPI. We only need buffers for remote neighbors since self-to-self communication is not done via MPI. 125120a1823SJunchao Zhang */ 126120a1823SJunchao Zhang if (!link->rootbuf[PETSC_MEMTYPE_HOST]) {ierr = PetscMallocWithMemType(PETSC_MEMTYPE_HOST,link->rootbuflen*link->unitbytes,(void**)&link->rootbuf[PETSC_MEMTYPE_HOST]);CHKERRQ(ierr);} 127120a1823SJunchao Zhang if (!link->leafbuf[PETSC_MEMTYPE_HOST]) {ierr = PetscMallocWithMemType(PETSC_MEMTYPE_HOST,link->leafbuflen*link->unitbytes,(void**)&link->leafbuf[PETSC_MEMTYPE_HOST]);CHKERRQ(ierr);} 128120a1823SJunchao Zhang } 129eb02082bSJunchao Zhang #endif 130eb02082bSJunchao Zhang if (!link->rootbuf[rootmtype]) {ierr = PetscMallocWithMemType(rootmtype,link->rootbuflen*link->unitbytes,(void**)&link->rootbuf[rootmtype]);CHKERRQ(ierr);} 131eb02082bSJunchao Zhang if (!link->leafbuf[leafmtype]) {ierr = PetscMallocWithMemType(leafmtype,link->leafbuflen*link->unitbytes,(void**)&link->leafbuf[leafmtype]);CHKERRQ(ierr);} 132eb02082bSJunchao Zhang if (!link->selfbuf[rootmtype]) {ierr = PetscMallocWithMemType(rootmtype,link->selfbuflen*link->unitbytes,(void**)&link->selfbuf[rootmtype]);CHKERRQ(ierr);} 133eb02082bSJunchao Zhang if (rootmtype != leafmtype && !link->selfbuf[leafmtype]) {ierr = PetscMallocWithMemType(leafmtype,link->selfbuflen*link->unitbytes,(void**)&link->selfbuf[leafmtype]);CHKERRQ(ierr);} 134*637e6665SJunchao Zhang link->rootdata = rootdata; 135*637e6665SJunchao Zhang link->leafdata = leafdata; 13640e23c03SJunchao Zhang link->next = bas->inuse; 137eb02082bSJunchao Zhang bas->inuse = link; 13840e23c03SJunchao Zhang *mylink = link; 13940e23c03SJunchao Zhang PetscFunctionReturn(0); 14095fce210SBarry Smith } 14195fce210SBarry Smith 142eb02082bSJunchao Zhang static PetscErrorCode PetscSFPackGet_Basic(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,const void *rootdata,PetscMemType leafmtype,const void *leafdata,PetscSFDirection direction,PetscSFPack *mylink) 143b23bfdefSJunchao Zhang { 144b23bfdefSJunchao Zhang PetscErrorCode ierr; 145eb02082bSJunchao Zhang PetscInt nrootranks,ndrootranks,nleafranks,ndleafranks; 146b23bfdefSJunchao Zhang 147b23bfdefSJunchao Zhang PetscFunctionBegin; 148b23bfdefSJunchao Zhang ierr = PetscSFGetRootInfo_Basic(sf,&nrootranks,&ndrootranks,NULL,NULL,NULL);CHKERRQ(ierr); 149b23bfdefSJunchao Zhang ierr = PetscSFGetLeafInfo_Basic(sf,&nleafranks,&ndleafranks,NULL,NULL,NULL,NULL);CHKERRQ(ierr); 150eb02082bSJunchao Zhang ierr = PetscSFPackGet_Basic_Common(sf,unit,rootmtype,rootdata,leafmtype,leafdata,nrootranks-ndrootranks,nleafranks-ndleafranks,mylink);CHKERRQ(ierr); 151b23bfdefSJunchao Zhang PetscFunctionReturn(0); 152b23bfdefSJunchao Zhang } 153b23bfdefSJunchao Zhang 15440e23c03SJunchao Zhang /*===================================================================================*/ 15540e23c03SJunchao Zhang /* SF public interface implementations */ 15640e23c03SJunchao Zhang /*===================================================================================*/ 15740e23c03SJunchao Zhang PETSC_INTERN PetscErrorCode PetscSFSetUp_Basic(PetscSF sf) 15895fce210SBarry Smith { 15995fce210SBarry Smith PetscErrorCode ierr; 160b23bfdefSJunchao Zhang PetscSF_Basic *bas = (PetscSF_Basic*)sf->data; 16195fce210SBarry Smith PetscInt *rlengths,*ilengths,i; 16240e23c03SJunchao Zhang PetscMPIInt rank,niranks,*iranks,tag; 16395fce210SBarry Smith MPI_Comm comm; 164b5a8e515SJed Brown MPI_Group group; 16540e23c03SJunchao Zhang MPI_Request *rootreqs,*leafreqs; 16695fce210SBarry Smith 16795fce210SBarry Smith PetscFunctionBegin; 168b5a8e515SJed Brown ierr = MPI_Comm_group(PETSC_COMM_SELF,&group);CHKERRQ(ierr); 169b5a8e515SJed Brown ierr = PetscSFSetUpRanks(sf,group);CHKERRQ(ierr); 170b5a8e515SJed Brown ierr = MPI_Group_free(&group);CHKERRQ(ierr); 17195fce210SBarry Smith ierr = PetscObjectGetComm((PetscObject)sf,&comm);CHKERRQ(ierr); 17240e23c03SJunchao Zhang ierr = PetscObjectGetNewTag((PetscObject)sf,&tag);CHKERRQ(ierr); 173c943f53fSJed Brown ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 17495fce210SBarry Smith /* 17595fce210SBarry Smith * Inform roots about how many leaves and from which ranks 17695fce210SBarry Smith */ 177785e854fSJed Brown ierr = PetscMalloc1(sf->nranks,&rlengths);CHKERRQ(ierr); 17895fce210SBarry Smith /* Determine number, sending ranks, and length of incoming */ 17995fce210SBarry Smith for (i=0; i<sf->nranks; i++) { 18095fce210SBarry Smith rlengths[i] = sf->roffset[i+1] - sf->roffset[i]; /* Number of roots referenced by my leaves; for rank sf->ranks[i] */ 18195fce210SBarry Smith } 18240e23c03SJunchao Zhang ierr = PetscCommBuildTwoSided(comm,1,MPIU_INT,sf->nranks-sf->ndranks,sf->ranks+sf->ndranks,rlengths+sf->ndranks,&niranks,&iranks,(void**)&ilengths);CHKERRQ(ierr); 183c943f53fSJed Brown 1840b899082SJunchao Zhang /* Sort iranks. See use of VecScatterGetRemoteOrdered_Private() in MatGetBrowsOfAoCols_MPIAIJ() on why. 1850b899082SJunchao Zhang We could sort ranks there at the price of allocating extra working arrays. Presumably, niranks is 1860b899082SJunchao Zhang small and the sorting is cheap. 1870b899082SJunchao Zhang */ 1880b899082SJunchao Zhang ierr = PetscSortMPIIntWithIntArray(niranks,iranks,ilengths);CHKERRQ(ierr); 1890b899082SJunchao Zhang 190c943f53fSJed Brown /* Partition into distinguished and non-distinguished incoming ranks */ 191c943f53fSJed Brown bas->ndiranks = sf->ndranks; 192c943f53fSJed Brown bas->niranks = bas->ndiranks + niranks; 193c943f53fSJed Brown ierr = PetscMalloc2(bas->niranks,&bas->iranks,bas->niranks+1,&bas->ioffset);CHKERRQ(ierr); 194c943f53fSJed Brown bas->ioffset[0] = 0; 195c943f53fSJed Brown for (i=0; i<bas->ndiranks; i++) { 196c943f53fSJed Brown bas->iranks[i] = sf->ranks[i]; 197c943f53fSJed Brown bas->ioffset[i+1] = bas->ioffset[i] + rlengths[i]; 198c943f53fSJed Brown } 19940e23c03SJunchao Zhang if (bas->ndiranks > 1 || (bas->ndiranks == 1 && bas->iranks[0] != rank)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Broken setup for shared ranks"); 20040e23c03SJunchao Zhang for ( ; i<bas->niranks; i++) { 201c943f53fSJed Brown bas->iranks[i] = iranks[i-bas->ndiranks]; 202c943f53fSJed Brown bas->ioffset[i+1] = bas->ioffset[i] + ilengths[i-bas->ndiranks]; 203c943f53fSJed Brown } 204c943f53fSJed Brown bas->itotal = bas->ioffset[i]; 20595fce210SBarry Smith ierr = PetscFree(rlengths);CHKERRQ(ierr); 206c943f53fSJed Brown ierr = PetscFree(iranks);CHKERRQ(ierr); 207c943f53fSJed Brown ierr = PetscFree(ilengths);CHKERRQ(ierr); 20895fce210SBarry Smith 20995fce210SBarry Smith /* Send leaf identities to roots */ 210c943f53fSJed Brown ierr = PetscMalloc1(bas->itotal,&bas->irootloc);CHKERRQ(ierr); 21140e23c03SJunchao Zhang ierr = PetscMalloc2(bas->niranks-bas->ndiranks,&rootreqs,sf->nranks-sf->ndranks,&leafreqs);CHKERRQ(ierr); 21240e23c03SJunchao Zhang for (i=bas->ndiranks; i<bas->niranks; i++) { 21340e23c03SJunchao Zhang ierr = MPI_Irecv(bas->irootloc+bas->ioffset[i],bas->ioffset[i+1]-bas->ioffset[i],MPIU_INT,bas->iranks[i],tag,comm,&rootreqs[i-bas->ndiranks]);CHKERRQ(ierr); 21440e23c03SJunchao Zhang } 21540e23c03SJunchao Zhang for (i=0; i<sf->nranks; i++) { 21695fce210SBarry Smith PetscMPIInt npoints; 21795fce210SBarry Smith ierr = PetscMPIIntCast(sf->roffset[i+1] - sf->roffset[i],&npoints);CHKERRQ(ierr); 21840e23c03SJunchao Zhang if (i < sf->ndranks) { 21940e23c03SJunchao Zhang if (sf->ranks[i] != rank) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot interpret distinguished leaf rank"); 22040e23c03SJunchao Zhang if (bas->iranks[0] != rank) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot interpret distinguished root rank"); 22140e23c03SJunchao Zhang if (npoints != bas->ioffset[1]-bas->ioffset[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Distinguished rank exchange has mismatched lengths"); 22240e23c03SJunchao Zhang ierr = PetscArraycpy(bas->irootloc+bas->ioffset[0],sf->rremote+sf->roffset[i],npoints);CHKERRQ(ierr); 223c943f53fSJed Brown continue; 224c943f53fSJed Brown } 22540e23c03SJunchao Zhang ierr = MPI_Isend(sf->rremote+sf->roffset[i],npoints,MPIU_INT,sf->ranks[i],tag,comm,&leafreqs[i-sf->ndranks]);CHKERRQ(ierr); 226bf39f1bfSJed Brown } 22740e23c03SJunchao Zhang ierr = MPI_Waitall(bas->niranks-bas->ndiranks,rootreqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr); 22840e23c03SJunchao Zhang ierr = MPI_Waitall(sf->nranks-sf->ndranks,leafreqs,MPI_STATUSES_IGNORE);CHKERRQ(ierr); 22940e23c03SJunchao Zhang ierr = PetscFree2(rootreqs,leafreqs);CHKERRQ(ierr); 23095fce210SBarry Smith 231eb02082bSJunchao Zhang sf->selfleafdups = PETSC_TRUE; /* The conservative assumption is there are data race */ 232eb02082bSJunchao Zhang sf->remoteleafdups = PETSC_TRUE; 233eb02082bSJunchao Zhang bas->selfrootdups = PETSC_TRUE; 234eb02082bSJunchao Zhang bas->remoterootdups = PETSC_TRUE; 235eb02082bSJunchao Zhang 236b23bfdefSJunchao Zhang /* Setup packing optimization for roots and leaves */ 237eb02082bSJunchao Zhang ierr = PetscSFPackSetupOptimizations_Basic(sf);CHKERRQ(ierr); 23895fce210SBarry Smith PetscFunctionReturn(0); 23995fce210SBarry Smith } 24095fce210SBarry Smith 2414416b707SBarry Smith static PetscErrorCode PetscSFSetFromOptions_Basic(PetscOptionItems *PetscOptionsObject,PetscSF sf) 24295fce210SBarry Smith { 24395fce210SBarry Smith PetscErrorCode ierr; 24495fce210SBarry Smith 24595fce210SBarry Smith PetscFunctionBegin; 246e55864a3SBarry Smith ierr = PetscOptionsHead(PetscOptionsObject,"PetscSF Basic options");CHKERRQ(ierr); 24795fce210SBarry Smith ierr = PetscOptionsTail();CHKERRQ(ierr); 24895fce210SBarry Smith PetscFunctionReturn(0); 24995fce210SBarry Smith } 25095fce210SBarry Smith 25140e23c03SJunchao Zhang PETSC_INTERN PetscErrorCode PetscSFReset_Basic(PetscSF sf) 25295fce210SBarry Smith { 25395fce210SBarry Smith PetscSF_Basic *bas = (PetscSF_Basic*)sf->data; 25495fce210SBarry Smith PetscErrorCode ierr; 25595fce210SBarry Smith 25695fce210SBarry Smith PetscFunctionBegin; 25729046d53SLisandro Dalcin if (bas->inuse) SETERRQ(PetscObjectComm((PetscObject)sf),PETSC_ERR_ARG_WRONGSTATE,"Outstanding operation has not been completed"); 258c943f53fSJed Brown ierr = PetscFree2(bas->iranks,bas->ioffset);CHKERRQ(ierr); 259c943f53fSJed Brown ierr = PetscFree(bas->irootloc);CHKERRQ(ierr); 260eb02082bSJunchao Zhang #if defined(PETSC_HAVE_CUDA) 261eb02082bSJunchao Zhang if (bas->irootloc_d) {cudaError_t err = cudaFree(bas->irootloc_d);CHKERRCUDA(err);bas->irootloc_d=NULL;} 262eb02082bSJunchao Zhang #endif 26364f49babSJed Brown ierr = PetscSFPackDestroyAvailable(&bas->avail);CHKERRQ(ierr); 264eb02082bSJunchao Zhang ierr = PetscSFPackDestroyOptimizations_Basic(sf);CHKERRQ(ierr); 26595fce210SBarry Smith PetscFunctionReturn(0); 26695fce210SBarry Smith } 26795fce210SBarry Smith 26840e23c03SJunchao Zhang PETSC_INTERN PetscErrorCode PetscSFDestroy_Basic(PetscSF sf) 26995fce210SBarry Smith { 27095fce210SBarry Smith PetscErrorCode ierr; 27195fce210SBarry Smith 27295fce210SBarry Smith PetscFunctionBegin; 27340e23c03SJunchao Zhang ierr = PetscSFReset(sf);CHKERRQ(ierr); 27495fce210SBarry Smith ierr = PetscFree(sf->data);CHKERRQ(ierr); 27595fce210SBarry Smith PetscFunctionReturn(0); 27695fce210SBarry Smith } 27795fce210SBarry Smith 27840e23c03SJunchao Zhang PETSC_INTERN PetscErrorCode PetscSFView_Basic(PetscSF sf,PetscViewer viewer) 27995fce210SBarry Smith { 28095fce210SBarry Smith PetscErrorCode ierr; 28195fce210SBarry Smith PetscBool iascii; 28295fce210SBarry Smith 28395fce210SBarry Smith PetscFunctionBegin; 28495fce210SBarry Smith ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 285b23bfdefSJunchao Zhang if (iascii) {ierr = PetscViewerASCIIPrintf(viewer," sort=%s\n",sf->rankorder ? "rank-order" : "unordered");CHKERRQ(ierr);} 28695fce210SBarry Smith PetscFunctionReturn(0); 28795fce210SBarry Smith } 28895fce210SBarry Smith 289eb02082bSJunchao Zhang static PetscErrorCode PetscSFBcastAndOpBegin_Basic(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,const void *rootdata,PetscMemType leafmtype,void *leafdata,MPI_Op op) 29095fce210SBarry Smith { 29195fce210SBarry Smith PetscErrorCode ierr; 292eb02082bSJunchao Zhang PetscSFPack link; 293eb02082bSJunchao Zhang const PetscInt *rootloc = NULL; 29495fce210SBarry Smith MPI_Request *rootreqs,*leafreqs; 29595fce210SBarry Smith 29695fce210SBarry Smith PetscFunctionBegin; 297eb02082bSJunchao Zhang ierr = PetscSFPackGet_Basic(sf,unit,rootmtype,rootdata,leafmtype,leafdata,PETSCSF_ROOT2LEAF_BCAST,&link);CHKERRQ(ierr); 298eb02082bSJunchao Zhang ierr = PetscSFGetRootIndicesWithMemType_Basic(sf,rootmtype,&rootloc);CHKERRQ(ierr); 29995fce210SBarry Smith 300b23bfdefSJunchao Zhang ierr = PetscSFPackGetReqs_Basic(sf,link,PETSCSF_ROOT2LEAF_BCAST,&rootreqs,&leafreqs);CHKERRQ(ierr); 301b23bfdefSJunchao Zhang /* Post Irecv. Note distinguished ranks receive data via shared memory (i.e., not via MPI) */ 302eb02082bSJunchao Zhang ierr = MPI_Startall_irecv(link->leafbuflen,unit,link->nleafreqs,leafreqs);CHKERRQ(ierr); 30330e38525SJunchao Zhang 304b23bfdefSJunchao Zhang /* Do Isend */ 305eb02082bSJunchao Zhang ierr = PetscSFPackRootData(sf,link,rootloc,rootdata,PETSC_TRUE);CHKERRQ(ierr); 306eb02082bSJunchao Zhang ierr = MPI_Startall_isend(link->rootbuflen,unit,link->nrootreqs,rootreqs);CHKERRQ(ierr); 307eb02082bSJunchao Zhang 308eb02082bSJunchao Zhang /* Do self to self communication via memcpy only when rootdata and leafdata are in different memory */ 309eb02082bSJunchao Zhang if (rootmtype != leafmtype) {ierr = PetscMemcpyWithMemType(leafmtype,rootmtype,link->selfbuf[leafmtype],link->selfbuf[rootmtype],link->selfbuflen*link->unitbytes);CHKERRQ(ierr);} 31095fce210SBarry Smith PetscFunctionReturn(0); 31195fce210SBarry Smith } 31295fce210SBarry Smith 313eb02082bSJunchao Zhang PETSC_INTERN PetscErrorCode PetscSFBcastAndOpEnd_Basic(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,const void *rootdata,PetscMemType leafmtype,void *leafdata,MPI_Op op) 31495fce210SBarry Smith { 31595fce210SBarry Smith PetscErrorCode ierr; 316eb02082bSJunchao Zhang PetscSFPack link; 317eb02082bSJunchao Zhang const PetscInt *leafloc = NULL; 31895fce210SBarry Smith 31995fce210SBarry Smith PetscFunctionBegin; 320eb02082bSJunchao Zhang ierr = PetscSFPackGetInUse(sf,unit,rootdata,leafdata,PETSC_OWN_POINTER,&link);CHKERRQ(ierr); 321b7c0d12aSJunchao Zhang ierr = PetscSFPackWaitall(link,PETSCSF_ROOT2LEAF_BCAST);CHKERRQ(ierr); 322eb02082bSJunchao Zhang ierr = PetscSFGetLeafIndicesWithMemType_Basic(sf,leafmtype,&leafloc);CHKERRQ(ierr); 323eb02082bSJunchao Zhang ierr = PetscSFUnpackAndOpLeafData(sf,link,leafloc,leafdata,op,PETSC_TRUE);CHKERRQ(ierr); 324eb02082bSJunchao Zhang ierr = PetscSFPackReclaim(sf,&link);CHKERRQ(ierr); 32595fce210SBarry Smith PetscFunctionReturn(0); 32695fce210SBarry Smith } 32795fce210SBarry Smith 32895fce210SBarry Smith /* leaf -> root with reduction */ 329eb02082bSJunchao Zhang static PetscErrorCode PetscSFReduceBegin_Basic(PetscSF sf,MPI_Datatype unit,PetscMemType leafmtype,const void *leafdata,PetscMemType rootmtype,void *rootdata,MPI_Op op) 33095fce210SBarry Smith { 33195fce210SBarry Smith PetscErrorCode ierr; 332eb02082bSJunchao Zhang PetscSFPack link; 333eb02082bSJunchao Zhang const PetscInt *leafloc = NULL; 334277f51e8SBarry Smith MPI_Request *rootreqs = NULL,*leafreqs = NULL; /* dummy values for compiler warnings about uninitialized value */ 33595fce210SBarry Smith 33695fce210SBarry Smith PetscFunctionBegin; 337eb02082bSJunchao Zhang ierr = PetscSFGetLeafIndicesWithMemType_Basic(sf,leafmtype,&leafloc); 33895fce210SBarry Smith 339eb02082bSJunchao Zhang ierr = PetscSFPackGet_Basic(sf,unit,rootmtype,rootdata,leafmtype,leafdata,PETSCSF_LEAF2ROOT_REDUCE,&link);CHKERRQ(ierr); 340b23bfdefSJunchao Zhang ierr = PetscSFPackGetReqs_Basic(sf,link,PETSCSF_LEAF2ROOT_REDUCE,&rootreqs,&leafreqs);CHKERRQ(ierr); 341c943f53fSJed Brown /* Eagerly post root receives for non-distinguished ranks */ 342eb02082bSJunchao Zhang ierr = MPI_Startall_irecv(link->rootbuflen,unit,link->nrootreqs,rootreqs);CHKERRQ(ierr); 34330e38525SJunchao Zhang 34495fce210SBarry Smith /* Pack and send leaf data */ 345eb02082bSJunchao Zhang ierr = PetscSFPackLeafData(sf,link,leafloc,leafdata,PETSC_TRUE);CHKERRQ(ierr); 346eb02082bSJunchao Zhang ierr = MPI_Startall_isend(link->leafbuflen,unit,link->nleafreqs,leafreqs);CHKERRQ(ierr); 347eb02082bSJunchao Zhang 348eb02082bSJunchao Zhang if (rootmtype != leafmtype) {ierr = PetscMemcpyWithMemType(rootmtype,leafmtype,link->selfbuf[rootmtype],link->selfbuf[leafmtype],link->selfbuflen*link->unitbytes);CHKERRQ(ierr);} 34995fce210SBarry Smith PetscFunctionReturn(0); 35095fce210SBarry Smith } 35195fce210SBarry Smith 352eb02082bSJunchao Zhang PETSC_INTERN PetscErrorCode PetscSFReduceEnd_Basic(PetscSF sf,MPI_Datatype unit,PetscMemType leafmtype,const void *leafdata,PetscMemType rootmtype,void *rootdata,MPI_Op op) 35395fce210SBarry Smith { 35495fce210SBarry Smith PetscErrorCode ierr; 355eb02082bSJunchao Zhang PetscSFPack link; 356eb02082bSJunchao Zhang const PetscInt *rootloc = NULL; 35795fce210SBarry Smith 35895fce210SBarry Smith PetscFunctionBegin; 359eb02082bSJunchao Zhang ierr = PetscSFGetRootIndicesWithMemType_Basic(sf,rootmtype,&rootloc);CHKERRQ(ierr); 360eb02082bSJunchao Zhang ierr = PetscSFPackGetInUse(sf,unit,rootdata,leafdata,PETSC_OWN_POINTER,&link);CHKERRQ(ierr); 361b7c0d12aSJunchao Zhang ierr = PetscSFPackWaitall(link,PETSCSF_LEAF2ROOT_REDUCE);CHKERRQ(ierr); 362eb02082bSJunchao Zhang ierr = PetscSFUnpackAndOpRootData(sf,link,rootloc,rootdata,op,PETSC_TRUE);CHKERRQ(ierr); 363eb02082bSJunchao Zhang ierr = PetscSFPackReclaim(sf,&link);CHKERRQ(ierr); 36495fce210SBarry Smith PetscFunctionReturn(0); 36595fce210SBarry Smith } 36695fce210SBarry Smith 367eb02082bSJunchao Zhang PETSC_INTERN PetscErrorCode PetscSFFetchAndOpBegin_Basic(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,void *rootdata,PetscMemType leafmtype,const void *leafdata,void *leafupdate,MPI_Op op) 36895fce210SBarry Smith { 36995fce210SBarry Smith PetscErrorCode ierr; 37095fce210SBarry Smith 37195fce210SBarry Smith PetscFunctionBegin; 37240e23c03SJunchao Zhang ierr = PetscSFReduceBegin(sf,unit,leafdata,rootdata,op);CHKERRQ(ierr); 37395fce210SBarry Smith PetscFunctionReturn(0); 37495fce210SBarry Smith } 37595fce210SBarry Smith 376eb02082bSJunchao Zhang static PetscErrorCode PetscSFFetchAndOpEnd_Basic(PetscSF sf,MPI_Datatype unit,PetscMemType rootmtype,void *rootdata,PetscMemType leafmtype,const void *leafdata,void *leafupdate,MPI_Op op) 37795fce210SBarry Smith { 37895fce210SBarry Smith PetscErrorCode ierr; 379eb02082bSJunchao Zhang PetscSFPack link; 380eb02082bSJunchao Zhang const PetscInt *rootloc = NULL,*leafloc = NULL; 38195fce210SBarry Smith MPI_Request *rootreqs,*leafreqs; 38295fce210SBarry Smith 38395fce210SBarry Smith PetscFunctionBegin; 384eb02082bSJunchao Zhang ierr = PetscSFGetRootIndicesWithMemType_Basic(sf,rootmtype,&rootloc);CHKERRQ(ierr); 385eb02082bSJunchao Zhang ierr = PetscSFGetLeafIndicesWithMemType_Basic(sf,leafmtype,&leafloc);CHKERRQ(ierr); 386eb02082bSJunchao Zhang ierr = PetscSFPackGetInUse(sf,unit,rootdata,leafdata,PETSC_OWN_POINTER,&link);CHKERRQ(ierr); 38795fce210SBarry Smith /* This implementation could be changed to unpack as receives arrive, at the cost of non-determinism */ 388b7c0d12aSJunchao Zhang ierr = PetscSFPackWaitall(link,PETSCSF_LEAF2ROOT_REDUCE);CHKERRQ(ierr); 389b23bfdefSJunchao Zhang ierr = PetscSFPackGetReqs_Basic(sf,link,PETSCSF_ROOT2LEAF_BCAST,&rootreqs,&leafreqs);CHKERRQ(ierr); 39040e23c03SJunchao Zhang 39195fce210SBarry Smith /* Post leaf receives */ 392eb02082bSJunchao Zhang ierr = MPI_Startall_irecv(link->leafbuflen,unit,link->nleafreqs,leafreqs);CHKERRQ(ierr); 39330e38525SJunchao Zhang 39495fce210SBarry Smith /* Process local fetch-and-op, post root sends */ 395eb02082bSJunchao Zhang ierr = PetscSFFetchAndOpRootData(sf,link,rootloc,rootdata,op,PETSC_TRUE);CHKERRQ(ierr); 396eb02082bSJunchao Zhang ierr = MPI_Startall_isend(link->rootbuflen,unit,link->nrootreqs,rootreqs);CHKERRQ(ierr); 397eb02082bSJunchao Zhang if (rootmtype != leafmtype) {ierr = PetscMemcpyWithMemType(leafmtype,rootmtype,link->selfbuf[leafmtype],link->selfbuf[rootmtype],link->selfbuflen*link->unitbytes);CHKERRQ(ierr);} 398b23bfdefSJunchao Zhang 399b23bfdefSJunchao Zhang /* Unpack and insert fetched data into leaves */ 400b7c0d12aSJunchao Zhang ierr = PetscSFPackWaitall(link,PETSCSF_ROOT2LEAF_BCAST);CHKERRQ(ierr); 401eb02082bSJunchao Zhang ierr = PetscSFUnpackAndOpLeafData(sf,link,leafloc,leafupdate,MPIU_REPLACE,PETSC_TRUE);CHKERRQ(ierr); 402eb02082bSJunchao Zhang ierr = PetscSFPackReclaim(sf,&link);CHKERRQ(ierr); 40395fce210SBarry Smith PetscFunctionReturn(0); 40495fce210SBarry Smith } 40595fce210SBarry Smith 40640e23c03SJunchao Zhang PETSC_INTERN PetscErrorCode PetscSFGetLeafRanks_Basic(PetscSF sf,PetscInt *niranks,const PetscMPIInt **iranks,const PetscInt **ioffset,const PetscInt **irootloc) 4078750ddebSJunchao Zhang { 4088750ddebSJunchao Zhang PetscSF_Basic *bas = (PetscSF_Basic*)sf->data; 4098750ddebSJunchao Zhang 4108750ddebSJunchao Zhang PetscFunctionBegin; 4118750ddebSJunchao Zhang if (niranks) *niranks = bas->niranks; 4128750ddebSJunchao Zhang if (iranks) *iranks = bas->iranks; 4138750ddebSJunchao Zhang if (ioffset) *ioffset = bas->ioffset; 4148750ddebSJunchao Zhang if (irootloc) *irootloc = bas->irootloc; 4158750ddebSJunchao Zhang PetscFunctionReturn(0); 4168750ddebSJunchao Zhang } 4178750ddebSJunchao Zhang 418f659e5c7SJunchao Zhang /* An optimized PetscSFCreateEmbeddedSF. We aggresively make use of the established communication on sf. 419f659e5c7SJunchao Zhang We need one bcast on sf, and no communication anymore to build the embedded sf. Note that selected[] 420f659e5c7SJunchao Zhang was sorted before calling the routine. 421f659e5c7SJunchao Zhang */ 422f659e5c7SJunchao Zhang PETSC_INTERN PetscErrorCode PetscSFCreateEmbeddedSF_Basic(PetscSF sf,PetscInt nselected,const PetscInt *selected,PetscSF *newsf) 423f659e5c7SJunchao Zhang { 424f659e5c7SJunchao Zhang PetscSF esf; 425b23bfdefSJunchao Zhang PetscInt esf_nranks,esf_ndranks,*esf_roffset,*esf_rmine,*esf_rremote,count; 426b23bfdefSJunchao Zhang PetscInt i,j,k,p,q,nroots,*rootdata,*leafdata,connected_leaves,*new_ilocal,nranks,ndranks,niranks,ndiranks,minleaf,maxleaf,maxlocal; 427f659e5c7SJunchao Zhang PetscMPIInt *esf_ranks; 428f659e5c7SJunchao Zhang const PetscMPIInt *ranks,*iranks; 429b23bfdefSJunchao Zhang const PetscInt *roffset,*rmine,*rremote,*ioffset,*irootloc,*buffer; 430f659e5c7SJunchao Zhang PetscBool connected; 431eb02082bSJunchao Zhang PetscSFPack link; 432f659e5c7SJunchao Zhang PetscSFNode *new_iremote; 433f659e5c7SJunchao Zhang PetscSF_Basic *bas; 434f659e5c7SJunchao Zhang PetscErrorCode ierr; 435f659e5c7SJunchao Zhang 436f659e5c7SJunchao Zhang PetscFunctionBegin; 437f659e5c7SJunchao Zhang ierr = PetscSFCreate(PetscObjectComm((PetscObject)sf),&esf);CHKERRQ(ierr); 438f659e5c7SJunchao Zhang ierr = PetscSFSetType(esf,PETSCSFBASIC);CHKERRQ(ierr); /* This optimized routine can only create a basic sf */ 439f659e5c7SJunchao Zhang 440f659e5c7SJunchao Zhang /* Find out which leaves are still connected to roots in the embedded sf */ 441f659e5c7SJunchao Zhang ierr = PetscSFGetGraph(sf,&nroots,NULL,NULL,NULL);CHKERRQ(ierr); 442f659e5c7SJunchao Zhang ierr = PetscSFGetLeafRange(sf,&minleaf,&maxleaf);CHKERRQ(ierr); 443f659e5c7SJunchao Zhang /* We abused the term leafdata here, whose size is usually the number of leaf data items. Here its size is # of leaves (always >= # of leaf data items) */ 444f659e5c7SJunchao Zhang maxlocal = (minleaf > maxleaf)? 0 : maxleaf-minleaf+1; /* maxleaf=-1 and minleaf=0 when nleaves=0 */ 445f659e5c7SJunchao Zhang ierr = PetscCalloc2(nroots,&rootdata,maxlocal,&leafdata);CHKERRQ(ierr); 446f659e5c7SJunchao Zhang /* Tag selected roots */ 447f659e5c7SJunchao Zhang for (i=0; i<nselected; ++i) rootdata[selected[i]] = 1; 448f659e5c7SJunchao Zhang 449f659e5c7SJunchao Zhang /* Bcast from roots to leaves to tag connected leaves. We reuse the established bcast communication in 450f659e5c7SJunchao Zhang sf but do not do unpacking (from leaf buffer to leafdata). The raw data in leaf buffer is what we are 451f659e5c7SJunchao Zhang interested in since it tells which leaves are connected to which ranks. 452f659e5c7SJunchao Zhang */ 453eb02082bSJunchao Zhang ierr = PetscSFBcastAndOpBegin_Basic(sf,MPIU_INT,PETSC_MEMTYPE_HOST,rootdata,PETSC_MEMTYPE_HOST,leafdata-minleaf,MPIU_REPLACE);CHKERRQ(ierr); /* Need to give leafdata but we won't use it */ 454eb02082bSJunchao Zhang ierr = PetscSFPackGetInUse(sf,MPIU_INT,rootdata,leafdata-minleaf,PETSC_OWN_POINTER,&link);CHKERRQ(ierr); 455b7c0d12aSJunchao Zhang ierr = PetscSFPackWaitall(link,PETSCSF_ROOT2LEAF_BCAST);CHKERRQ(ierr); 456f659e5c7SJunchao Zhang ierr = PetscSFGetLeafInfo_Basic(sf,&nranks,&ndranks,&ranks,&roffset,&rmine,&rremote);CHKERRQ(ierr); /* Get send info */ 457f659e5c7SJunchao Zhang esf_nranks = esf_ndranks = connected_leaves = 0; 458b23bfdefSJunchao Zhang for (i=0; i<nranks; i++) { 459f659e5c7SJunchao Zhang connected = PETSC_FALSE; /* Is the current process still connected to this remote root rank? */ 460eb02082bSJunchao Zhang buffer = i < ndranks? (PetscInt*)link->selfbuf[PETSC_MEMTYPE_HOST] : (PetscInt*)link->leafbuf[PETSC_MEMTYPE_HOST] + (roffset[i] - roffset[ndranks]); 461b23bfdefSJunchao Zhang count = roffset[i+1] - roffset[i]; 462b23bfdefSJunchao Zhang for (j=0; j<count; j++) {if (buffer[j]) {connected_leaves++; connected = PETSC_TRUE;}} 463f659e5c7SJunchao Zhang if (connected) {esf_nranks++; if (i < ndranks) esf_ndranks++;} 464f659e5c7SJunchao Zhang } 465f659e5c7SJunchao Zhang 466f659e5c7SJunchao Zhang /* Set graph of esf and also set up its outgoing communication (i.e., send info), which is usually done by PetscSFSetUpRanks */ 467f659e5c7SJunchao Zhang ierr = PetscMalloc1(connected_leaves,&new_ilocal);CHKERRQ(ierr); 468f659e5c7SJunchao Zhang ierr = PetscMalloc1(connected_leaves,&new_iremote);CHKERRQ(ierr); 469f659e5c7SJunchao Zhang ierr = PetscMalloc4(esf_nranks,&esf_ranks,esf_nranks+1,&esf_roffset,connected_leaves,&esf_rmine,connected_leaves,&esf_rremote);CHKERRQ(ierr); 470f659e5c7SJunchao Zhang p = 0; /* Counter for connected root ranks */ 471f659e5c7SJunchao Zhang q = 0; /* Counter for connected leaves */ 472f659e5c7SJunchao Zhang esf_roffset[0] = 0; 473f659e5c7SJunchao Zhang for (i=0; i<nranks; i++) { /* Scan leaf data again to fill esf arrays */ 474eb02082bSJunchao Zhang buffer = i < ndranks? (PetscInt*)link->selfbuf[PETSC_MEMTYPE_HOST] : (PetscInt*)link->leafbuf[PETSC_MEMTYPE_HOST] + (roffset[i] - roffset[ndranks]); 475f659e5c7SJunchao Zhang connected = PETSC_FALSE; 476f659e5c7SJunchao Zhang for (j=roffset[i],k=0; j<roffset[i+1]; j++,k++) { 477b23bfdefSJunchao Zhang if (buffer[k]) { 478f659e5c7SJunchao Zhang esf_rmine[q] = new_ilocal[q] = rmine[j]; 479f659e5c7SJunchao Zhang esf_rremote[q] = rremote[j]; 480f659e5c7SJunchao Zhang new_iremote[q].index = rremote[j]; 481f659e5c7SJunchao Zhang new_iremote[q].rank = ranks[i]; 482f659e5c7SJunchao Zhang connected = PETSC_TRUE; 483f659e5c7SJunchao Zhang q++; 484f659e5c7SJunchao Zhang } 485f659e5c7SJunchao Zhang } 486f659e5c7SJunchao Zhang if (connected) { 487f659e5c7SJunchao Zhang esf_ranks[p] = ranks[i]; 488f659e5c7SJunchao Zhang esf_roffset[p+1] = q; 489f659e5c7SJunchao Zhang p++; 490f659e5c7SJunchao Zhang } 491f659e5c7SJunchao Zhang } 492f659e5c7SJunchao Zhang 493eb02082bSJunchao Zhang ierr = PetscSFPackReclaim(sf,&link);CHKERRQ(ierr); 494f659e5c7SJunchao Zhang 495f659e5c7SJunchao Zhang /* SetGraph internally resets the SF, so we only set its fields after the call */ 496f659e5c7SJunchao Zhang ierr = PetscSFSetGraph(esf,nroots,connected_leaves,new_ilocal,PETSC_OWN_POINTER,new_iremote,PETSC_OWN_POINTER);CHKERRQ(ierr); 497f659e5c7SJunchao Zhang esf->nranks = esf_nranks; 498f659e5c7SJunchao Zhang esf->ndranks = esf_ndranks; 499f659e5c7SJunchao Zhang esf->ranks = esf_ranks; 500f659e5c7SJunchao Zhang esf->roffset = esf_roffset; 501f659e5c7SJunchao Zhang esf->rmine = esf_rmine; 502f659e5c7SJunchao Zhang esf->rremote = esf_rremote; 503f659e5c7SJunchao Zhang 504f659e5c7SJunchao Zhang /* Set up the incoming communication (i.e., recv info) stored in esf->data, which is usually done by PetscSFSetUp_Basic */ 505f659e5c7SJunchao Zhang bas = (PetscSF_Basic*)esf->data; 506f659e5c7SJunchao Zhang ierr = PetscSFGetRootInfo_Basic(sf,&niranks,&ndiranks,&iranks,&ioffset,&irootloc);CHKERRQ(ierr); /* Get recv info */ 507f659e5c7SJunchao Zhang /* Embedded sf always has simpler communication than the original one. We might allocate longer arrays than needed here. But we 508f659e5c7SJunchao Zhang expect these arrays are usually short, so we do not care. The benefit is we can fill these arrays by just parsing irootloc once. 509f659e5c7SJunchao Zhang */ 510f659e5c7SJunchao Zhang ierr = PetscMalloc2(niranks,&bas->iranks,niranks+1,&bas->ioffset);CHKERRQ(ierr); 511f659e5c7SJunchao Zhang ierr = PetscMalloc1(ioffset[niranks],&bas->irootloc);CHKERRQ(ierr); 512f659e5c7SJunchao Zhang bas->niranks = bas->ndiranks = bas->ioffset[0] = 0; 513f659e5c7SJunchao Zhang p = 0; /* Counter for connected leaf ranks */ 514f659e5c7SJunchao Zhang q = 0; /* Counter for connected roots */ 515f659e5c7SJunchao Zhang for (i=0; i<niranks; i++) { 516f659e5c7SJunchao Zhang connected = PETSC_FALSE; /* Is the current process still connected to this remote leaf rank? */ 517f659e5c7SJunchao Zhang for (j=ioffset[i]; j<ioffset[i+1]; j++) { 518f659e5c7SJunchao Zhang PetscInt loc; 519f659e5c7SJunchao Zhang ierr = PetscFindInt(irootloc[j],nselected,selected,&loc);CHKERRQ(ierr); 520f659e5c7SJunchao Zhang if (loc >= 0) { /* Found in selected this root is connected */ 521f659e5c7SJunchao Zhang bas->irootloc[q++] = irootloc[j]; 522f659e5c7SJunchao Zhang connected = PETSC_TRUE; 523f659e5c7SJunchao Zhang } 524f659e5c7SJunchao Zhang } 525f659e5c7SJunchao Zhang if (connected) { 526f659e5c7SJunchao Zhang bas->niranks++; 527f659e5c7SJunchao Zhang if (i<ndiranks) bas->ndiranks++; /* Note that order of ranks (including distinguished ranks) is kept */ 528f659e5c7SJunchao Zhang bas->iranks[p] = iranks[i]; 529f659e5c7SJunchao Zhang bas->ioffset[p+1] = q; 530f659e5c7SJunchao Zhang p++; 531f659e5c7SJunchao Zhang } 532f659e5c7SJunchao Zhang } 533f659e5c7SJunchao Zhang bas->itotal = q; 534f659e5c7SJunchao Zhang 535f659e5c7SJunchao Zhang /* Setup packing optimizations */ 536eb02082bSJunchao Zhang ierr = PetscSFPackSetupOptimizations_Basic(esf);CHKERRQ(ierr); 537f659e5c7SJunchao Zhang esf->setupcalled = PETSC_TRUE; /* We have done setup ourselves! */ 538f659e5c7SJunchao Zhang 539f659e5c7SJunchao Zhang ierr = PetscFree2(rootdata,leafdata);CHKERRQ(ierr); 540f659e5c7SJunchao Zhang *newsf = esf; 541f659e5c7SJunchao Zhang PetscFunctionReturn(0); 542f659e5c7SJunchao Zhang } 543f659e5c7SJunchao Zhang 544f659e5c7SJunchao Zhang PETSC_INTERN PetscErrorCode PetscSFCreateEmbeddedLeafSF_Basic(PetscSF sf,PetscInt nselected,const PetscInt *selected,PetscSF *newsf) 545f659e5c7SJunchao Zhang { 546f659e5c7SJunchao Zhang PetscSF esf; 547f659e5c7SJunchao Zhang PetscInt i,j,k,p,q,nroots,*rootdata,*leafdata,*new_ilocal,niranks,ndiranks,minleaf,maxleaf,maxlocal; 548b23bfdefSJunchao Zhang const PetscInt *ilocal,*ioffset,*irootloc,*buffer; 549f659e5c7SJunchao Zhang const PetscMPIInt *iranks; 550eb02082bSJunchao Zhang PetscSFPack link; 551f659e5c7SJunchao Zhang PetscSFNode *new_iremote; 552f659e5c7SJunchao Zhang const PetscSFNode *iremote; 553f659e5c7SJunchao Zhang PetscSF_Basic *bas; 554f659e5c7SJunchao Zhang MPI_Group group; 555f659e5c7SJunchao Zhang PetscErrorCode ierr; 556f659e5c7SJunchao Zhang 557f659e5c7SJunchao Zhang PetscFunctionBegin; 558f659e5c7SJunchao Zhang ierr = PetscSFCreate(PetscObjectComm((PetscObject)sf),&esf);CHKERRQ(ierr); 559f659e5c7SJunchao Zhang ierr = PetscSFSetType(esf,PETSCSFBASIC);CHKERRQ(ierr); /* This optimized routine can only create a basic sf */ 560f659e5c7SJunchao Zhang 561f659e5c7SJunchao Zhang /* Set the graph of esf, which is easy for CreateEmbeddedLeafSF */ 562f659e5c7SJunchao Zhang ierr = PetscSFGetGraph(sf,&nroots,NULL,&ilocal,&iremote);CHKERRQ(ierr); 563f659e5c7SJunchao Zhang ierr = PetscSFGetLeafRange(sf,&minleaf,&maxleaf);CHKERRQ(ierr); 564f659e5c7SJunchao Zhang ierr = PetscMalloc1(nselected,&new_ilocal);CHKERRQ(ierr); 565f659e5c7SJunchao Zhang ierr = PetscMalloc1(nselected,&new_iremote);CHKERRQ(ierr); 566f659e5c7SJunchao Zhang for (i=0; i<nselected; i++) { 567f659e5c7SJunchao Zhang const PetscInt l = selected[i]; 568f659e5c7SJunchao Zhang new_ilocal[i] = ilocal ? ilocal[l] : l; 569f659e5c7SJunchao Zhang new_iremote[i].rank = iremote[l].rank; 570f659e5c7SJunchao Zhang new_iremote[i].index = iremote[l].index; 571f659e5c7SJunchao Zhang } 572f659e5c7SJunchao Zhang 573f659e5c7SJunchao Zhang /* Tag selected leaves before PetscSFSetGraph since new_ilocal might turn into NULL since we use PETSC_OWN_POINTER below */ 574f659e5c7SJunchao Zhang maxlocal = (minleaf > maxleaf)? 0 : maxleaf-minleaf+1; /* maxleaf=-1 and minleaf=0 when nleaves=0 */ 575f659e5c7SJunchao Zhang ierr = PetscCalloc2(nroots,&rootdata,maxlocal,&leafdata);CHKERRQ(ierr); 576f659e5c7SJunchao Zhang for (i=0; i<nselected; i++) leafdata[new_ilocal[i]-minleaf] = 1; /* -minleaf to adjust indices according to minleaf */ 577f659e5c7SJunchao Zhang 578f659e5c7SJunchao Zhang ierr = PetscSFSetGraph(esf,nroots,nselected,new_ilocal,PETSC_OWN_POINTER,new_iremote,PETSC_OWN_POINTER);CHKERRQ(ierr); 579f659e5c7SJunchao Zhang 580f659e5c7SJunchao Zhang /* Set up the outgoing communication (i.e., send info). We can not reuse rmine etc in sf since there is no way to 581f659e5c7SJunchao Zhang map rmine[i] (ilocal of leaves) back to selected[j] (leaf indices). 582f659e5c7SJunchao Zhang */ 583f659e5c7SJunchao Zhang ierr = MPI_Comm_group(PETSC_COMM_SELF,&group);CHKERRQ(ierr); 584f659e5c7SJunchao Zhang ierr = PetscSFSetUpRanks(esf,group);CHKERRQ(ierr); 585f659e5c7SJunchao Zhang ierr = MPI_Group_free(&group);CHKERRQ(ierr); 586f659e5c7SJunchao Zhang 587f659e5c7SJunchao Zhang /* Set up the incoming communication (i.e., recv info) */ 588f659e5c7SJunchao Zhang ierr = PetscSFGetRootInfo_Basic(sf,&niranks,&ndiranks,&iranks,&ioffset,&irootloc);CHKERRQ(ierr); 589f659e5c7SJunchao Zhang bas = (PetscSF_Basic*)esf->data; 590f659e5c7SJunchao Zhang ierr = PetscMalloc2(niranks,&bas->iranks,niranks+1,&bas->ioffset);CHKERRQ(ierr); 591f659e5c7SJunchao Zhang ierr = PetscMalloc1(ioffset[niranks],&bas->irootloc);CHKERRQ(ierr); 592f659e5c7SJunchao Zhang 593f659e5c7SJunchao Zhang /* Pass info about selected leaves to root buffer */ 594eb02082bSJunchao Zhang ierr = PetscSFReduceBegin_Basic(sf,MPIU_INT,PETSC_MEMTYPE_HOST,leafdata-minleaf,PETSC_MEMTYPE_HOST,rootdata,MPIU_REPLACE);CHKERRQ(ierr); /* -minleaf to re-adjust start address of leafdata */ 595eb02082bSJunchao Zhang ierr = PetscSFPackGetInUse(sf,MPIU_INT,rootdata,leafdata-minleaf,PETSC_OWN_POINTER,&link);CHKERRQ(ierr); 596b7c0d12aSJunchao Zhang ierr = PetscSFPackWaitall(link,PETSCSF_LEAF2ROOT_REDUCE);CHKERRQ(ierr); 597f659e5c7SJunchao Zhang 598f659e5c7SJunchao Zhang bas->niranks = bas->ndiranks = bas->ioffset[0] = 0; 599f659e5c7SJunchao Zhang p = 0; /* Counter for connected leaf ranks */ 600f659e5c7SJunchao Zhang q = 0; /* Counter for connected roots */ 601f659e5c7SJunchao Zhang for (i=0; i<niranks; i++) { 602f659e5c7SJunchao Zhang PetscBool connected = PETSC_FALSE; /* Is the current process still connected to this remote leaf rank? */ 603eb02082bSJunchao Zhang buffer = i < ndiranks? (PetscInt*)link->selfbuf[PETSC_MEMTYPE_HOST] : (PetscInt*)link->rootbuf[PETSC_MEMTYPE_HOST] + (ioffset[i] - ioffset[ndiranks]); 604f659e5c7SJunchao Zhang for (j=ioffset[i],k=0; j<ioffset[i+1]; j++,k++) { 605b23bfdefSJunchao Zhang if (buffer[k]) {bas->irootloc[q++] = irootloc[j]; connected = PETSC_TRUE;} 606f659e5c7SJunchao Zhang } 607f659e5c7SJunchao Zhang if (connected) { 608f659e5c7SJunchao Zhang bas->niranks++; 609f659e5c7SJunchao Zhang if (i<ndiranks) bas->ndiranks++; 610f659e5c7SJunchao Zhang bas->iranks[p] = iranks[i]; 611f659e5c7SJunchao Zhang bas->ioffset[p+1] = q; 612f659e5c7SJunchao Zhang p++; 613f659e5c7SJunchao Zhang } 614f659e5c7SJunchao Zhang } 615f659e5c7SJunchao Zhang bas->itotal = q; 616eb02082bSJunchao Zhang ierr = PetscSFPackReclaim(sf,&link);CHKERRQ(ierr); 617f659e5c7SJunchao Zhang 618f659e5c7SJunchao Zhang /* Setup packing optimizations */ 619eb02082bSJunchao Zhang ierr = PetscSFPackSetupOptimizations_Basic(esf);CHKERRQ(ierr); 620f659e5c7SJunchao Zhang esf->setupcalled = PETSC_TRUE; /* We have done setup ourselves! */ 621f659e5c7SJunchao Zhang 622f659e5c7SJunchao Zhang ierr = PetscFree2(rootdata,leafdata);CHKERRQ(ierr); 623f659e5c7SJunchao Zhang *newsf = esf; 624f659e5c7SJunchao Zhang PetscFunctionReturn(0); 625f659e5c7SJunchao Zhang } 626f659e5c7SJunchao Zhang 6278cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PetscSFCreate_Basic(PetscSF sf) 62895fce210SBarry Smith { 62940e23c03SJunchao Zhang PetscSF_Basic *dat; 63095fce210SBarry Smith PetscErrorCode ierr; 63195fce210SBarry Smith 63295fce210SBarry Smith PetscFunctionBegin; 63395fce210SBarry Smith sf->ops->SetUp = PetscSFSetUp_Basic; 63495fce210SBarry Smith sf->ops->SetFromOptions = PetscSFSetFromOptions_Basic; 63595fce210SBarry Smith sf->ops->Reset = PetscSFReset_Basic; 63695fce210SBarry Smith sf->ops->Destroy = PetscSFDestroy_Basic; 63795fce210SBarry Smith sf->ops->View = PetscSFView_Basic; 6383482bfa8SJunchao Zhang sf->ops->BcastAndOpBegin = PetscSFBcastAndOpBegin_Basic; 6393482bfa8SJunchao Zhang sf->ops->BcastAndOpEnd = PetscSFBcastAndOpEnd_Basic; 64095fce210SBarry Smith sf->ops->ReduceBegin = PetscSFReduceBegin_Basic; 64195fce210SBarry Smith sf->ops->ReduceEnd = PetscSFReduceEnd_Basic; 64295fce210SBarry Smith sf->ops->FetchAndOpBegin = PetscSFFetchAndOpBegin_Basic; 64395fce210SBarry Smith sf->ops->FetchAndOpEnd = PetscSFFetchAndOpEnd_Basic; 6448750ddebSJunchao Zhang sf->ops->GetLeafRanks = PetscSFGetLeafRanks_Basic; 645f659e5c7SJunchao Zhang sf->ops->CreateEmbeddedSF = PetscSFCreateEmbeddedSF_Basic; 646f659e5c7SJunchao Zhang sf->ops->CreateEmbeddedLeafSF = PetscSFCreateEmbeddedLeafSF_Basic; 64795fce210SBarry Smith 64840e23c03SJunchao Zhang ierr = PetscNewLog(sf,&dat);CHKERRQ(ierr); 64940e23c03SJunchao Zhang sf->data = (void*)dat; 65095fce210SBarry Smith PetscFunctionReturn(0); 65195fce210SBarry Smith } 652