Nature Language: funnelledPingPing:Two processes send a message to each other using the MPI_Isend, MPI_Recv and MPI_Wait routines. Inter-process communication takes place inside the OpenMP parallel region.
  
CPP: int funnelledPingping(int totalReps, int dataSize){\n\tint repIter, i;\n\tint destRank;\n\n    /* set destRank to ID of other process */\n    if (myMPIRank == pingRankA){\n    \tdestRank = pingRankB;\n    }\n    else if (myMPIRank == pingRankB){\n    \tdestRank = pingRankA;\n    }\n\n\t/* Open the parallel region */\n#pragma omp parallel default(none) \\\n\tprivate(i, repIter) \\\n\tshared(dataSize,sizeofBuffer,pingSendBuf,globalIDarray) \\\n\tshared(pingRecvBuf,finalRecvBuf,status,requestID) \\\n\tshared(destRank,comm,myMPIRank,pingRankA,pingRankB,totalReps)\n\n\tfor (repIter = 0; repIter < totalReps; repIter++){\n\n\n\t\tif (myMPIRank == pingRankA || myMPIRank == pingRankB){\n\n\t\t\t/* Each thread writes its globalID to its part of\n\t\t\t * pingSendBuf.\n\t\t\t */\n#pragma omp for schedule(static,dataSize)\n\t\t\tfor (i=0; i<sizeofBuffer; i++){\n\t\t\t\tpingSendBuf[i] = globalIDarray[myThreadID];\n\t\t\t}\n/* Implicit barrier here takes care of necessary synchronisation */\n\n#pragma omp master\n\t\t\t{\n\t\t\t/* Master thread starts send of buffer */\n\t\t\tMPI_Isend(pingSendBuf, sizeofBuffer, MPI_INT, destRank, \\\n\t\t\t\t\tTAG, comm, &requestID);\n\n\t\t\t/* then waits for message from other process */\n\t\t\tMPI_Recv(pingRecvBuf, sizeofBuffer, MPI_INT, destRank, \\\n\t\t\t\t\tTAG, comm, &status);\n\n\t\t\t/* Master thread then completes send using an MPI_Wait */\n\t\t\tMPI_Wait(&requestID, &status);\n\t\t\t}\n\n/* Barrier needed to ensure master thread has completed transfer */\n#pragma omp barrier\n\n\t\t\t/* Each thread reads its part of the received buffer */\n#pragma omp for schedule(static,dataSize)\n\t\t\tfor (i=0; i<sizeofBuffer; i++){\n\t\t\t\tfinalRecvBuf[i] = pingRecvBuf[i];\n\t\t\t}\n\t\t}\n\t}\n\n\treturn 0;\n}
  
Fortran: SUBROUTINE funnelledPingping(totalReps, dataSize)\n integer, intent(in) :: totalReps, dataSize\n integer :: repIter, i\n integer :: destRank\n\n !set destRank to ID of other process\n IF (myMPIRank == pingRankA) THEN\n destRank = pingRankB\n ELSE IF (myMPIRank == pingRankB) THEN\n destRank = pingRankA\n END IF\n\n !Open the parallel region\n!$OMP PARALLEL DEFAULT(NONE), &\n!$OMP PRIVATE(i,repIter), &\n!$OMP SHARED(dataSize,sizeofBuffer,pingSendBuf,globalIDarray), &\n!$OMP SHARED(pingRecvBuf,finalRecvBuf,status,requestID,ierr), &\n!$OMP SHARED(destRank,comm,myMPIRank,pingRankA,pingRankB,totalReps)\n\n DO repIter = 1, totalReps !loop totalRep times\n \n IF(myMPIRank == pingRankA .or. myMPIRank == pingRankB) THEN\n \n !Each threads write its globalID to its part of\n !pingSendBuf.\n!$OMP DO SCHEDULE(STATIC,dataSize)\n DO i = 1,sizeofBuffer\n pingSendBuf(i) = globalIDarray(myThreadID)\n END DO\n!$OMP END DO\n!Implicit barrier here takes care of necessary synchronisation.\n \n!$OMP MASTER\n !Master thread starts send of buffer\n CALL MPI_Isend(pingSendBuf, sizeofBuffer, MPI_INTEGER,&\n destRank, tag, comm, requestID, ierr)\n !then waits for message from other process.\n CALL MPI_Recv(pingRecvBuf, sizeofBuffer, MPI_INTEGER,&\n destRank, tag, comm, status, ierr)\n !Master thread then completes send using MPI_Wait.\n CALL MPI_Wait(requestID, status, ierr)\n!$OMP END MASTER\n\n!Barrier needed to ensure master thread has completed transfer.\n!$OMP BARRIER\n \n !Each thread reads its part of the received buffer\n!$OMP DO SCHEDULE(STATIC,dataSize)\n DO i = 1,sizeofBuffer\n finalRecvBuf(i) = pingRecvBuf(i)\n END DO\n!$OMP END DO\n\n END IF\n\n END DO !End repetitions loop\n!$OMP END PARALLEL\n\n END SUBROUTINE funnelledPingping
  