diff --git a/hpc_mpi/src/bin_reduce.c b/hpc_mpi/src/bin_reduce.c index 45a6093..c420b2c 100644 --- a/hpc_mpi/src/bin_reduce.c +++ b/hpc_mpi/src/bin_reduce.c @@ -11,7 +11,7 @@ #include "bin_reduce.h" int int_log2(int x) { - int r; + int r=0; while (x >>= 1) { r++; } @@ -46,7 +46,6 @@ int Bin_Reduce(const void *sendbuf, void *recvbuf, int count, if (r == root) { recv_right = recvbuf; } else { - //printf("%i gets some memory\n", r); MPI_Alloc_mem(count * size, MPI_INFO_NULL, &recv_right); } @@ -60,21 +59,14 @@ int Bin_Reduce(const void *sendbuf, void *recvbuf, int count, max_nodes /= 2; } - //printf("%i: %i\n", r, parent); - if (depth != tree_depth && r + 1 < p) { MPI_Alloc_mem(count * size, MPI_INFO_NULL, &recv_left); MPI_Recv(recv_left, count, datatype, r + 1, 0, comm, &status); - //printf("%i received %i from %i\n", r, *((int*) recv_left), r + 1); - printf("%i: %i + %i\n", r, ((int *)sendbuf)[0], ((int *)recv_left)[0]); MPI_Reduce_local(sendbuf, recv_left, count, datatype, op); - //printf("right child of %i: %i\n", r, r + max_nodes + 1); + if (r + max_nodes + 1 < p) { MPI_Recv(recv_right, count, datatype, r + max_nodes + 1, 0, comm, &status); - //printf("%i received %i from %i\n", r, *((int*) recv_right), - // r + max_nodes + 1); - printf("%i: %i + %i\n", r, ((int *)recv_left)[0], ((int *)recv_right)[0]); MPI_Reduce_local(recv_left, recv_right, count, datatype, op); } else { memcpy(recv_right, recv_left, count * size); @@ -86,7 +78,6 @@ int Bin_Reduce(const void *sendbuf, void *recvbuf, int count, } if (r != root) { - //printf("%i sends %i to %i\n", r, *((int*) recv_right), parent); MPI_Send(recv_right, count, datatype, parent, 0, comm); MPI_Free_mem(recv_right); } diff --git a/hpc_mpi/src/binom_reduce.c b/hpc_mpi/src/binom_reduce.c index f4543df..e96db38 100644 --- a/hpc_mpi/src/binom_reduce.c +++ b/hpc_mpi/src/binom_reduce.c @@ -10,8 +10,21 @@ #include #include "binom_reduce.h" +void swap(void **a, void **b) { + void *temp; + temp = *a; + *a = *b; + *b = temp; +} + int Binom_Reduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm) { + + if (root != 0) { + fprintf(stderr, "Sorry, root!=0 not allowed"); + return -1; + } + int r, p, size; MPI_Status status; void *recv; @@ -22,29 +35,27 @@ int Binom_Reduce(const void *sendbuf, void *recvbuf, int count, MPI_Type_size(datatype, &size); MPI_Alloc_mem(count * size, MPI_INFO_NULL, &recv); - if (r != root) { - MPI_Alloc_mem(count * size, MPI_INFO_NULL, &reduced); - } else { - reduced = recvbuf; - } + MPI_Alloc_mem(count * size, MPI_INFO_NULL, &reduced); + memcpy(reduced, sendbuf, count * size); int i = 1; while ((r + i) % (2 * i) != 0 && i < p) { if (r + i < p) { MPI_Recv(recv, count, datatype, r + i, i, comm, &status); - printf("%i: %i + %i\n", r, ((int *)reduced)[0], ((int *)recv)[0]); MPI_Reduce_local(reduced, recv, count, datatype, op); - memcpy(reduced, recv, count*size); + swap(&reduced, &recv); } i <<= 1; } if (r != root) { MPI_Send(reduced, count, datatype, r - i, i, comm); - MPI_Free_mem(reduced); + } else { + memcpy(recvbuf, reduced, count * size); } + MPI_Free_mem(reduced); MPI_Free_mem(recv); return 0; diff --git a/hpc_mpi/src/fib_reduce.c b/hpc_mpi/src/fib_reduce.c index 12286d8..b1c69cf 100644 --- a/hpc_mpi/src/fib_reduce.c +++ b/hpc_mpi/src/fib_reduce.c @@ -26,17 +26,16 @@ int Fib_Reduce(const void *sendbuf, void *recvbuf, int count, MPI_Type_size(datatype, &size); int temp; - int fibm1 = 1; + int right = 1; int fib = 1; while (fib - 1 < p) { temp = fib; - fib += fibm1; - fibm1 = temp; + fib += right; + right = temp; } - int right = fibm1; - int left = fib - fibm1; + int left = fib - right; int i = 0; int parent = 0; @@ -64,12 +63,10 @@ int Fib_Reduce(const void *sendbuf, void *recvbuf, int count, void *recv_left; MPI_Alloc_mem(count * size, MPI_INFO_NULL, &recv_left); MPI_Recv(recv_left, count, datatype, r + 1, 0, comm, &status); - printf("%i: %i + %i\n", r, ((int *)sendbuf)[0], ((int *)recv_left)[0]); MPI_Reduce_local(sendbuf, recv_left, count, datatype, op); if (left - 1 > 0 && r + left < p) { MPI_Recv(recv_right, count, datatype, r + left, 0, comm, &status); - printf("%i: %i + %i\n", r, ((int *)recv_left)[0], ((int *)recv_right)[0]); MPI_Reduce_local(recv_left, recv_right, count, datatype, op); } else { memcpy(recv_right, recv_left, count * size); diff --git a/hpc_mpi/src/hpc_mpi.c b/hpc_mpi/src/hpc_mpi.c index 626c10a..c0d2e7d 100644 --- a/hpc_mpi/src/hpc_mpi.c +++ b/hpc_mpi/src/hpc_mpi.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "bin_reduce.h" #include "binom_reduce.h" #include "fib_reduce.h" @@ -27,8 +28,9 @@ void usage(char *progname, int rank) { } void fill(int *a, int count, int rank) { + srand(time(NULL) + rank); for (int i = 0; i < count; i++) { - a[i] = rank + i; + a[i] = rand(); } } @@ -92,7 +94,7 @@ int main(int argc, char* argv[]) { case '8': op = MPI_LXOR; break; - case '9': + default: op = MPI_BXOR; break; } @@ -158,14 +160,8 @@ int main(int argc, char* argv[]) { MPI_Alloc_mem(size * sizeof(int), MPI_INFO_NULL, &rbinom); MPI_Reduce(a, red, size, MPI_INT, op, 0, MPI_COMM_WORLD); - if(r==0) - printf("fib:\n"); Fib_Reduce(a, rfib, size, MPI_INT, op, 0, MPI_COMM_WORLD); - if(r==0) - printf("bin:\n"); Bin_Reduce(a, rbin, size, MPI_INT, op, 0, MPI_COMM_WORLD); - if(r==0) - printf("binom:\n"); Binom_Reduce(a, rbinom, size, MPI_INT, op, 0, MPI_COMM_WORLD); if (r == 0) { diff --git a/reduce/Makefile b/reduce/Makefile new file mode 100644 index 0000000..8acaa71 --- /dev/null +++ b/reduce/Makefile @@ -0,0 +1,7 @@ +all: reduce + +reduce: hpc_mpi.c binom_reduce.c fib_reduce.c bin_reduce.c + mpicc -Wall -Wextra -O3 -o reduce bin_reduce.c fib_reduce.c binom_reduce.c hpc_mpi.c + +clean: + rm reduce diff --git a/reduce/bin_reduce.c b/reduce/bin_reduce.c new file mode 100644 index 0000000..c420b2c --- /dev/null +++ b/reduce/bin_reduce.c @@ -0,0 +1,86 @@ +/* + * bin_reduce.c + * + * Created on: 16 Jun 2016 + * Author: johannes + */ + +#include +#include +#include +#include "bin_reduce.h" + +int int_log2(int x) { + int r=0; + while (x >>= 1) { + r++; + } + return r; +} + +int Bin_Reduce(const void *sendbuf, void *recvbuf, int count, + MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm) { + if (root != 0) { + fprintf(stderr, "Sorry, root!=0 not allowed"); + return -1; + } + + int r, p, size; + MPI_Status status; + + MPI_Comm_rank(comm, &r); + MPI_Comm_size(comm, &p); + MPI_Type_size(datatype, &size); + + int tree_depth = int_log2(p) + 1; + int i = 0; + int depth; + int parent = 0; + + // maximum possible number of nodes in a subtree with current depth + int max_nodes = ((1 << tree_depth) - 1) / 2; + + void *recv_left; + void *recv_right; + + if (r == root) { + recv_right = recvbuf; + } else { + MPI_Alloc_mem(count * size, MPI_INFO_NULL, &recv_right); + } + + for (depth = 1; i != r; depth++) { + parent = i; + if (r > i + max_nodes) { + i += max_nodes + 1; + } else { + i++; + } + max_nodes /= 2; + } + + if (depth != tree_depth && r + 1 < p) { + MPI_Alloc_mem(count * size, MPI_INFO_NULL, &recv_left); + MPI_Recv(recv_left, count, datatype, r + 1, 0, comm, &status); + MPI_Reduce_local(sendbuf, recv_left, count, datatype, op); + + if (r + max_nodes + 1 < p) { + MPI_Recv(recv_right, count, datatype, r + max_nodes + 1, 0, comm, + &status); + MPI_Reduce_local(recv_left, recv_right, count, datatype, op); + } else { + memcpy(recv_right, recv_left, count * size); + } + + MPI_Free_mem(recv_left); + } else { + memcpy(recv_right, sendbuf, count * size); + } + + if (r != root) { + MPI_Send(recv_right, count, datatype, parent, 0, comm); + MPI_Free_mem(recv_right); + } + + return 0; +} diff --git a/reduce/bin_reduce.h b/reduce/bin_reduce.h new file mode 100644 index 0000000..aa421b0 --- /dev/null +++ b/reduce/bin_reduce.h @@ -0,0 +1,14 @@ +/* + * bin_reduce.h + * + * Created on: 16 Jun 2016 + * Author: johannes + */ + +#ifndef BIN_REDUCE_H_ +#define BIN_REDUCE_H_ + +int Bin_Reduce(const void *sendbuf, void *recvbuf, int count, + MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm); + +#endif /* BIN_REDUCE_H_ */ diff --git a/reduce/binom_reduce.c b/reduce/binom_reduce.c new file mode 100644 index 0000000..e96db38 --- /dev/null +++ b/reduce/binom_reduce.c @@ -0,0 +1,62 @@ +/* + * binom_reduce.c + * + * Created on: 18 Jun 2016 + * Author: johannes + */ + +#include +#include +#include +#include "binom_reduce.h" + +void swap(void **a, void **b) { + void *temp; + temp = *a; + *a = *b; + *b = temp; +} + +int Binom_Reduce(const void *sendbuf, void *recvbuf, int count, + MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm) { + + if (root != 0) { + fprintf(stderr, "Sorry, root!=0 not allowed"); + return -1; + } + + int r, p, size; + MPI_Status status; + void *recv; + void *reduced; + + MPI_Comm_rank(comm, &r); + MPI_Comm_size(comm, &p); + MPI_Type_size(datatype, &size); + + MPI_Alloc_mem(count * size, MPI_INFO_NULL, &recv); + MPI_Alloc_mem(count * size, MPI_INFO_NULL, &reduced); + + memcpy(reduced, sendbuf, count * size); + + int i = 1; + while ((r + i) % (2 * i) != 0 && i < p) { + if (r + i < p) { + MPI_Recv(recv, count, datatype, r + i, i, comm, &status); + MPI_Reduce_local(reduced, recv, count, datatype, op); + swap(&reduced, &recv); + } + i <<= 1; + } + + if (r != root) { + MPI_Send(reduced, count, datatype, r - i, i, comm); + } else { + memcpy(recvbuf, reduced, count * size); + } + + MPI_Free_mem(reduced); + MPI_Free_mem(recv); + + return 0; +} diff --git a/reduce/binom_reduce.h b/reduce/binom_reduce.h new file mode 100644 index 0000000..5b36a10 --- /dev/null +++ b/reduce/binom_reduce.h @@ -0,0 +1,14 @@ +/* + * binom_reduce.h + * + * Created on: 18 Jun 2016 + * Author: johannes + */ + +#ifndef BINOM_REDUCE_H_ +#define BINOM_REDUCE_H_ + +int Binom_Reduce(const void *sendbuf, void *recvbuf, int count, + MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm); + +#endif /* BINOM_REDUCE_H_ */ diff --git a/reduce/fib_reduce.c b/reduce/fib_reduce.c new file mode 100644 index 0000000..b1c69cf --- /dev/null +++ b/reduce/fib_reduce.c @@ -0,0 +1,86 @@ +/* + * fib_reduce.c + * + * Created on: 18 Jun 2016 + * Author: johannes + */ + +#include +#include +#include +#include "fib_reduce.h" + +int Fib_Reduce(const void *sendbuf, void *recvbuf, int count, + MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm) { + if (root != 0) { + fprintf(stderr, "Sorry, root!=0 not allowed"); + return -1; + } + + int r, p, size; + MPI_Status status; + void *recv_right; + + MPI_Comm_rank(comm, &r); + MPI_Comm_size(comm, &p); + MPI_Type_size(datatype, &size); + + int temp; + int right = 1; + int fib = 1; + + while (fib - 1 < p) { + temp = fib; + fib += right; + right = temp; + } + + int left = fib - right; + int i = 0; + int parent = 0; + + while (i != r) { + parent = i; + if (r >= i + left) { + i += left; + temp = left; + left = right - left; + right = temp; + } else { + i++; + right -= left; + left -= right; + } + } + + if (r == root) { + recv_right = recvbuf; + } else { + MPI_Alloc_mem(size * count, MPI_INFO_NULL, &recv_right); + } + + if (right - 1 > 0 && r + 1 < p) { + void *recv_left; + MPI_Alloc_mem(count * size, MPI_INFO_NULL, &recv_left); + MPI_Recv(recv_left, count, datatype, r + 1, 0, comm, &status); + MPI_Reduce_local(sendbuf, recv_left, count, datatype, op); + + if (left - 1 > 0 && r + left < p) { + MPI_Recv(recv_right, count, datatype, r + left, 0, comm, &status); + MPI_Reduce_local(recv_left, recv_right, count, datatype, op); + } else { + memcpy(recv_right, recv_left, count * size); + } + + MPI_Free_mem(recv_left); + } else { + memcpy(recv_right, sendbuf, count * size); + } + + if (r != root) { + MPI_Send(recv_right, count, datatype, parent, 0, comm); + MPI_Free_mem(recv_right); + } + + return 0; +} diff --git a/reduce/fib_reduce.h b/reduce/fib_reduce.h new file mode 100644 index 0000000..fa20580 --- /dev/null +++ b/reduce/fib_reduce.h @@ -0,0 +1,14 @@ +/* + * fib_reduce.h + * + * Created on: 18 Jun 2016 + * Author: johannes + */ + +#ifndef FIB_REDUCE_H_ +#define FIB_REDUCE_H_ + +int Fib_Reduce(const void *sendbuf, void *recvbuf, int count, + MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm); + +#endif /* FIB_REDUCE_H_ */ diff --git a/reduce/hpc_mpi.c b/reduce/hpc_mpi.c new file mode 100644 index 0000000..c0d2e7d --- /dev/null +++ b/reduce/hpc_mpi.c @@ -0,0 +1,192 @@ +/* + ============================================================================ + Name : hpc_mpi.c + Author : + Version : + Copyright : Your copyright notice + Description : Hello MPI World in C + ============================================================================ + */ +#include +#include +#include +#include +#include +#include +#include "bin_reduce.h" +#include "binom_reduce.h" +#include "fib_reduce.h" + +void usage(char *progname, int rank) { + if (rank == 0) { + fprintf(stderr, + "USAGE: %s [-b] [-o operation] size\n supported operations:\n 0 MAX\n 1 MIN\n 2 SUM\n 3 PROD\n 4 LAND\n 5 BAND\n 6 LOR\n 7 BOR\n 8 LXOR\n 9 BXOR\n", + progname); + } + MPI_Finalize(); + exit(EXIT_SUCCESS); +} + +void fill(int *a, int count, int rank) { + srand(time(NULL) + rank); + for (int i = 0; i < count; i++) { + a[i] = rand(); + } +} + +int main(int argc, char* argv[]) { + int r; + int p; + + MPI_Init(&argc, &argv); + MPI_Comm_rank(MPI_COMM_WORLD, &r); + MPI_Comm_size(MPI_COMM_WORLD, &p); + + int opt; + int benchmark = 0; + char oparg = '0'; + + while ((opt = getopt(argc, argv, "bo:")) != -1) { + switch (opt) { + case 'b': + benchmark = 1; + break; + case 'o': + oparg = optarg[0]; + break; + default: + usage(argv[0], r); + } + } + + if (optind >= argc) { + usage(argv[0], r); + } + + int size = atoi(argv[optind]); + MPI_Op op; + + switch (oparg) { + case '0': + op = MPI_MAX; + break; + case '1': + op = MPI_MIN; + break; + case '2': + op = MPI_SUM; + break; + case '3': + op = MPI_PROD; + break; + case '4': + op = MPI_LAND; + break; + case '5': + op = MPI_BAND; + break; + case '6': + op = MPI_LOR; + break; + case '7': + op = MPI_BOR; + break; + case '8': + op = MPI_LXOR; + break; + default: + op = MPI_BXOR; + break; + } + + int *a; + MPI_Alloc_mem(size * sizeof(int), MPI_INFO_NULL, &a); + fill(a, size, r); + + if (benchmark) { + int *red; + MPI_Alloc_mem(size * sizeof(int), MPI_INFO_NULL, &red); + double start, end, global_end; + + MPI_Barrier(MPI_COMM_WORLD); + start = MPI_Wtime(); + MPI_Reduce(a, red, size, MPI_INT, op, 0, MPI_COMM_WORLD); + end = MPI_Wtime(); + MPI_Reduce(&end, &global_end, 1, MPI_DOUBLE, MPI_MAX, 0, + MPI_COMM_WORLD); + if (r == 0) { + printf("%f, ", global_end - start); + } + + MPI_Barrier(MPI_COMM_WORLD); + start = MPI_Wtime(); + Fib_Reduce(a, red, size, MPI_INT, op, 0, MPI_COMM_WORLD); + end = MPI_Wtime(); + MPI_Reduce(&end, &global_end, 1, MPI_DOUBLE, MPI_MAX, 0, + MPI_COMM_WORLD); + if (r == 0) { + printf("%f, ", global_end - start); + } + + MPI_Barrier(MPI_COMM_WORLD); + start = MPI_Wtime(); + Bin_Reduce(a, red, size, MPI_INT, op, 0, MPI_COMM_WORLD); + end = MPI_Wtime(); + MPI_Reduce(&end, &global_end, 1, MPI_DOUBLE, MPI_MAX, 0, + MPI_COMM_WORLD); + if (r == 0) { + printf("%f, ", global_end - start); + } + + MPI_Barrier(MPI_COMM_WORLD); + start = MPI_Wtime(); + Binom_Reduce(a, red, size, MPI_INT, op, 0, MPI_COMM_WORLD); + end = MPI_Wtime(); + MPI_Reduce(&end, &global_end, 1, MPI_DOUBLE, MPI_MAX, 0, + MPI_COMM_WORLD); + if (r == 0) { + printf("%f\n", global_end - start); + } + + MPI_Free_mem(red); + } else { + int *red; + int *rfib; + int *rbin; + int *rbinom; + MPI_Alloc_mem(size * sizeof(int), MPI_INFO_NULL, &red); + MPI_Alloc_mem(size * sizeof(int), MPI_INFO_NULL, &rfib); + MPI_Alloc_mem(size * sizeof(int), MPI_INFO_NULL, &rbin); + MPI_Alloc_mem(size * sizeof(int), MPI_INFO_NULL, &rbinom); + + MPI_Reduce(a, red, size, MPI_INT, op, 0, MPI_COMM_WORLD); + Fib_Reduce(a, rfib, size, MPI_INT, op, 0, MPI_COMM_WORLD); + Bin_Reduce(a, rbin, size, MPI_INT, op, 0, MPI_COMM_WORLD); + Binom_Reduce(a, rbinom, size, MPI_INT, op, 0, MPI_COMM_WORLD); + + if (r == 0) { + if (memcmp(red, rfib, size * sizeof(int))) { + printf("Fib_Reduce does not match\n"); + } + if (memcmp(red, rbin, size * sizeof(int))) { + printf("Bin_Reduce does not match\n"); + } + if (memcmp(red, rbinom, size * sizeof(int))) { + printf("Binom_Reduce does not match\n"); + } + + printf("All checks done\n"); + } + + MPI_Free_mem(red); + MPI_Free_mem(rfib); + MPI_Free_mem(rbin); + MPI_Free_mem(rbinom); + } + + MPI_Free_mem(a); + + MPI_Finalize(); + return EXIT_SUCCESS; +} +