1f6ced4a3SJed Brown #include <petscsys.h> /*I "petscsys.h" I*/ 2f6ced4a3SJed Brown 33b3561c8SJed Brown PetscLogEvent PETSC_BuildTwoSided; 43b3561c8SJed Brown 56145cd65SJed Brown const char *const PetscBuildTwoSidedTypes[] = { 6f6ced4a3SJed Brown "ALLREDUCE", 76145cd65SJed Brown "IBARRIER", 8*1654bf6bSJed Brown "REDSCATTER", 96145cd65SJed Brown "PetscBuildTwoSidedType", 106145cd65SJed Brown "PETSC_BUILDTWOSIDED_", 11f6ced4a3SJed Brown 0 12f6ced4a3SJed Brown }; 13f6ced4a3SJed Brown 146145cd65SJed Brown static PetscBuildTwoSidedType _twosided_type = PETSC_BUILDTWOSIDED_NOTSET; 15f6ced4a3SJed Brown 16f6ced4a3SJed Brown #undef __FUNCT__ 176145cd65SJed Brown #define __FUNCT__ "PetscCommBuildTwoSidedSetType" 186145cd65SJed Brown /*@ 196145cd65SJed Brown PetscCommBuildTwoSidedSetType - set algorithm to use when building two-sided communication 206145cd65SJed Brown 216145cd65SJed Brown Logically Collective 226145cd65SJed Brown 236145cd65SJed Brown Input Arguments: 246145cd65SJed Brown + comm - PETSC_COMM_WORLD 256145cd65SJed Brown - twosided - algorithm to use in subsequent calls to PetscCommBuildTwoSided() 266145cd65SJed Brown 276145cd65SJed Brown Level: developer 286145cd65SJed Brown 296145cd65SJed Brown Note: 306145cd65SJed Brown This option is currently global, but could be made per-communicator. 316145cd65SJed Brown 326145cd65SJed Brown .seealso: PetscCommBuildTwoSided(), PetscCommBuildTwoSidedGetType() 336145cd65SJed Brown @*/ 346145cd65SJed Brown PetscErrorCode PetscCommBuildTwoSidedSetType(MPI_Comm comm,PetscBuildTwoSidedType twosided) 356145cd65SJed Brown { 366145cd65SJed Brown PetscFunctionBegin; 376145cd65SJed Brown #if defined(PETSC_USE_DEBUG) 386145cd65SJed Brown { /* We don't have a PetscObject so can't use PetscValidLogicalCollectiveEnum */ 396145cd65SJed Brown PetscMPIInt ierr; 406145cd65SJed Brown PetscMPIInt b1[2],b2[2]; 416145cd65SJed Brown b1[0] = -(PetscMPIInt)twosided; 426145cd65SJed Brown b1[1] = (PetscMPIInt)twosided; 436145cd65SJed Brown ierr = MPI_Allreduce(b1,b2,2,MPI_INT,MPI_MAX,comm);CHKERRQ(ierr); 446145cd65SJed Brown if (-b2[0] != b2[1]) SETERRQ(comm,PETSC_ERR_ARG_WRONG,"Enum value must be same on all processes"); 456145cd65SJed Brown } 466145cd65SJed Brown #endif 476145cd65SJed Brown _twosided_type = twosided; 486145cd65SJed Brown PetscFunctionReturn(0); 496145cd65SJed Brown } 506145cd65SJed Brown 516145cd65SJed Brown #undef __FUNCT__ 526145cd65SJed Brown #define __FUNCT__ "PetscCommBuildTwoSidedGetType" 536145cd65SJed Brown /*@ 546145cd65SJed Brown PetscCommBuildTwoSidedGetType - set algorithm to use when building two-sided communication 556145cd65SJed Brown 566145cd65SJed Brown Logically Collective 576145cd65SJed Brown 586145cd65SJed Brown Output Arguments: 596145cd65SJed Brown + comm - communicator on which to query algorithm 606145cd65SJed Brown - twosided - algorithm to use for PetscCommBuildTwoSided() 616145cd65SJed Brown 626145cd65SJed Brown Level: developer 636145cd65SJed Brown 646145cd65SJed Brown .seealso: PetscCommBuildTwoSided(), PetscCommBuildTwoSidedSetType() 656145cd65SJed Brown @*/ 666145cd65SJed Brown PetscErrorCode PetscCommBuildTwoSidedGetType(MPI_Comm comm,PetscBuildTwoSidedType *twosided) 67f6ced4a3SJed Brown { 68f6ced4a3SJed Brown PetscErrorCode ierr; 69f6ced4a3SJed Brown 70f6ced4a3SJed Brown PetscFunctionBegin; 716145cd65SJed Brown *twosided = PETSC_BUILDTWOSIDED_NOTSET; 726145cd65SJed Brown if (_twosided_type == PETSC_BUILDTWOSIDED_NOTSET) { 73f6ced4a3SJed Brown #if defined(PETSC_HAVE_MPI_IBARRIER) 746145cd65SJed Brown # if defined(PETSC_HAVE_MPICH_CH3_SOCK) && !defined(PETSC_HAVE_MPICH_CH3_SOCK_FIXED_NBC_PROGRESS) 756145cd65SJed Brown /* Deadlock in Ibarrier: http://trac.mpich.org/projects/mpich/ticket/1785 */ 766145cd65SJed Brown _twosided_type = PETSC_BUILDTWOSIDED_ALLREDUCE; 77f6ced4a3SJed Brown # else 786145cd65SJed Brown _twosided_type = PETSC_BUILDTWOSIDED_IBARRIER; 79f6ced4a3SJed Brown # endif 806145cd65SJed Brown #else 816145cd65SJed Brown _twosided_type = PETSC_BUILDTWOSIDED_ALLREDUCE; 826145cd65SJed Brown #endif 830298fd71SBarry Smith ierr = PetscOptionsGetEnum(NULL,"-build_twosided",PetscBuildTwoSidedTypes,(PetscEnum*)&_twosided_type,NULL);CHKERRQ(ierr); 84f6ced4a3SJed Brown } 85f6ced4a3SJed Brown *twosided = _twosided_type; 86f6ced4a3SJed Brown PetscFunctionReturn(0); 87f6ced4a3SJed Brown } 88f6ced4a3SJed Brown 89f6ced4a3SJed Brown #if defined(PETSC_HAVE_MPI_IBARRIER) 90f6ced4a3SJed Brown 91f6ced4a3SJed Brown #undef __FUNCT__ 926145cd65SJed Brown #define __FUNCT__ "PetscCommBuildTwoSided_Ibarrier" 936145cd65SJed Brown static PetscErrorCode PetscCommBuildTwoSided_Ibarrier(MPI_Comm comm,PetscMPIInt count,MPI_Datatype dtype,PetscInt nto,const PetscMPIInt *toranks,const void *todata,PetscInt *nfrom,PetscMPIInt **fromranks,void *fromdata) 94f6ced4a3SJed Brown { 95f6ced4a3SJed Brown PetscErrorCode ierr; 96f6ced4a3SJed Brown PetscMPIInt nrecvs,tag,unitbytes,done; 97f6ced4a3SJed Brown PetscInt i; 98f6ced4a3SJed Brown char *tdata; 99f6ced4a3SJed Brown MPI_Request *sendreqs,barrier; 1000f453b92SJed Brown PetscSegBuffer segrank,segdata; 101f6ced4a3SJed Brown 102f6ced4a3SJed Brown PetscFunctionBegin; 103f6ced4a3SJed Brown ierr = PetscCommGetNewTag(comm,&tag);CHKERRQ(ierr); 104f6ced4a3SJed Brown ierr = MPI_Type_size(dtype,&unitbytes);CHKERRQ(ierr); 105f6ced4a3SJed Brown tdata = (char*)todata; 106785e854fSJed Brown ierr = PetscMalloc1(nto,&sendreqs);CHKERRQ(ierr); 107f6ced4a3SJed Brown for (i=0; i<nto; i++) { 108f6ced4a3SJed Brown ierr = MPI_Issend((void*)(tdata+count*unitbytes*i),count,dtype,toranks[i],tag,comm,sendreqs+i);CHKERRQ(ierr); 109f6ced4a3SJed Brown } 1100f453b92SJed Brown ierr = PetscSegBufferCreate(sizeof(PetscMPIInt),4,&segrank);CHKERRQ(ierr); 1110f453b92SJed Brown ierr = PetscSegBufferCreate(unitbytes,4*count,&segdata);CHKERRQ(ierr); 112f6ced4a3SJed Brown 113f6ced4a3SJed Brown nrecvs = 0; 114f6ced4a3SJed Brown barrier = MPI_REQUEST_NULL; 115f6ced4a3SJed Brown for (done=0; !done; ) { 116f6ced4a3SJed Brown PetscMPIInt flag; 117f6ced4a3SJed Brown MPI_Status status; 118f6ced4a3SJed Brown ierr = MPI_Iprobe(MPI_ANY_SOURCE,tag,comm,&flag,&status);CHKERRQ(ierr); 119f6ced4a3SJed Brown if (flag) { /* incoming message */ 120f6ced4a3SJed Brown PetscMPIInt *recvrank; 121f6ced4a3SJed Brown void *buf; 122137cf7b6SJed Brown ierr = PetscSegBufferGet(segrank,1,&recvrank);CHKERRQ(ierr); 123137cf7b6SJed Brown ierr = PetscSegBufferGet(segdata,count,&buf);CHKERRQ(ierr); 124f6ced4a3SJed Brown *recvrank = status.MPI_SOURCE; 125f6ced4a3SJed Brown ierr = MPI_Recv(buf,count,dtype,status.MPI_SOURCE,tag,comm,MPI_STATUS_IGNORE);CHKERRQ(ierr); 126f6ced4a3SJed Brown nrecvs++; 127f6ced4a3SJed Brown } 128f6ced4a3SJed Brown if (barrier == MPI_REQUEST_NULL) { 1294dc2109aSBarry Smith PetscMPIInt sent,nsends; 1304dc2109aSBarry Smith ierr = PetscMPIIntCast(nto,&nsends);CHKERRQ(ierr); 131f6ced4a3SJed Brown ierr = MPI_Testall(nsends,sendreqs,&sent,MPI_STATUSES_IGNORE);CHKERRQ(ierr); 132f6ced4a3SJed Brown if (sent) { 133f6ced4a3SJed Brown ierr = MPI_Ibarrier(comm,&barrier);CHKERRQ(ierr); 134f6ced4a3SJed Brown ierr = PetscFree(sendreqs);CHKERRQ(ierr); 135f6ced4a3SJed Brown } 136f6ced4a3SJed Brown } else { 137f6ced4a3SJed Brown ierr = MPI_Test(&barrier,&done,MPI_STATUS_IGNORE);CHKERRQ(ierr); 138f6ced4a3SJed Brown } 139f6ced4a3SJed Brown } 140f6ced4a3SJed Brown *nfrom = nrecvs; 141137cf7b6SJed Brown ierr = PetscSegBufferExtractAlloc(segrank,fromranks);CHKERRQ(ierr); 1420f453b92SJed Brown ierr = PetscSegBufferDestroy(&segrank);CHKERRQ(ierr); 143137cf7b6SJed Brown ierr = PetscSegBufferExtractAlloc(segdata,fromdata);CHKERRQ(ierr); 1440f453b92SJed Brown ierr = PetscSegBufferDestroy(&segdata);CHKERRQ(ierr); 145f6ced4a3SJed Brown PetscFunctionReturn(0); 146f6ced4a3SJed Brown } 147f6ced4a3SJed Brown #endif 148f6ced4a3SJed Brown 149f6ced4a3SJed Brown #undef __FUNCT__ 1506145cd65SJed Brown #define __FUNCT__ "PetscCommBuildTwoSided_Allreduce" 1516145cd65SJed Brown static PetscErrorCode PetscCommBuildTwoSided_Allreduce(MPI_Comm comm,PetscMPIInt count,MPI_Datatype dtype,PetscInt nto,const PetscMPIInt *toranks,const void *todata,PetscInt *nfrom,PetscMPIInt **fromranks,void *fromdata) 152f6ced4a3SJed Brown { 153f6ced4a3SJed Brown PetscErrorCode ierr; 154f6ced4a3SJed Brown PetscMPIInt size,*iflags,nrecvs,tag,unitbytes,*franks; 155f6ced4a3SJed Brown PetscInt i; 156f6ced4a3SJed Brown char *tdata,*fdata; 157f6ced4a3SJed Brown MPI_Request *reqs,*sendreqs; 158f6ced4a3SJed Brown MPI_Status *statuses; 159f6ced4a3SJed Brown 160f6ced4a3SJed Brown PetscFunctionBegin; 161f6ced4a3SJed Brown ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 1621795a4d1SJed Brown ierr = PetscCalloc1(size,&iflags);CHKERRQ(ierr); 163f6ced4a3SJed Brown for (i=0; i<nto; i++) iflags[toranks[i]] = 1; 1640298fd71SBarry Smith ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&nrecvs);CHKERRQ(ierr); 165f6ced4a3SJed Brown ierr = PetscFree(iflags);CHKERRQ(ierr); 166f6ced4a3SJed Brown 167f6ced4a3SJed Brown ierr = PetscCommGetNewTag(comm,&tag);CHKERRQ(ierr); 168f6ced4a3SJed Brown ierr = MPI_Type_size(dtype,&unitbytes);CHKERRQ(ierr); 169f6ced4a3SJed Brown ierr = PetscMalloc(nrecvs*count*unitbytes,&fdata);CHKERRQ(ierr); 170f6ced4a3SJed Brown tdata = (char*)todata; 171dcca6d9dSJed Brown ierr = PetscMalloc2(nto+nrecvs,&reqs,nto+nrecvs,&statuses);CHKERRQ(ierr); 17206926cafSJed Brown sendreqs = reqs + nrecvs; 173f6ced4a3SJed Brown for (i=0; i<nrecvs; i++) { 174f6ced4a3SJed Brown ierr = MPI_Irecv((void*)(fdata+count*unitbytes*i),count,dtype,MPI_ANY_SOURCE,tag,comm,reqs+i);CHKERRQ(ierr); 175f6ced4a3SJed Brown } 176f6ced4a3SJed Brown for (i=0; i<nto; i++) { 177f6ced4a3SJed Brown ierr = MPI_Isend((void*)(tdata+count*unitbytes*i),count,dtype,toranks[i],tag,comm,sendreqs+i);CHKERRQ(ierr); 178f6ced4a3SJed Brown } 179f6ced4a3SJed Brown ierr = MPI_Waitall(nto+nrecvs,reqs,statuses);CHKERRQ(ierr); 180785e854fSJed Brown ierr = PetscMalloc1(nrecvs,&franks);CHKERRQ(ierr); 181a297a907SKarl Rupp for (i=0; i<nrecvs; i++) franks[i] = statuses[i].MPI_SOURCE; 18206926cafSJed Brown ierr = PetscFree2(reqs,statuses);CHKERRQ(ierr); 183f6ced4a3SJed Brown 184f6ced4a3SJed Brown *nfrom = nrecvs; 185f6ced4a3SJed Brown *fromranks = franks; 186f6ced4a3SJed Brown *(void**)fromdata = fdata; 187f6ced4a3SJed Brown PetscFunctionReturn(0); 188f6ced4a3SJed Brown } 189f6ced4a3SJed Brown 190*1654bf6bSJed Brown #if defined(PETSC_HAVE_MPI_REDUCE_SCATTER_BLOCK) 191*1654bf6bSJed Brown #undef __FUNCT__ 192*1654bf6bSJed Brown #define __FUNCT__ "PetscCommBuildTwoSided_RedScatter" 193*1654bf6bSJed Brown static PetscErrorCode PetscCommBuildTwoSided_RedScatter(MPI_Comm comm,PetscMPIInt count,MPI_Datatype dtype,PetscInt nto,const PetscMPIInt *toranks,const void *todata,PetscInt *nfrom,PetscMPIInt **fromranks,void *fromdata) 194*1654bf6bSJed Brown { 195*1654bf6bSJed Brown PetscErrorCode ierr; 196*1654bf6bSJed Brown PetscMPIInt size,*iflags,nrecvs,tag,unitbytes,*franks; 197*1654bf6bSJed Brown PetscInt i; 198*1654bf6bSJed Brown char *tdata,*fdata; 199*1654bf6bSJed Brown MPI_Request *reqs,*sendreqs; 200*1654bf6bSJed Brown MPI_Status *statuses; 201*1654bf6bSJed Brown 202*1654bf6bSJed Brown PetscFunctionBegin; 203*1654bf6bSJed Brown ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 204*1654bf6bSJed Brown ierr = PetscMalloc1(size,&iflags);CHKERRQ(ierr); 205*1654bf6bSJed Brown ierr = PetscMemzero(iflags,size*sizeof(*iflags));CHKERRQ(ierr); 206*1654bf6bSJed Brown for (i=0; i<nto; i++) iflags[toranks[i]] = 1; 207*1654bf6bSJed Brown ierr = MPI_Reduce_scatter_block(iflags,&nrecvs,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr); 208*1654bf6bSJed Brown ierr = PetscFree(iflags);CHKERRQ(ierr); 209*1654bf6bSJed Brown 210*1654bf6bSJed Brown ierr = PetscCommGetNewTag(comm,&tag);CHKERRQ(ierr); 211*1654bf6bSJed Brown ierr = MPI_Type_size(dtype,&unitbytes);CHKERRQ(ierr); 212*1654bf6bSJed Brown ierr = PetscMalloc(nrecvs*count*unitbytes,&fdata);CHKERRQ(ierr); 213*1654bf6bSJed Brown tdata = (char*)todata; 214*1654bf6bSJed Brown ierr = PetscMalloc2(nto+nrecvs,&reqs,nto+nrecvs,&statuses);CHKERRQ(ierr); 215*1654bf6bSJed Brown sendreqs = reqs + nrecvs; 216*1654bf6bSJed Brown for (i=0; i<nrecvs; i++) { 217*1654bf6bSJed Brown ierr = MPI_Irecv((void*)(fdata+count*unitbytes*i),count,dtype,MPI_ANY_SOURCE,tag,comm,reqs+i);CHKERRQ(ierr); 218*1654bf6bSJed Brown } 219*1654bf6bSJed Brown for (i=0; i<nto; i++) { 220*1654bf6bSJed Brown ierr = MPI_Isend((void*)(tdata+count*unitbytes*i),count,dtype,toranks[i],tag,comm,sendreqs+i);CHKERRQ(ierr); 221*1654bf6bSJed Brown } 222*1654bf6bSJed Brown ierr = MPI_Waitall(nto+nrecvs,reqs,statuses);CHKERRQ(ierr); 223*1654bf6bSJed Brown ierr = PetscMalloc1(nrecvs,&franks);CHKERRQ(ierr); 224*1654bf6bSJed Brown for (i=0; i<nrecvs; i++) franks[i] = statuses[i].MPI_SOURCE; 225*1654bf6bSJed Brown ierr = PetscFree2(reqs,statuses);CHKERRQ(ierr); 226*1654bf6bSJed Brown 227*1654bf6bSJed Brown *nfrom = nrecvs; 228*1654bf6bSJed Brown *fromranks = franks; 229*1654bf6bSJed Brown *(void**)fromdata = fdata; 230*1654bf6bSJed Brown PetscFunctionReturn(0); 231*1654bf6bSJed Brown } 232*1654bf6bSJed Brown #endif 233*1654bf6bSJed Brown 234f6ced4a3SJed Brown #undef __FUNCT__ 235f6ced4a3SJed Brown #define __FUNCT__ "PetscCommBuildTwoSided" 236f6ced4a3SJed Brown /*@C 237f6ced4a3SJed Brown PetscCommBuildTwoSided - discovers communicating ranks given one-sided information, moving constant-sized data in the process (often message lengths) 238f6ced4a3SJed Brown 239f6ced4a3SJed Brown Collective on MPI_Comm 240f6ced4a3SJed Brown 241f6ced4a3SJed Brown Input Arguments: 242f6ced4a3SJed Brown + comm - communicator 243f6ced4a3SJed Brown . count - number of entries to send/receive (must match on all ranks) 244f6ced4a3SJed Brown . dtype - datatype to send/receive from each rank (must match on all ranks) 245f6ced4a3SJed Brown . nto - number of ranks to send data to 246f6ced4a3SJed Brown . toranks - ranks to send to (array of length nto) 247f6ced4a3SJed Brown - todata - data to send to each rank (packed) 248f6ced4a3SJed Brown 249f6ced4a3SJed Brown Output Arguments: 250f6ced4a3SJed Brown + nfrom - number of ranks receiving messages from 251f6ced4a3SJed Brown . fromranks - ranks receiving messages from (length nfrom; caller should PetscFree()) 252f6ced4a3SJed Brown - fromdata - packed data from each rank, each with count entries of type dtype (length nfrom, caller responsible for PetscFree()) 253f6ced4a3SJed Brown 254f6ced4a3SJed Brown Level: developer 255f6ced4a3SJed Brown 256*1654bf6bSJed Brown Options Database Keys: 257*1654bf6bSJed Brown . -build_twosided <allreduce|ibarrier|redscatter> - algorithm to set up two-sided communication 258*1654bf6bSJed Brown 259f6ced4a3SJed Brown Notes: 260f6ced4a3SJed Brown This memory-scalable interface is an alternative to calling PetscGatherNumberOfMessages() and 261f6ced4a3SJed Brown PetscGatherMessageLengths(), possibly with a subsequent round of communication to send other constant-size data. 262f6ced4a3SJed Brown 263f6ced4a3SJed Brown Basic data types as well as contiguous types are supported, but non-contiguous (e.g., strided) types are not. 264f6ced4a3SJed Brown 265f6ced4a3SJed Brown References: 266f6ced4a3SJed Brown The MPI_Ibarrier implementation uses the algorithm in 267f6ced4a3SJed Brown Hoefler, Siebert and Lumsdaine, Scalable communication protocols for dynamic sparse data exchange, 2010. 268f6ced4a3SJed Brown 269f6ced4a3SJed Brown .seealso: PetscGatherNumberOfMessages(), PetscGatherMessageLengths() 270f6ced4a3SJed Brown @*/ 271f6ced4a3SJed Brown PetscErrorCode PetscCommBuildTwoSided(MPI_Comm comm,PetscMPIInt count,MPI_Datatype dtype,PetscInt nto,const PetscMPIInt *toranks,const void *todata,PetscInt *nfrom,PetscMPIInt **fromranks,void *fromdata) 272f6ced4a3SJed Brown { 273f6ced4a3SJed Brown PetscErrorCode ierr; 2746145cd65SJed Brown PetscBuildTwoSidedType buildtype = PETSC_BUILDTWOSIDED_NOTSET; 275f6ced4a3SJed Brown 276f6ced4a3SJed Brown PetscFunctionBegin; 2773b3561c8SJed Brown ierr = PetscSysInitializePackage();CHKERRQ(ierr); 2783b3561c8SJed Brown ierr = PetscLogEventBegin(PETSC_BuildTwoSided,0,0,0,0);CHKERRQ(ierr); 2796145cd65SJed Brown ierr = PetscCommBuildTwoSidedGetType(comm,&buildtype);CHKERRQ(ierr); 280f6ced4a3SJed Brown switch (buildtype) { 2816145cd65SJed Brown case PETSC_BUILDTWOSIDED_IBARRIER: 282f6ced4a3SJed Brown #if defined(PETSC_HAVE_MPI_IBARRIER) 2836145cd65SJed Brown ierr = PetscCommBuildTwoSided_Ibarrier(comm,count,dtype,nto,toranks,todata,nfrom,fromranks,fromdata);CHKERRQ(ierr); 2846145cd65SJed Brown #else 2856145cd65SJed Brown SETERRQ(comm,PETSC_ERR_PLIB,"MPI implementation does not provide MPI_Ibarrier (part of MPI-3)"); 286f6ced4a3SJed Brown #endif 2876145cd65SJed Brown break; 2886145cd65SJed Brown case PETSC_BUILDTWOSIDED_ALLREDUCE: 2896145cd65SJed Brown ierr = PetscCommBuildTwoSided_Allreduce(comm,count,dtype,nto,toranks,todata,nfrom,fromranks,fromdata);CHKERRQ(ierr); 290f6ced4a3SJed Brown break; 291*1654bf6bSJed Brown case PETSC_BUILDTWOSIDED_REDSCATTER: 292*1654bf6bSJed Brown #if defined(PETSC_HAVE_MPI_REDUCE_SCATTER_BLOCK) 293*1654bf6bSJed Brown ierr = PetscCommBuildTwoSided_RedScatter(comm,count,dtype,nto,toranks,todata,nfrom,fromranks,fromdata);CHKERRQ(ierr); 294*1654bf6bSJed Brown #else 295*1654bf6bSJed Brown SETERRQ(comm,PETSC_ERR_PLIB,"MPI implementation does not provide MPI_Reduce_scatter_block (part of MPI-2.2)"); 296*1654bf6bSJed Brown #endif 297*1654bf6bSJed Brown break; 298f6ced4a3SJed Brown default: SETERRQ(comm,PETSC_ERR_PLIB,"Unknown method for building two-sided communication"); 299f6ced4a3SJed Brown } 3003b3561c8SJed Brown ierr = PetscLogEventEnd(PETSC_BuildTwoSided,0,0,0,0);CHKERRQ(ierr); 301f6ced4a3SJed Brown PetscFunctionReturn(0); 302f6ced4a3SJed Brown } 303