Nature Language: funnelledMultiPingping:All processes with rank of pingNodeA or pingNodeB in crossComm send a message to each other. Inter-process communication takes place inside the OpenMP parallel region by the master thread.
  
CPP: int funnelledMultiPingping(int totalReps, int dataSize){\n    int repIter, i;\n    int destRank;\n\n    if (crossCommRank == pingNodeA){\n        destRank = pingNodeB;\n    } \n    else if (crossCommRank == pingNodeB){\n        destRank = pingNodeA;\n    }\n\n    #pragma omp parallel default(none)                \\\n    private(i,repIter)                                \\\n    shared(dataSize,sizeofBuffer,pingSendBuf,globalIDarray)    \\\n    shared(pingRecvBuf,finalRecvBuf,status,requestID,destRank)    \\\n    shared(crossComm,crossCommRank,pingNodeA,pingNodeB,totalReps)\n    {\n        for (repIter = 1; repIter <= totalReps; repIter++){\n            if (crossCommRank == pingNodeA || crossCommRank == pingNodeB){\n\n                #pragma omp for schedule(static,dataSize)\n                for (i=0; i<sizeofBuffer; i++){\n                    pingSendBuf[i] = globalIDarray[myThreadID];\n                }\n\n                #pragma omp master \n                {\n                    MPI_Isend(pingSendBuf, sizeofBuffer, MPI_INT, \\\n                    destRank, TAG, crossComm, &requestID);\n                    MPI_Recv(pingRecvBuf, sizeofBuffer, MPI_INT, \\\n                    destRank, TAG, crossComm, &status);\n                    MPI_Wait(&requestID, &status);\n                }\n\n                #pragma omp barrier\n\n                #pragma omp for schedule(static,dataSize)\n                for (i=0; i<sizeofBuffer; i++){\n                    finalRecvBuf[i] = pingRecvBuf[i];\n                }\n            }\n        } /* End repetitions loop */\n    } /* End parallel region */\n\n    return 0;\n}",
  
Fortran: SUBROUTINE funnelledMultiPingping(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 (crossCommRank == pingNodeA) THEN\n destRank = pingNodeB\n ELSE IF (crossCommRank == pingNodeB) THEN\n destRank = pingNodeA\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,crossComm,crossCommRank,pingNodeA), &\n!$OMP SHARED(pingNodeB,totalReps)\n\n DO repIter = 1, totalReps !loop totalRep times\n\n IF (crossCommRank == pingNodeA .or. &\n crossCommRank == pingNodeB) THEN\n \n !Each thread writes its globalID to its part \n !of pingSendBuf with a OMP DO.\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 of each process starts send.\n CALL MPI_Isend(pingSendBuf, sizeofBuffer, MPI_INTEGER, &\n destRank, tag, crossComm, requestID, ierr)\n\n !Processes then wait for message.\n CALL MPI_Recv(pingRecvBuf, sizeofBuffer, MPI_INTEGER, &\n destRank, tag, crossComm, status, ierr)\n\n !Finish the send operation with an MPI_Wait\n CALL MPI_Wait(requestID, status, ierr)\n!$OMP END MASTER\n\n!Barrier 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 funnelledMultiPingping
  