1e5c89e4eSSatish Balay 2c6db04a5SJed Brown #include <petscsys.h> /*I "petscsys.h" I*/ 3e5c89e4eSSatish Balay 4e5c89e4eSSatish Balay 5e5c89e4eSSatish Balay /*@C 6e5c89e4eSSatish Balay PetscGatherNumberOfMessages - Computes the number of messages a node expects to receive 7e5c89e4eSSatish Balay 8d083f849SBarry Smith Collective 9e5c89e4eSSatish Balay 10e5c89e4eSSatish Balay Input Parameters: 11e5c89e4eSSatish Balay + comm - Communicator 12e5c89e4eSSatish Balay . iflags - an array of integers of length sizeof(comm). A '1' in ilengths[i] represent a 130298fd71SBarry Smith message from current node to ith node. Optionally NULL 14e5c89e4eSSatish Balay - ilengths - Non zero ilengths[i] represent a message to i of length ilengths[i]. 150298fd71SBarry Smith Optionally NULL. 16e5c89e4eSSatish Balay 17e5c89e4eSSatish Balay Output Parameters: 18e5c89e4eSSatish Balay . nrecvs - number of messages received 19e5c89e4eSSatish Balay 20e5c89e4eSSatish Balay Level: developer 21e5c89e4eSSatish Balay 22e5c89e4eSSatish Balay Notes: 23e5c89e4eSSatish Balay With this info, the correct message lengths can be determined using 24e5c89e4eSSatish Balay PetscGatherMessageLengths() 25e5c89e4eSSatish Balay 26e5c89e4eSSatish Balay Either iflags or ilengths should be provided. If iflags is not 270298fd71SBarry Smith provided (NULL) it can be computed from ilengths. If iflags is 28e5c89e4eSSatish Balay provided, ilengths is not required. 29e5c89e4eSSatish Balay 30e5c89e4eSSatish Balay .seealso: PetscGatherMessageLengths() 31e5c89e4eSSatish Balay @*/ 327087cfbeSBarry Smith PetscErrorCode PetscGatherNumberOfMessages(MPI_Comm comm,const PetscMPIInt iflags[],const PetscMPIInt ilengths[],PetscMPIInt *nrecvs) 33e5c89e4eSSatish Balay { 340298fd71SBarry Smith PetscMPIInt size,rank,*recv_buf,i,*iflags_local = NULL,*iflags_localm = NULL; 35e5c89e4eSSatish Balay PetscErrorCode ierr; 36e5c89e4eSSatish Balay 37e5c89e4eSSatish Balay PetscFunctionBegin; 38e5c89e4eSSatish Balay ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 39e5c89e4eSSatish Balay ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 40e5c89e4eSSatish Balay 41dcca6d9dSJed Brown ierr = PetscMalloc2(size,&recv_buf,size,&iflags_localm);CHKERRQ(ierr); 42e5c89e4eSSatish Balay 43e5c89e4eSSatish Balay /* If iflags not provided, compute iflags from ilengths */ 44e5c89e4eSSatish Balay if (!iflags) { 45e32f2f54SBarry Smith if (!ilengths) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Either iflags or ilengths should be provided"); 46e5c89e4eSSatish Balay iflags_local = iflags_localm; 47e5c89e4eSSatish Balay for (i=0; i<size; i++) { 48e5c89e4eSSatish Balay if (ilengths[i]) iflags_local[i] = 1; 49e5c89e4eSSatish Balay else iflags_local[i] = 0; 50e5c89e4eSSatish Balay } 51a297a907SKarl Rupp } else iflags_local = (PetscMPIInt*) iflags; 52e5c89e4eSSatish Balay 53e5c89e4eSSatish Balay /* Post an allreduce to determine the numer of messages the current node will receive */ 54b2566f29SBarry Smith ierr = MPIU_Allreduce(iflags_local,recv_buf,size,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr); 55e5c89e4eSSatish Balay *nrecvs = recv_buf[rank]; 56e5c89e4eSSatish Balay 57e5c89e4eSSatish Balay ierr = PetscFree2(recv_buf,iflags_localm);CHKERRQ(ierr); 58e5c89e4eSSatish Balay PetscFunctionReturn(0); 59e5c89e4eSSatish Balay } 60e5c89e4eSSatish Balay 61e5c89e4eSSatish Balay 62e5c89e4eSSatish Balay /*@C 63e5c89e4eSSatish Balay PetscGatherMessageLengths - Computes info about messages that a MPI-node will receive, 64e5c89e4eSSatish Balay including (from-id,length) pairs for each message. 65e5c89e4eSSatish Balay 66d083f849SBarry Smith Collective 67e5c89e4eSSatish Balay 68e5c89e4eSSatish Balay Input Parameters: 69e5c89e4eSSatish Balay + comm - Communicator 70e5c89e4eSSatish Balay . nsends - number of messages that are to be sent. 71e5c89e4eSSatish Balay . nrecvs - number of messages being received 72e5c89e4eSSatish Balay - ilengths - an array of integers of length sizeof(comm) 73e5c89e4eSSatish Balay a non zero ilengths[i] represent a message to i of length ilengths[i] 74e5c89e4eSSatish Balay 75e5c89e4eSSatish Balay 76e5c89e4eSSatish Balay Output Parameters: 77e5c89e4eSSatish Balay + onodes - list of node-ids from which messages are expected 78e5c89e4eSSatish Balay - olengths - corresponding message lengths 79e5c89e4eSSatish Balay 80e5c89e4eSSatish Balay Level: developer 81e5c89e4eSSatish Balay 82e5c89e4eSSatish Balay Notes: 83e5c89e4eSSatish Balay With this info, the correct MPI_Irecv() can be posted with the correct 84e5c89e4eSSatish Balay from-id, with a buffer with the right amount of memory required. 85e5c89e4eSSatish Balay 86e5c89e4eSSatish Balay The calling function deallocates the memory in onodes and olengths 87e5c89e4eSSatish Balay 88e5c89e4eSSatish Balay To determine nrecevs, one can use PetscGatherNumberOfMessages() 89e5c89e4eSSatish Balay 90e5c89e4eSSatish Balay .seealso: PetscGatherNumberOfMessages() 91e5c89e4eSSatish Balay @*/ 927087cfbeSBarry Smith PetscErrorCode PetscGatherMessageLengths(MPI_Comm comm,PetscMPIInt nsends,PetscMPIInt nrecvs,const PetscMPIInt ilengths[],PetscMPIInt **onodes,PetscMPIInt **olengths) 93e5c89e4eSSatish Balay { 94e5c89e4eSSatish Balay PetscErrorCode ierr; 95*6bfd7d4fSJunchao Zhang PetscMPIInt size,rank,tag,i,j; 960298fd71SBarry Smith MPI_Request *s_waits = NULL,*r_waits = NULL; 970298fd71SBarry Smith MPI_Status *w_status = NULL; 98e5c89e4eSSatish Balay 99e5c89e4eSSatish Balay PetscFunctionBegin; 100e5c89e4eSSatish Balay ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 101*6bfd7d4fSJunchao Zhang ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 102e5c89e4eSSatish Balay ierr = PetscCommGetNewTag(comm,&tag);CHKERRQ(ierr); 103e5c89e4eSSatish Balay 104e5c89e4eSSatish Balay /* cannot use PetscMalloc3() here because in the call to MPI_Waitall() they MUST be contiguous */ 105dcca6d9dSJed Brown ierr = PetscMalloc2(nrecvs+nsends,&r_waits,nrecvs+nsends,&w_status);CHKERRQ(ierr); 106e5c89e4eSSatish Balay s_waits = r_waits+nrecvs; 107e5c89e4eSSatish Balay 108e5c89e4eSSatish Balay /* Post the Irecv to get the message length-info */ 109785e854fSJed Brown ierr = PetscMalloc1(nrecvs,olengths);CHKERRQ(ierr); 110e5c89e4eSSatish Balay for (i=0; i<nrecvs; i++) { 111e5c89e4eSSatish Balay ierr = MPI_Irecv((*olengths)+i,1,MPI_INT,MPI_ANY_SOURCE,tag,comm,r_waits+i);CHKERRQ(ierr); 112e5c89e4eSSatish Balay } 113e5c89e4eSSatish Balay 114e5c89e4eSSatish Balay /* Post the Isends with the message length-info */ 115e5c89e4eSSatish Balay for (i=0,j=0; i<size; ++i) { 116e5c89e4eSSatish Balay if (ilengths[i]) { 117300a7f5bSBarry Smith ierr = MPI_Isend((void*)(ilengths+i),1,MPI_INT,i,tag,comm,s_waits+j);CHKERRQ(ierr); 118e5c89e4eSSatish Balay j++; 119e5c89e4eSSatish Balay } 120e5c89e4eSSatish Balay } 121e5c89e4eSSatish Balay 122e5c89e4eSSatish Balay /* Post waits on sends and receivs */ 123e5c89e4eSSatish Balay if (nrecvs+nsends) {ierr = MPI_Waitall(nrecvs+nsends,r_waits,w_status);CHKERRQ(ierr);} 124e5c89e4eSSatish Balay 125e5c89e4eSSatish Balay /* Pack up the received data */ 126785e854fSJed Brown ierr = PetscMalloc1(nrecvs,onodes);CHKERRQ(ierr); 127*6bfd7d4fSJunchao Zhang for (i=0; i<nrecvs; ++i) { 128*6bfd7d4fSJunchao Zhang (*onodes)[i] = w_status[i].MPI_SOURCE; 129*6bfd7d4fSJunchao Zhang #if defined(PETSC_HAVE_OMPI_MAJOR_VERSION) 130*6bfd7d4fSJunchao Zhang /* This line is a workaround for a bug in OpenMPI-2.1.1 distributed by Ubuntu-18.04.2 LTS. 131*6bfd7d4fSJunchao Zhang It happens in self-to-self MPI_Send/Recv using MPI_ANY_SOURCE for message matching. OpenMPI 132*6bfd7d4fSJunchao Zhang does not put correct value in recv buffer. See also 133*6bfd7d4fSJunchao Zhang https://lists.mcs.anl.gov/pipermail/petsc-dev/2019-July/024803.html 134*6bfd7d4fSJunchao Zhang https://www.mail-archive.com/users@lists.open-mpi.org//msg33383.html 135*6bfd7d4fSJunchao Zhang */ 136*6bfd7d4fSJunchao Zhang if (w_status[i].MPI_SOURCE == rank) (*olengths)[i] = ilengths[rank]; 137*6bfd7d4fSJunchao Zhang #endif 138*6bfd7d4fSJunchao Zhang } 139e5c89e4eSSatish Balay ierr = PetscFree2(r_waits,w_status);CHKERRQ(ierr); 140e5c89e4eSSatish Balay PetscFunctionReturn(0); 141e5c89e4eSSatish Balay } 142dd6ea824SBarry Smith 143e5c89e4eSSatish Balay /*@C 144e5c89e4eSSatish Balay PetscGatherMessageLengths2 - Computes info about messages that a MPI-node will receive, 145e5c89e4eSSatish Balay including (from-id,length) pairs for each message. Same functionality as PetscGatherMessageLengths() 146e5c89e4eSSatish Balay except it takes TWO ilenths and output TWO olengths. 147e5c89e4eSSatish Balay 148d083f849SBarry Smith Collective 149e5c89e4eSSatish Balay 150e5c89e4eSSatish Balay Input Parameters: 151e5c89e4eSSatish Balay + comm - Communicator 152e5c89e4eSSatish Balay . nsends - number of messages that are to be sent. 153e5c89e4eSSatish Balay . nrecvs - number of messages being received 154e5c89e4eSSatish Balay - ilengths1, ilengths2 - array of integers of length sizeof(comm) 155e5c89e4eSSatish Balay a non zero ilengths[i] represent a message to i of length ilengths[i] 156e5c89e4eSSatish Balay 157e5c89e4eSSatish Balay Output Parameters: 158e5c89e4eSSatish Balay + onodes - list of node-ids from which messages are expected 159e5c89e4eSSatish Balay - olengths1, olengths2 - corresponding message lengths 160e5c89e4eSSatish Balay 161e5c89e4eSSatish Balay Level: developer 162e5c89e4eSSatish Balay 163e5c89e4eSSatish Balay Notes: 164e5c89e4eSSatish Balay With this info, the correct MPI_Irecv() can be posted with the correct 165e5c89e4eSSatish Balay from-id, with a buffer with the right amount of memory required. 166e5c89e4eSSatish Balay 167e5c89e4eSSatish Balay The calling function deallocates the memory in onodes and olengths 168e5c89e4eSSatish Balay 169e5c89e4eSSatish Balay To determine nrecevs, one can use PetscGatherNumberOfMessages() 170e5c89e4eSSatish Balay 171e5c89e4eSSatish Balay .seealso: PetscGatherMessageLengths() and PetscGatherNumberOfMessages() 172e5c89e4eSSatish Balay @*/ 1737087cfbeSBarry Smith PetscErrorCode PetscGatherMessageLengths2(MPI_Comm comm,PetscMPIInt nsends,PetscMPIInt nrecvs,const PetscMPIInt ilengths1[],const PetscMPIInt ilengths2[],PetscMPIInt **onodes,PetscMPIInt **olengths1,PetscMPIInt **olengths2) 174e5c89e4eSSatish Balay { 175e5c89e4eSSatish Balay PetscErrorCode ierr; 1760298fd71SBarry Smith PetscMPIInt size,tag,i,j,*buf_s = NULL,*buf_r = NULL,*buf_j = NULL; 1770298fd71SBarry Smith MPI_Request *s_waits = NULL,*r_waits = NULL; 1780298fd71SBarry Smith MPI_Status *w_status = NULL; 179e5c89e4eSSatish Balay 180e5c89e4eSSatish Balay PetscFunctionBegin; 181e5c89e4eSSatish Balay ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 182e5c89e4eSSatish Balay ierr = PetscCommGetNewTag(comm,&tag);CHKERRQ(ierr); 183e5c89e4eSSatish Balay 1843bf92927SBarry Smith /* cannot use PetscMalloc5() because r_waits and s_waits must be contiguous for the call to MPI_Waitall() */ 185dcca6d9dSJed Brown ierr = PetscMalloc4(nrecvs+nsends,&r_waits,2*nrecvs,&buf_r,2*nsends,&buf_s,nrecvs+nsends,&w_status);CHKERRQ(ierr); 186e5c89e4eSSatish Balay s_waits = r_waits + nrecvs; 187e5c89e4eSSatish Balay 188e5c89e4eSSatish Balay /* Post the Irecv to get the message length-info */ 189854ce69bSBarry Smith ierr = PetscMalloc1(nrecvs+1,olengths1);CHKERRQ(ierr); 190854ce69bSBarry Smith ierr = PetscMalloc1(nrecvs+1,olengths2);CHKERRQ(ierr); 191e5c89e4eSSatish Balay for (i=0; i<nrecvs; i++) { 192e5c89e4eSSatish Balay buf_j = buf_r + (2*i); 193e5c89e4eSSatish Balay ierr = MPI_Irecv(buf_j,2,MPI_INT,MPI_ANY_SOURCE,tag,comm,r_waits+i);CHKERRQ(ierr); 194e5c89e4eSSatish Balay } 195e5c89e4eSSatish Balay 196e5c89e4eSSatish Balay /* Post the Isends with the message length-info */ 197e5c89e4eSSatish Balay for (i=0,j=0; i<size; ++i) { 198e5c89e4eSSatish Balay if (ilengths1[i]) { 199e5c89e4eSSatish Balay buf_j = buf_s + (2*j); 200e5c89e4eSSatish Balay buf_j[0] = *(ilengths1+i); 201e5c89e4eSSatish Balay buf_j[1] = *(ilengths2+i); 202e5c89e4eSSatish Balay ierr = MPI_Isend(buf_j,2,MPI_INT,i,tag,comm,s_waits+j);CHKERRQ(ierr); 203e5c89e4eSSatish Balay j++; 204e5c89e4eSSatish Balay } 205e5c89e4eSSatish Balay } 206f327f304SBarry Smith if (j != nsends) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"j %d not equal to expected number of sends %d\n",j,nsends); 207e5c89e4eSSatish Balay 208e5c89e4eSSatish Balay /* Post waits on sends and receivs */ 209e5c89e4eSSatish Balay if (nrecvs+nsends) {ierr = MPI_Waitall(nrecvs+nsends,r_waits,w_status);CHKERRQ(ierr);} 210e5c89e4eSSatish Balay 211e5c89e4eSSatish Balay 212e5c89e4eSSatish Balay /* Pack up the received data */ 213854ce69bSBarry Smith ierr = PetscMalloc1(nrecvs+1,onodes);CHKERRQ(ierr); 214e5c89e4eSSatish Balay for (i=0; i<nrecvs; ++i) { 215e5c89e4eSSatish Balay (*onodes)[i] = w_status[i].MPI_SOURCE; 216e5c89e4eSSatish Balay buf_j = buf_r + (2*i); 217e5c89e4eSSatish Balay (*olengths1)[i] = buf_j[0]; 218e5c89e4eSSatish Balay (*olengths2)[i] = buf_j[1]; 219e5c89e4eSSatish Balay } 220e5c89e4eSSatish Balay 221e5c89e4eSSatish Balay ierr = PetscFree4(r_waits,buf_r,buf_s,w_status);CHKERRQ(ierr); 222e5c89e4eSSatish Balay PetscFunctionReturn(0); 223e5c89e4eSSatish Balay } 224e5c89e4eSSatish Balay 225e5c89e4eSSatish Balay /* 226e5c89e4eSSatish Balay 227e5c89e4eSSatish Balay Allocate a bufffer sufficient to hold messages of size specified in olengths. 228e5c89e4eSSatish Balay And post Irecvs on these buffers using node info from onodes 229e5c89e4eSSatish Balay 230e5c89e4eSSatish Balay */ 2317087cfbeSBarry Smith PetscErrorCode PetscPostIrecvInt(MPI_Comm comm,PetscMPIInt tag,PetscMPIInt nrecvs,const PetscMPIInt onodes[],const PetscMPIInt olengths[],PetscInt ***rbuf,MPI_Request **r_waits) 232e5c89e4eSSatish Balay { 233e5c89e4eSSatish Balay PetscErrorCode ierr; 234c05d87d6SBarry Smith PetscInt **rbuf_t,i,len = 0; 235e5c89e4eSSatish Balay MPI_Request *r_waits_t; 236e5c89e4eSSatish Balay 237e5c89e4eSSatish Balay PetscFunctionBegin; 238e5c89e4eSSatish Balay /* compute memory required for recv buffers */ 239e5c89e4eSSatish Balay for (i=0; i<nrecvs; i++) len += olengths[i]; /* each message length */ 240e5c89e4eSSatish Balay 241e5c89e4eSSatish Balay /* allocate memory for recv buffers */ 242854ce69bSBarry Smith ierr = PetscMalloc1(nrecvs+1,&rbuf_t);CHKERRQ(ierr); 243785e854fSJed Brown ierr = PetscMalloc1(len,&rbuf_t[0]);CHKERRQ(ierr); 244e5c89e4eSSatish Balay for (i=1; i<nrecvs; ++i) rbuf_t[i] = rbuf_t[i-1] + olengths[i-1]; 245e5c89e4eSSatish Balay 246e5c89e4eSSatish Balay /* Post the receives */ 247785e854fSJed Brown ierr = PetscMalloc1(nrecvs,&r_waits_t);CHKERRQ(ierr); 248e5c89e4eSSatish Balay for (i=0; i<nrecvs; ++i) { 249e5c89e4eSSatish Balay ierr = MPI_Irecv(rbuf_t[i],olengths[i],MPIU_INT,onodes[i],tag,comm,r_waits_t+i);CHKERRQ(ierr); 250e5c89e4eSSatish Balay } 251e5c89e4eSSatish Balay 252e5c89e4eSSatish Balay *rbuf = rbuf_t; 253e5c89e4eSSatish Balay *r_waits = r_waits_t; 254e5c89e4eSSatish Balay PetscFunctionReturn(0); 255e5c89e4eSSatish Balay } 256e5c89e4eSSatish Balay 2577087cfbeSBarry Smith PetscErrorCode PetscPostIrecvScalar(MPI_Comm comm,PetscMPIInt tag,PetscMPIInt nrecvs,const PetscMPIInt onodes[],const PetscMPIInt olengths[],PetscScalar ***rbuf,MPI_Request **r_waits) 258e5c89e4eSSatish Balay { 259e5c89e4eSSatish Balay PetscErrorCode ierr; 260052f0c41SBarry Smith PetscMPIInt i; 261e5c89e4eSSatish Balay PetscScalar **rbuf_t; 262e5c89e4eSSatish Balay MPI_Request *r_waits_t; 263c05d87d6SBarry Smith PetscInt len = 0; 264e5c89e4eSSatish Balay 265fe28d99cSBarry Smith PetscFunctionBegin; 266e5c89e4eSSatish Balay /* compute memory required for recv buffers */ 267e5c89e4eSSatish Balay for (i=0; i<nrecvs; i++) len += olengths[i]; /* each message length */ 268e5c89e4eSSatish Balay 269e5c89e4eSSatish Balay /* allocate memory for recv buffers */ 270854ce69bSBarry Smith ierr = PetscMalloc1(nrecvs+1,&rbuf_t);CHKERRQ(ierr); 271785e854fSJed Brown ierr = PetscMalloc1(len,&rbuf_t[0]);CHKERRQ(ierr); 272e5c89e4eSSatish Balay for (i=1; i<nrecvs; ++i) rbuf_t[i] = rbuf_t[i-1] + olengths[i-1]; 273e5c89e4eSSatish Balay 274e5c89e4eSSatish Balay /* Post the receives */ 275785e854fSJed Brown ierr = PetscMalloc1(nrecvs,&r_waits_t);CHKERRQ(ierr); 276e5c89e4eSSatish Balay for (i=0; i<nrecvs; ++i) { 277e5c89e4eSSatish Balay ierr = MPI_Irecv(rbuf_t[i],olengths[i],MPIU_SCALAR,onodes[i],tag,comm,r_waits_t+i);CHKERRQ(ierr); 278e5c89e4eSSatish Balay } 279e5c89e4eSSatish Balay 280e5c89e4eSSatish Balay *rbuf = rbuf_t; 281e5c89e4eSSatish Balay *r_waits = r_waits_t; 282e5c89e4eSSatish Balay PetscFunctionReturn(0); 283e5c89e4eSSatish Balay } 284