#ifdef __CIVL_MPI__ #else #define __CIVL_MPI__ #include #include #include #include #include /* Completed definition for mpi-common.h */ struct MPI_Request{ int id; }; struct MPI_Comm { $comm p2p; // point-to-point communication $comm col; // collective communication $barrier barrier; __MPI_Sys_status__ status; }; /********************************** State *****************************************/ /* The number of times the MPI_Wtime function has been called */ int CMPI_time_count = 0; /************************** MPI LIB Implementations *******************************/ double MPI_Wtime() { double result = CMPI_time(CMPI_time_count); CMPI_time_count++; return result; } int MPI_Comm_size(MPI_Comm comm, int *size) { $assert comm.status == __INIT : "MPI_Comm_size() cannot be invoked without MPI_Init() being called before.\n"; *size = $comm_size(comm.p2p); return 0; } int MPI_Comm_rank(MPI_Comm comm, int *rank) { $assert comm.status == __INIT : "MPI_Comm_rank() cannot be invoked without MPI_Init() being called before.\n"; *rank = $comm_place(comm.p2p); return 0; } int MPI_Send(void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm) { $assert comm.status == __INIT : "MPI_Send() cannot be invoked without MPI_Init() being called before.\n"; return CMPI_Send(buf, count, datatype, dest, tag, comm.p2p); } int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status) { $assert comm.status == __INIT : "MPI_Recv() cannot be invoked without " "MPI_Init() being called before.\n"; return CMPI_Recv(buf, count, datatype, source, tag, comm.p2p, status); } int MPI_Get_count(MPI_Status *status, MPI_Datatype datatype, int *count) { *count = status->size/sizeofDatatype(datatype); return 0; } int MPI_Sendrecv(void *sendbuf, int sendcount, MPI_Datatype sendtype, int dest, int sendtag, void *recvbuf, int recvcount, MPI_Datatype recvtype, int source, int recvtag, MPI_Comm comm, MPI_Status *status) { $assert comm.status == __INIT : "MPI_Sendrecv() cannot be invoked " "without MPI_Init() being called before.\n"; // not correct for checking potential deadlock...rewrite: MPI_Send(sendbuf, sendcount, sendtype, dest, sendtag, comm); MPI_Recv(recvbuf, recvcount, recvtype, source, recvtag, comm, status); return 0; } /******************************** Collective ***********************************/ /* Broadcasts a message from root to everyone else. * Need to use a differnt comm. */ int MPI_Bcast(void *buf, int count, MPI_Datatype datatype, int root, MPI_Comm comm) { $assert comm.status == __INIT : "MPI_Bcast() cannot be invoked without MPI_Init() " "being called before.\n"; if ($comm_place(comm.col) == root) { int nprocs = $comm_size(comm.col); for (int i=0; i(root==rank) int real_recvcount; MPI_Status status; MPI_Recv(recvbuf, recvcount, recvtype, root, SCATTER_TAG, comm, &status); MPI_Get_count(&status, recvtype, &real_recvcount); $assert real_recvcount == recvcount : "MPI_Gather() asks for equality between" " the amount of data sent and the " "amount of data received."; } } /* MPI_Gatherv extends the functionality of MPI_Gather by allowing a varying count of data to be sent to root process, since recvcounts is now an array.*/ int MPI_Gatherv(const void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, const int recvcounts[], const int displs[], MPI_Datatype recvtype, int root, MPI_Comm comm){ int rank, nprocs; _Bool rootInPlace = $false; $assert comm.status == __INIT : "MPI_Gatherv() cannot be invoked without " "MPI_Init() being called before.\n"; rank = $comm_place(comm.col); nprocs = $comm_size(comm.col); if(sendbuf == MPI_IN_PLACE){ $assert root == rank: "Only root can replace 'sendbuf' with 'MPI_IN_PLACE'."; rootInPlace = $true; }else{ MPI_Send(sendbuf, sendcount, sendtype, root, GATHERV_TAG, comm); } //Root receive if(rank == root){ int real_recvcount; MPI_Status status; $assert sendtype == recvtype : "MPI_Gatherv() asks for equality " "between 'sendtype' and 'recvtype'."; for(int i=0; i