From 6678dccccdfffb9c40f64a828fd769c53bb2d29f Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Tue, 30 May 2023 03:01:25 -0400 Subject: mpi-based tabulator --- tabulator-mpi/head.cpp | 83 ++++++++++++++++++++++++++++++++++++++++++++++++ tabulator-mpi/main.cpp | 46 +++++++++++++++++++++++++++ tabulator-mpi/worker.cpp | 43 +++++++++++++++++++++++++ 3 files changed, 172 insertions(+) create mode 100644 tabulator-mpi/head.cpp create mode 100644 tabulator-mpi/main.cpp create mode 100644 tabulator-mpi/worker.cpp (limited to 'tabulator-mpi') diff --git a/tabulator-mpi/head.cpp b/tabulator-mpi/head.cpp new file mode 100644 index 0000000..e2372bc --- /dev/null +++ b/tabulator-mpi/head.cpp @@ -0,0 +1,83 @@ +#include +#include +#include + +static int **score_results; + +static int get_result() { + int result[3]; + MPI_Status status; + MPI_Recv(result, 3, MPI_INT, MPI_ANY_SOURCE, 1, MPI_COMM_WORLD, &status); + + if (result[0] != -1) + score_results[result[0]][result[1]] += result[2]; + + return status.MPI_SOURCE; +} + +void head_main(int comm_size, int warrior_count, const lib94::warrior *const *warriors) { + score_results = new int *[warrior_count]; + for (int i = 0; i < warrior_count; ++i) { + score_results[i] = new int[warrior_count]; + for (int j = 0; j < warrior_count; ++j) + score_results[i][j] = 0; + } + + for (int i = 0; i < warrior_count; ++i) + for (int j = i + 1; j < warrior_count; ++j) { + fprintf(stderr, "%s vs %s\n", warriors[i]->name.c_str(), warriors[j]->name.c_str()); + for (int x = 0; x < 10; ++x) { + int rank = get_result(); + int message[3] = {i, j, x * 100}; + MPI_Send(message, 2, MPI_INT, rank, 0, MPI_COMM_WORLD); + fprintf(stderr, "sent rounds %d through %d to worker %d\n", x * 100 + 1, x * 100 + 100, rank); + } + fputc('\n', stderr); + } + + + for (int i = 0; i < comm_size - 1; ++i) { + int rank = get_result(); + int message[3] = {-1}; + MPI_Send(message, 3, MPI_INT, rank, 0, MPI_COMM_WORLD); + } + + for (int i = 0; i < warrior_count; ++i) + for (int j = i + 1; j < warrior_count; ++j) + if (score_results[i][j] < 0) { + score_results[j][i] = -score_results[i][j]; + score_results[i][j] = 0; + } + + int *tab_widths = new int[warrior_count + 1]; + tab_widths[0] = 0; + + for (int i = 0; i < warrior_count; ++i) { + int len = warriors[i]->name.size(); + if (len > tab_widths[0]) + tab_widths[0] = len; + tab_widths[i + 1] = len > 5 ? len : 5; + } + + printf(" %*s", tab_widths[0], ""); + for (int j = 0; j < warrior_count; ++j) + printf(" | %*s", tab_widths[j + 1], warriors[j]->name.c_str()); + putchar('\n'); + + putchar('-'); + for (int x = 0; x < tab_widths[0]; ++x) + putchar('-'); + for (int j = 0; j < warrior_count; ++j) { + printf("-+-"); + for (int x = 0; x < tab_widths[j + 1]; ++x) + putchar('-'); + } + printf("-\n"); + + for (int i = 0; i < warrior_count; ++i) { + printf(" %*s", tab_widths[0], warriors[i]->name.c_str()); + for (int j = 0; j < warrior_count; ++j) + printf(" | %*d", tab_widths[j + 1], score_results[i][j]); + putchar('\n'); + } +} diff --git a/tabulator-mpi/main.cpp b/tabulator-mpi/main.cpp new file mode 100644 index 0000000..f76ed70 --- /dev/null +++ b/tabulator-mpi/main.cpp @@ -0,0 +1,46 @@ +#include +#include +#include +#include + +void head_main(int comm_size, int warrior_count, const lib94::warrior *const *warriors); + +void worker_main(const lib94::warrior *const *warriors); + +const lib94::warrior *load_warrior(const char *file) { + std::ifstream stream(file); + if (!stream) { + fprintf(stderr, "could not open %s\n", file); + exit(1); + } + + std::string source(std::istreambuf_iterator(stream), {}); + + auto w = lib94::compile_warrior(source); + + if (std::holds_alternative(w)) { + fprintf(stderr, "error compiling %s: %s\n", file, std::get(w).c_str()); + exit(1); + } + + return std::get(w); +} + +int main(int argc, char **argv) { + MPI_Init(&argc, &argv); + + int comm_rank, comm_size; + MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank); + MPI_Comm_size(MPI_COMM_WORLD, &comm_size); + + const lib94::warrior **warriors = new const lib94::warrior *[argc - 1]; + for (int i = 0; i < argc - 1; ++i) + warriors[i] = load_warrior(argv[i + 1]); + + if (comm_rank == 0) + head_main(comm_size, argc - 1, warriors); + else + worker_main(warriors); + + MPI_Finalize(); +} diff --git a/tabulator-mpi/worker.cpp b/tabulator-mpi/worker.cpp new file mode 100644 index 0000000..e9768b2 --- /dev/null +++ b/tabulator-mpi/worker.cpp @@ -0,0 +1,43 @@ +#include +#include + +static int do_round(const lib94::warrior *w1, const lib94::warrior *w2) { + const lib94::warrior *ws[2] = {w1, w2}; + + lib94::instruction background = { + .op = lib94::DAT, .mod = lib94::F, + .amode = lib94::DIRECT, .bmode = lib94::DIRECT, + .anumber = 0, .bnumber = 0 + }; + + lib94::clear_core(background); + + lib94::init_round(ws, 2); + + for (int i = 0; i < 1000000; ++i) { + const lib94::warrior *result = lib94::single_step(); + if (result == w1) + return -1; + if (result == w2) + return 1; + } + + return 0; +} + +void worker_main(const lib94::warrior *const *warriors) { + int buffer[3] = {-1}; + + while (1) { + MPI_Send(buffer, 3, MPI_INT, 0, 1, MPI_COMM_WORLD); + MPI_Recv(buffer, 3, MPI_INT, 0, 0, MPI_COMM_WORLD, 0); + + if (buffer[0] == -1) + return; + + buffer[2] = 0; + + for (int i = 0; i < 100; ++i) + buffer[2] += do_round(warriors[buffer[0]], warriors[buffer[1]]); + } +} -- cgit v1.2.3