#include "mpi.h" #include "stdlib.h" #include "string.h" #include "assert.h" #include "reduceScatter_optimized.h" $input int NP; // nprocs $input int N; // size of input data per proc $input int NB; // upper bound of the size of input data per proc $assume(0 < N && N < NB); $input double DATA[N * NP]; // arbitrary input data, N per proc $input int VEC[NP]; // arbitrary recv counts $assume($forall (int i : 0 .. NP-1) VEC[i] > 0); #ifdef _CHECK_MAX #define MPIOP MPI_MAX #else #define MPIOP MPI_SUM #endif int main() { double * sendbuf, * recvbuf; int rank, size; MPI_Init(NULL, NULL); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); // NP is nprocs: $assume(NP == size); int recvcnts[size]; int total_counts = 0; int my_oft = 0; // initializes recv counts // computes the total count for completing the assumption over the recv counts // computes my offset for (int i = 0; i < size; i++) { recvcnts[i] = VEC[i]; total_counts += VEC[i]; if (i < rank) my_oft += recvcnts[i]; } // assumption over the recv count: $assume(total_counts == N); sendbuf = (double*)malloc(sizeof(double) * N); recvbuf = (double*)malloc(sizeof(double) * recvcnts[rank]); memcpy(sendbuf, DATA + rank * N, sizeof(double) * N); reduce_scatter_double(sendbuf, recvbuf, recvcnts, MPIOP, MPI_COMM_WORLD); // assertions: #ifdef _CHECK_MAX for (int i = 0; i < recvcnts[rank]; i++) assert(recvbuf[i] >= sendbuf[my_oft + i]); #else for (int i = 0; i < recvcnts[rank]; i++) { double expect = 0; for (int j = 0; j < size; j++) expect += DATA[j * N + my_oft + i]; assert(recvbuf[i] == expect); } #endif free(sendbuf); free(recvbuf); MPI_Finalize(); }