#include #include #include #include #define USE_DERIVED_DATATYPE 1 void PrintMPIError(int err, int my_rank) { int eclass, len; char estring[MPI_MAX_ERROR_STRING]; MPI_Error_class(err, &eclass); MPI_Error_string(err, estring, &len); printf("P%d Error %d: %s\n", my_rank, eclass, estring);fflush(stdout); } void MakePacket(int *buffer1, double *buffer2, int elems, int my_rank, MPI_Datatype *new_type) { int k, err, lblq[2]; MPI_Aint dspl[2]; MPI_Datatype type[2]; type[0] = MPI_INT ; lblq[0] = elems ; MPI_Get_address(buffer1, &dspl[0]); type[1] = MPI_DOUBLE; lblq[1] = elems ; MPI_Get_address(buffer2, &dspl[1]); for (k=1; k>=0; k--) dspl[k] -= dspl[0]; // Creation of the packet err = MPI_Type_create_struct (2, lblq, dspl, type, new_type); if (err != MPI_SUCCESS) PrintMPIError(err, my_rank); err = MPI_Type_commit(new_type); if (err != MPI_SUCCESS) PrintMPIError(err, my_rank); } int main(int argc, char* argv[]) { MPI_Init(&argc, &argv); // Size of the default communicator int size, my_rank; int tag, elems, use_derived, err; MPI_Datatype new_type; tag = 210; MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); MPI_Comm_size(MPI_COMM_WORLD, &size); char processor_name[MPI_MAX_PROCESSOR_NAME]; int name_len; MPI_Get_processor_name(processor_name, &name_len); use_derived = USE_DERIVED_DATATYPE; // Get my rank and do the corresponding job switch(my_rank) { case 0: { printf("P%d at node %s\n", my_rank, processor_name); elems = 752; int *buffer1 = (int*) malloc(elems * sizeof(int)); double *buffer2 = (double*) malloc(elems * sizeof(double)); if(use_derived) { MakePacket(buffer1, buffer2, elems, my_rank, &new_type); err = MPI_Send(buffer1, 1, new_type, 2, tag, MPI_COMM_WORLD); if (err != MPI_SUCCESS) PrintMPIError(err, my_rank); sleep(1); err = MPI_Send(buffer1, 1, new_type, 1, tag, MPI_COMM_WORLD); if (err != MPI_SUCCESS) PrintMPIError(err, my_rank); err = MPI_Type_free(&new_type); if (err != MPI_SUCCESS) PrintMPIError(err, my_rank); } else { MPI_Send(buffer1, elems, MPI_INT, 2, tag, MPI_COMM_WORLD); sleep(1); MPI_Send(buffer1, elems, MPI_INT, 1, tag, MPI_COMM_WORLD); } break; } case 1: // This rank is in a different machine than rank 0 sleep(2); case 2: // This rank is in the same machine than rank 0 { printf("P%d at node %s\n", my_rank, processor_name); // Retrieve information about the incoming message MPI_Status status; err = MPI_Probe(0, tag, MPI_COMM_WORLD, &status); if (err != MPI_SUCCESS) PrintMPIError(err, my_rank); // Get the number of elements in the message probed int count, tam_int, tam_double; if(use_derived) { err = MPI_Get_count(&status, MPI_BYTE, &count); if (err != MPI_SUCCESS) PrintMPIError(err, my_rank); err = MPI_Type_size(MPI_INT, &tam_int); if (err != MPI_SUCCESS) PrintMPIError(err, my_rank); err = MPI_Type_size(MPI_DOUBLE, &tam_double); if (err != MPI_SUCCESS) PrintMPIError(err, my_rank); elems = count / (tam_int + tam_double); // elems = 752; } else { MPI_Get_count(&status, MPI_INT, &count); elems=count; } printf("P%d: Total expected counts=%d elems=%d\n", my_rank, count, elems); // Allocate the buffer now that we know how many elements there are int* buffer1 = (int*) malloc(elems * sizeof(int)); double *buffer2 = (double*) malloc(elems * sizeof(double)); // Receive the message if(use_derived) { MakePacket(buffer1, buffer2, elems, my_rank, &new_type); err = MPI_Recv(buffer1, 1, new_type, 0, tag, MPI_COMM_WORLD, &status); if (err != MPI_SUCCESS) PrintMPIError(err, my_rank); err = MPI_Type_free(&new_type); if (err != MPI_SUCCESS) PrintMPIError(err, my_rank); } else { MPI_Recv(buffer1, elems, MPI_INT, 0, tag, MPI_COMM_WORLD, &status); } printf("P%d: received message with %d elements\n", my_rank, elems); break; } default: { break; } } MPI_Finalize(); return EXIT_SUCCESS; }