summaryrefslogtreecommitdiff
path: root/tabulator-mpi
diff options
context:
space:
mode:
authorBenji Dial <benji@benjidial.net>2023-05-30 03:01:25 -0400
committerBenji Dial <benji@benjidial.net>2023-05-30 03:01:25 -0400
commit6678dccccdfffb9c40f64a828fd769c53bb2d29f (patch)
tree4a7f1c0b849b8bc4cebe5c9c0bc690a0e6e07146 /tabulator-mpi
parente39e53f96e0fb75847bd2f5eb40cac7c52e85886 (diff)
downloadlib94-6678dccccdfffb9c40f64a828fd769c53bb2d29f.tar.gz
mpi-based tabulator
Diffstat (limited to 'tabulator-mpi')
-rw-r--r--tabulator-mpi/head.cpp83
-rw-r--r--tabulator-mpi/main.cpp46
-rw-r--r--tabulator-mpi/worker.cpp43
3 files changed, 172 insertions, 0 deletions
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 <lib94/lib94.hpp>
+#include <cstdio>
+#include <mpi.h>
+
+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 <lib94/lib94.hpp>
+#include <fstream>
+#include <cstdio>
+#include <mpi.h>
+
+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<char>(stream), {});
+
+ auto w = lib94::compile_warrior(source);
+
+ if (std::holds_alternative<std::string>(w)) {
+ fprintf(stderr, "error compiling %s: %s\n", file, std::get<std::string>(w).c_str());
+ exit(1);
+ }
+
+ return std::get<lib94::warrior *>(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 <lib94/lib94.hpp>
+#include <mpi.h>
+
+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]]);
+ }
+}