Nature Language: funnelledMultiPingpong:All MPI processes in crossComm = pingNode sends a single fixed length message to the neighbouring process in crossComm = pongNode. The neighbouring processes then sends the message back to the first process. All communication takes place within the OpenMP parallel region for this benchmark.
  
CPP: int funnelledMultiPingpong(int totalReps, int dataSize){\n    int repIter, i;\n    #pragma omp parallel default(none) \\\n        private(i,repIter) \\\n        shared(pingNode,pongNode,pingSendBuf,pingRecvBuf) \\\n        shared(pongSendBuf,pongRecvBuf,finalRecvBuf,sizeofBuffer) \\\n        shared(dataSize,globalIDarray,crossComm,status) \\\n        shared(totalReps,myMPIRank,crossCommRank)\n    {\n        for (repIter = 1; repIter <= totalReps; repIter++){\n            if (crossCommRank == pingNode){\n                #pragma omp for schedule(static,dataSize)\n                for (i=0; i<sizeofBuffer; i++){\n                    pingSendBuf[i] = globalIDarray[myThreadID];\n                }\n                #pragma omp master\n                {\n                    MPI_Send(pingSendBuf, sizeofBuffer, MPI_INT, pongNode, TAG, crossComm);\n                    MPI_Recv(pongRecvBuf, sizeofBuffer, MPI_INT, pongNode, TAG, \\\n                             crossComm, &status);\n                }\n                #pragma omp barrier\n\n                #pragma omp for schedule(static,dataSize)\n                for (i=0; i<sizeofBuffer; i++){\n                    finalRecvBuf[i] = pongRecvBuf[i];\n                }\n            } else if (crossCommRank == pongNode){\n                #pragma omp master\n                {\n                    MPI_Recv(pingRecvBuf, sizeofBuffer, MPI_INT, pingNode,\\\n                             TAG, crossComm, &status);\n                }\n                #pragma omp barrier\n\n                #pragma omp for schedule(static,dataSize)\n                for (i=0; i<sizeofBuffer; i++){\n                    pongSendBuf[i] = pingRecvBuf[i];\n                }\n\n                #pragma omp master\n                {\n                    MPI_Send(pongSendBuf, sizeofBuffer, MPI_INT, pingNode, TAG, crossComm);\n                }\n            }\n        }\n    }\n    return 0;\n}",
  
Fortran: SUBROUTINE funnelledMultiPingpong(totalReps, dataSize)\n integer, intent(in) :: totalReps, dataSize\n integer :: repIter, i\n\n !Open parallel region for threads\n!$OMP PARALLEL DEFAULT(NONE), &\n!$OMP PRIVATE(i,repIter), &\n!$OMP SHARED(pingNode,pongNode,pingSendBuf,pingRecvBuf),&\n!$OMP SHARED(pongSendBuf,pongRecvBuf,finalRecvBuf,sizeofBuffer),&\n!$OMP SHARED(dataSize,globalIDarray,crossComm,ierr,status), &\n!$OMP SHARED(totalReps,myMPIRank,crossCommRank)\n\n DO repIter = 1, totalReps !loop totalRep times\n \n !All threads under each MPI process with\n !crossCommRank = pingNode write to pingSendBuf array\n !using a PARALLEL DO directive.\n IF (crossCommRank == pingNode) THEN\n\n!$OMP DO SCHEDULE(STATIC,dataSize)\n\n DO i = 1, sizeofBuffer\n pingSendBuf(i) = globalIDarray(myThreadID)\n END DO\n\n!$OMP END DO\n!Implicit barrier at end of DO takes care of synchronisation here\n \n !Master thread under each pingNode process sends \n !buffer to corresponding MPI process in pongNode\n !using the crossComm.\n!$OMP MASTER\n CALL MPI_Send(pingSendBuf, sizeofBuffer, MPI_INTEGER,&\n pongNode, tag, crossComm, ierr)\n\n !The Master thread then waits for a message from the\n !pong process.\n CALL MPI_Recv(pongRecvBuf, sizeofBuffer, MPI_INTEGER,&\n pongNode, tag, crossComm, status, ierr)\n!$OMP END MASTER\n\n!Barrier needed to wait for master thread to complete MPI_Recv\n!$OMP BARRIER\n\n !Each thread then reads its part of the received buffer.\n!$OMP DO SCHEDULE(STATIC,dataSize)\n\n DO i = 1, sizeofBuffer\n finalRecvBuf(i) = pongRecvBuf(i)\n END DO\n\n!$OMP END DO\n \n ELSE IF (crossCommRank == pongNode) THEN\n\n !Master thread under each pongNode process receives\n !the message from the pingNode processes.\n!$OMP MASTER \n CALL MPI_Recv(pingRecvBuf, sizeofBuffer, MPI_INTEGER,&\n pingNode, tag, crossComm, status, ierr)\n!$OMP END MASTER\n\n!Barrier needed to wait on master thread\n!$OMP BARRIER\n\n !Each thread reads its part of the received buffer.\n!$OMP DO SCHEDULE(STATIC,dataSize)\n\n DO i = 1, sizeofBuffer\n pongSendBuf(i) = pingRecvBuf(i)\n END DO\n\n!$OMP END DO\n!Implicit barrier at end of DO\n\n !Master threads sends pongSendBuf to processes\n !with crossCommRank = pingNode.\n!$OMP MASTER\n CALL MPI_Send(pongSendBuf, sizeofBuffer, MPI_INTEGER,&\n pingNode, tag, crossComm, ierr)\n!$OMP END MASTER\n\n END IF\n END DO !End repetitions loop\n\n!$OMP END PARALLEL\n\n END SUBROUTINE funnelledMultiPingpong
  