The previous example is tailored specifically for send-side partitioning using threads.
This is an example where parallel task producers produce
input to part of an overall buffer; they complete in any order and contribute
to the overall buffer.
Example
Parallel task producers for partitioned communication using threads.
#include <stdlib.h> #include "mpi.h" #define NUM_THREADS 8 #define NUM_TASKS 64 #define PARTITIONS NUM_TASKS #define PARTLENGTH 16 #define MESSAGE_LENGTH PARTITIONS*PARTLENGTH int main(int argc, char *argv[]) /* send-side partitioning */ { double message[MESSAGE_LENGTH]; int send_partitions = PARTITIONS, send_partlength = PARTLENGTH, recv_partitions = 1, recv_partlength = PARTITIONS*PARTLENGTH; int count = 1, source = 0, dest = 1, tag = 1, flag = 0; int myrank; int provided; MPI_Request request; MPI_Info info = MPI_INFO_NULL; MPI_Datatype send_type; MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided); if (provided < MPI_THREAD_MULTIPLE) MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); MPI_Comm_rank(MPI_COMM_WORLD, &myrank); MPI_Type_contiguous(send_partlength, MPI_DOUBLE, &send_type); MPI_Type_commit(&send_type); if (myrank == 0) { MPI_Psend_init(message, send_partitions, count, send_type, dest, tag, MPI_COMM_WORLD, info, &request); MPI_Start(&request); #pragma omp parallel shared(request) num_threads(NUM_THREADS) { #pragma omp single { /* single thread creates 64 tasks to be executed by 8 threads */ for (int partition_num=0;partition_num<NUM_TASKS;partition_num++) { #pragma omp task firstprivate(partition_num) { /* compute and fill partition #partition_num, then mark ready: */ /* buffer is filled in arbitrary order from each task */ MPI_Pready(partition_num, request); } /*end task*/ } /* end for */ } /* end single */ } /* end parallel */ while(!flag) { /* Do useful work */ MPI_Test(&request, &flag, MPI_STATUS_IGNORE); /* Do useful work */ } MPI_Request_free(&request); } else if (myrank == 1) { MPI_Precv_init(message, recv_partitions, recv_partlength, MPI_DOUBLE, source, tag, MPI_COMM_WORLD, info, &request); MPI_Start(&request); while(!flag) { /* Do useful work */ MPI_Test(&request, &flag, MPI_STATUS_IGNORE); /* Do useful work */ } MPI_Request_free(&request); } MPI_Finalize(); return 0; }