Nature Language: multiplePingping:With this algorithm multiple threads take place in the communication and computation. Each thread sends its portion of the pingSendBuf to the other process using MPI_Isend/ MPI_Recv/ MPI_Wait routines.
  
CPP: int multiplePingping(int totalReps, int dataSize){\n\tint repIter, i;\n\tint destRank;\n\tint lBound;\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    /* Open parallel region */\n#pragma omp parallel default(none) \\\n\tprivate(i,lBound,requestID,status,repIter) \\\n\tshared(pingSendBuf,pingRecvBuf,finalRecvBuf,sizeofBuffer) \\\n\tshared(destRank,myMPIRank,pingRankA,pingRankB,totalReps) \\\n\tshared(dataSize,globalIDarray,comm)\n    {\n    for (repIter = 0; repIter < totalReps; repIter++){\n\n    \tif (myMPIRank == pingRankA || myMPIRank == pingRankB){\n\n    \t\t/* Calculate the lower bound of each threads\n    \t\t * portion of the data arrays.\n    \t\t */\n    \t\tlBound = (myThreadID * dataSize);\n\n    \t\t/* Each thread writes to its part of pingSendBuf */\n#pragma omp for nowait schedule(static,dataSize)\n    \t\tfor (i=0; i<sizeofBuffer; i++){\n    \t\t\tpingSendBuf[i] = globalIDarray[myThreadID];\n    \t\t}\n\n    \t\t/* Each thread starts send of dataSize items of\n    \t\t * pingSendBuf to process with rank = destRank.\n    \t\t */\n    \t\tMPI_Isend(&pingSendBuf[lBound], dataSize, MPI_INT, destRank, \\\n    \t\t\t\tmyThreadID, comm, &requestID);\n\n    \t\t/* Thread then waits for message from destRank with\n    \t\t * tag equal to it thread id.\n    \t\t */\n    \t\tMPI_Recv(&pingRecvBuf[lBound], dataSize, MPI_INT, destRank, \\\n    \t\t\t\tmyThreadID, comm, &status);\n\n    \t\t/* Thread completes send using MPI_Wait */\n    \t\tMPI_Wait(&requestID, &status);\n\n    \t\t/* Each thread reads its part of received buffer. */\n#pragma omp for nowait schedule(static,dataSize)\n    \t\tfor (i=0; i<sizeofBuffer; i++){\n    \t\t\tfinalRecvBuf[i] = pingRecvBuf[i];\n    \t\t}\n    \t}\n    }\n    }\n\n    return 0;\n}
  
Fortran: SUBROUTINE multiplePingping(totalReps, dataSize)\n integer, intent(in) :: totalReps, dataSize\n integer :: repIter, i\n integer :: destRank\n integer :: lBound, uBound\n\n !set destRank to be 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 parallel region\n!$OMP PARALLEL DEFAULT(NONE), &\n!$OMP PRIVATE(i,lBound,uBound,requestID,status,ierr,repIter), &\n!$OMP SHARED(pingSendBuf,pingRecvBuf,finalRecvBuf,sizeofBuffer),&\n!$OMP SHARED(destRank,myMPIRank,pingRankA,pingRankB,totalReps),&\n!$OMP SHARED(dataSize,globalIDarray,comm)\n\n DO repIter = 1,totalReps !Loop totalReps times\n IF(myMPIRank == pingRankA .or. myMPIRank == pingRankB) THEN\n \n !Calculate lower and upper bound of each threads \n !portion of the data arrays\n lBound = ((myThreadID-1)* dataSize) + 1\n uBound = (myThreadID * dataSize)\n \n !Each thread writes to its part of pingSendBuf\n!$OMP DO SCHEDULE(STATIC,dataSize)\n DO i = 1,sizeofBuffer\n pingSendBuf(i) = globalIDarray(myThreadID)\n END DO\n!$OMP END DO NOWAIT\n\n !Each thread starts send of dataSize items of \n !pingSendBuf to process with rank = destRank\n CALL MPI_Isend(pingSendBuf(lBound:uBound), dataSize,&\n MPI_INTEGER, destRank, myThreadID, comm,&\n requestID, ierr)\n !Thread then waits for message from destRank with \n !tag equal to its thread id.\n CALL MPI_Recv(pingRecvBuf(lBound:uBound), dataSize,&\n MPI_INTEGER, destRank, myThreadID, comm,&\n status, ierr)\n !Thread completes send using MPI_Wait\n CALL MPI_Wait(requestID, status, ierr)\n\n !Each thread reads its part of 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 NOWAIT\n\n END IF\n\n END DO !End repetitions loop\n!$OMP END PARALLEL\n\n END SUBROUTINE multiplePingping
  