From bb363d3ed66aa6a1fffa3eed660e4d6f7f2bb737 Mon Sep 17 00:00:00 2001
From: "baptiste.coudray" <baptiste.coudray@etu.hesge.ch>
Date: Tue, 8 Jun 2021 11:10:20 +0200
Subject: [PATCH] Added function to create futhark outer envelope

---
 futhark_mpi/CMakeLists.txt    |  2 +-
 futhark_mpi/dispatch.c        | 80 ++++++++++++++++++++++++++++++++++-
 futhark_mpi/dispatch.h        |  7 +++
 futhark_mpi/envelope.fut      | 23 +++++++++-
 game_of_life/benchmark/main.c | 52 +++++------------------
 game_of_life/gol.fut          |  5 ++-
 game_of_life/main.c           | 52 +++++------------------
 7 files changed, 133 insertions(+), 88 deletions(-)

diff --git a/futhark_mpi/CMakeLists.txt b/futhark_mpi/CMakeLists.txt
index 7ffd907..444c380 100644
--- a/futhark_mpi/CMakeLists.txt
+++ b/futhark_mpi/CMakeLists.txt
@@ -6,7 +6,7 @@ set(CMAKE_C_STANDARD 11)
 if (CMAKE_BUILD_TYPE MATCHES Debug)
     set(GCC_COMPILE_FLAGS "-Wall -Wextra -Wconversion -pedantic -fsanitize=address -fsanitize=undefined")
 elseif (CMAKE_BUILD_TYPE MATCHES Release)
-    set(GCC_COMPILE_FLAGS "-O2")
+    set(GCC_COMPILE_FLAGS "-O3")
 endif ()
 
 find_package(MPI REQUIRED)
diff --git a/futhark_mpi/dispatch.c b/futhark_mpi/dispatch.c
index 0cc2396..7b69024 100644
--- a/futhark_mpi/dispatch.c
+++ b/futhark_mpi/dispatch.c
@@ -187,23 +187,33 @@ static envelope_t get_inner_envelope_1d(struct dispatch_context *dc, struct futh
     int thickness_x = min(thickness, dc->chunk_info->dimensions[1]);
     int dimensions[2] = {1, thickness_x};
 
+//    struct futhark_opaque_envelope_1d_t *fut_inner_envelope;
     futhark_context_sync(fc);
+//    futhark_entry_get_envelope_1d(fc, &fut_inner_envelope, fut_chunk_data, thickness_x * dc->type);
     futhark_entry_get_envelope_1d(fc, &fut_west, &fut_east, fut_chunk_data, dimensions[1] * dc->type);
     futhark_context_sync(fc);
     futhark_free_u8_1d(fc, fut_chunk_data);
 
+//    futhark_context_sync(fc);
+//    futhark_free_u8_1d(fc, fut_chunk_data);
+
     envelope_t inner_envelope = (envelope_t) {0};
+//    size_t size;
+//    futhark_store_opaque_envelope_1d_t(fc, fut_inner_envelope, &inner_envelope.futhark_bytes, &size);
+
     // West
     {
         int start_x = dc->chunk_info->x;
-        chunk_info_init(&inner_envelope.west, dc->type, dimensions, 0, start_x, true);
+        chunk_info_init(&inner_envelope.west, dc->type, dimensions, 0, start_x, false);
+//        inner_envelope.west.data = ((uint8_t *) inner_envelope.futhark_bytes) + 0x0F;
         futhark_values_u8_1d(fc, fut_west, inner_envelope.west.data);
     }
 
     // East
     {
         int start_x = dc->chunk_info->x + dc->chunk_info->dimensions[1] - thickness_x;
-        chunk_info_init(&inner_envelope.east, dc->type, dimensions, 0, start_x, true);
+        chunk_info_init(&inner_envelope.east, dc->type, dimensions, 0, start_x, false);
+//        inner_envelope.east.data = ((uint8_t *) inner_envelope.futhark_bytes) + 0x0F + thickness_x * dc->type + 0x0F;
         futhark_values_u8_1d(fc, fut_east, inner_envelope.east.data);
     }
 
@@ -230,7 +240,9 @@ static envelope_t get_inner_envelope_2d(struct dispatch_context *dc, struct futh
     int thickness_y = min(thickness, dc->chunk_info->dimensions[0]);
     int thickness_x = min(thickness, dc->chunk_info->dimensions[1]);
 
+//    struct futhark_opaque_envelope_2d_t *fut_inner_envelope;
     futhark_context_sync(fc);
+//    futhark_entry_get_envelope_2d(fc, &fut_inner_envelope, fut_chunk_data, thickness_y, thickness_x * dc->type);
     futhark_entry_get_envelope_2d(fc, &fut_north_west, &fut_north, &fut_north_east, &fut_west, &fut_east,
                                   &fut_south_west, &fut_south, &fut_south_east, fut_chunk_data, thickness_y,
                                   thickness_x * dc->type);
@@ -238,6 +250,8 @@ static envelope_t get_inner_envelope_2d(struct dispatch_context *dc, struct futh
     futhark_free_u8_2d(fc, fut_chunk_data);
 
     envelope_t inner_envelope = (envelope_t) {0};
+//    size_t size;
+//    futhark_store_opaque_envelope_2d_t(fc, fut_inner_envelope, &inner_envelope.futhark_bytes, &size);
 
     // North-West
     {
@@ -245,6 +259,7 @@ static envelope_t get_inner_envelope_2d(struct dispatch_context *dc, struct futh
         int start_y = dc->chunk_info->y;
         int start_x = dc->chunk_info->x;
         chunk_info_init(&inner_envelope.north_west, dc->type, dimensions, start_y, start_x, true);
+//        inner_envelope.north_west.data = ((uint8_t *) inner_envelope.futhark_bytes) + 0x0F;
         futhark_values_u8_2d(fc, fut_north_west, inner_envelope.north_west.data);
     }
 
@@ -323,6 +338,60 @@ static envelope_t get_inner_envelope_2d(struct dispatch_context *dc, struct futh
     return inner_envelope;
 }
 
+static void futhark_outer_envelope_1d_new(struct futhark_context *fc, envelope_t *outer_envelope,
+                                          void *f(struct futhark_context *, uint8_t *, int64_t),
+                                          void *futhark_envelope[2]) {
+    futhark_envelope[0] = f(fc, outer_envelope->west.data, outer_envelope->west.dimensions[1]);
+    futhark_envelope[1] = f(fc, outer_envelope->east.data, outer_envelope->east.dimensions[1]);
+}
+
+static void futhark_outer_envelope_2d_new(struct futhark_context *fc, envelope_t *outer_envelope,
+                                          void *f(struct futhark_context *, uint8_t *, int64_t, int64_t),
+                                          void *futhark_envelope[2]) {
+    futhark_envelope[0] = f(fc, outer_envelope->north_west.data, outer_envelope->north_west.dimensions[0],
+                            outer_envelope->north_west.dimensions[1]);
+
+    futhark_envelope[1] = f(fc, outer_envelope->north.data, outer_envelope->north.dimensions[0],
+                            outer_envelope->north.dimensions[1]);
+
+    futhark_envelope[2] = f(fc, outer_envelope->north_east.data, outer_envelope->north_east.dimensions[0],
+                            outer_envelope->north_east.dimensions[1]);
+
+    futhark_envelope[3] = f(fc, outer_envelope->west.data, outer_envelope->west.dimensions[0],
+                            outer_envelope->west.dimensions[1]);
+
+    futhark_envelope[4] = f(fc, outer_envelope->east.data, outer_envelope->east.dimensions[0],
+                            outer_envelope->east.dimensions[1]);
+
+    futhark_envelope[5] = f(fc, outer_envelope->south_west.data, outer_envelope->south_west.dimensions[0],
+                            outer_envelope->south_west.dimensions[1]);
+
+    futhark_envelope[6] = f(fc, outer_envelope->south.data, outer_envelope->south.dimensions[0],
+                            outer_envelope->south.dimensions[1]);
+
+    futhark_envelope[7] = f(fc, outer_envelope->south_east.data, outer_envelope->south_east.dimensions[0],
+                            outer_envelope->south_east.dimensions[1]);
+}
+
+extern void futhark_outer_envelope_new(struct dispatch_context *dc, struct futhark_context *fc,
+                                       envelope_t *outer_envelope, void *f(struct futhark_context *, uint8_t *, ...),
+                                       void *futhark_envelope[]) {
+    switch (dc->n_dimensions) {
+        case 1:
+            futhark_outer_envelope_1d_new(fc, outer_envelope,
+                                          (void *(*)(struct futhark_context *, uint8_t *, int64_t)) f,
+                                          futhark_envelope);
+            break;
+        case 2:
+            futhark_outer_envelope_2d_new(fc, outer_envelope,
+                                          (void *(*)(struct futhark_context *, uint8_t *, int64_t, int64_t)) f,
+                                          futhark_envelope);
+            break;
+        default:
+            break;
+    }
+}
+
 static envelope_t get_outer_envelope_1d(struct dispatch_context *dc, int thickness, envelope_t *inner_envelope) {
     int coordinate_x = dc->coordinates[1];
     MPI_Request requests[4];
@@ -636,6 +705,13 @@ extern void dispatch_context_free(struct dispatch_context *dc) {
     MPI_Comm_free(&dc->communicators[0]);
 }
 
+extern void futhark_outer_envelope_free(struct dispatch_context *dc, struct futhark_context *fc,
+                                        int f(struct futhark_context *, void *), void *foe[]) {
+    for (int i = 0; i < (dc->n_dimensions * dc->n_dimensions) * 2; ++i) {
+        f(fc, foe[i]);
+    }
+}
+
 extern void envelope_free(envelope_t *envelope) {
     chunk_info_free(&envelope->north);
     chunk_info_free(&envelope->north_east);
diff --git a/futhark_mpi/dispatch.h b/futhark_mpi/dispatch.h
index 3e0c848..df9df9c 100644
--- a/futhark_mpi/dispatch.h
+++ b/futhark_mpi/dispatch.h
@@ -25,12 +25,19 @@ extern envelope_t get_inner_envelope(struct dispatch_context *dc, struct futhark
 
 extern envelope_t get_outer_envelope(struct dispatch_context *dc, struct futhark_context *fc, int thickness);
 
+extern void futhark_outer_envelope_new(struct dispatch_context *dc, struct futhark_context *fc,
+                                       envelope_t *outer_envelope, void *f(struct futhark_context *, uint8_t *, ...),
+                                       void *futhark_envelope[]);
+
 extern chunk_info_t get_chunk_info(struct dispatch_context *dc);
 
 extern void *get_data(struct dispatch_context *dc);
 
 extern void dispatch_context_free(struct dispatch_context *dc);
 
+extern void futhark_outer_envelope_free(struct dispatch_context *dc, struct futhark_context *fc,
+                                        int f(struct futhark_context *, void *), void *foe[]);
+
 extern void envelope_free(envelope_t *envelope);
 
 #endif //_DISPATCH_H_
diff --git a/futhark_mpi/envelope.fut b/futhark_mpi/envelope.fut
index be9c774..e132ee4 100644
--- a/futhark_mpi/envelope.fut
+++ b/futhark_mpi/envelope.fut
@@ -2,7 +2,7 @@
 --     west: [n]u8,
 --     east: [n]u8
 -- }
---
+
 -- type envelope_2d_t [n][m][ty][tx] = {
 --     north_west: [ty][tx]u8,
 --     north: [ty][m]u8,
@@ -19,6 +19,11 @@ entry get_envelope_1d [n] (xs: [n]u8) (thickness: i64) : ([]u8, []u8) =
     let east = xs[n - thickness:] :> [thickness]u8
     in (west, east)
 
+-- entry get_envelope_1d [n] (xs: [n]u8) (thickness: i64) : envelope_1d_t [thickness] =
+--     let west = xs[0:thickness] :> [thickness]u8
+--     let east = xs[n - thickness:] :> [thickness]u8
+--     in {west, east}
+
 entry get_envelope_2d [n][m] (matrix: [n][m]u8) (thickness_y: i64) (thickness_x: i64): ([][]u8, [][]u8, [][]u8, [][]u8, [][]u8, [][]u8, [][]u8, [][]u8) =
     let north = matrix[0:thickness_y] :> [thickness_y][m]u8
 
@@ -34,3 +39,19 @@ entry get_envelope_2d [n][m] (matrix: [n][m]u8) (thickness_y: i64) (thickness_x:
     let west = matrix[:,0:thickness_x] :> [n][thickness_x]u8
 
     in (north_west, north, north_east, west, east, south_west, south, south_east)
+
+-- entry get_envelope_2d [n][m] (matrix: [n][m]u8) (thickness_y: i64) (thickness_x: i64): envelope_2d_t [n][m][thickness_y][thickness_x] =
+--     let north = matrix[0:thickness_y] :> [thickness_y][m]u8
+--
+--     let north_west = matrix[0:thickness_y,0:thickness_x] :> [thickness_y][thickness_x]u8
+--     let north_east = matrix[0:thickness_y,m - thickness_x:m] :> [thickness_y][thickness_x]u8
+--
+--     let south = matrix[n - thickness_y:] :> [thickness_y][m]u8
+--
+--     let south_east = matrix[n - thickness_y:n,m - thickness_x:m] :> [thickness_y][thickness_x]u8
+--     let south_west = matrix[n - thickness_y:n,0:thickness_x] :> [thickness_y][thickness_x]u8
+--
+--     let east = matrix[:,m - (thickness_x):] :> [n][thickness_x]u8
+--     let west = matrix[:,0:thickness_x] :> [n][thickness_x]u8
+--
+--     in {north_west, north, north_east, west, east, south_west, south, south_east}
diff --git a/game_of_life/benchmark/main.c b/game_of_life/benchmark/main.c
index 9c7c7fe..140888d 100644
--- a/game_of_life/benchmark/main.c
+++ b/game_of_life/benchmark/main.c
@@ -31,45 +31,19 @@ void init_chunk_board(chunk_info_t *ci) {
 void compute_next_chunk_board(struct dispatch_context *dc, struct futhark_context *fc, chunk_info_t *ci) {
     envelope_t outer_envelope = get_outer_envelope(dc, fc, 1);
 
-    struct futhark_i8_2d *fut_north = futhark_new_i8_2d(fc, outer_envelope.north.data,
-                                                        outer_envelope.north.dimensions[0],
-                                                        outer_envelope.north.dimensions[1]);
-
-    struct futhark_i8_2d *fut_north_east = futhark_new_i8_2d(fc, outer_envelope.north_east.data,
-                                                             outer_envelope.north_east.dimensions[0],
-                                                             outer_envelope.north_east.dimensions[1]);
-
-    struct futhark_i8_2d *fut_east = futhark_new_i8_2d(fc, outer_envelope.east.data,
-                                                       outer_envelope.east.dimensions[0],
-                                                       outer_envelope.east.dimensions[1]);
-
-    struct futhark_i8_2d *fut_south_east = futhark_new_i8_2d(fc, outer_envelope.south_east.data,
-                                                             outer_envelope.south_east.dimensions[0],
-                                                             outer_envelope.south_east.dimensions[1]);
-
-    struct futhark_i8_2d *fut_south = futhark_new_i8_2d(fc, outer_envelope.south.data,
-                                                        outer_envelope.south.dimensions[0],
-                                                        outer_envelope.south.dimensions[1]);
-
-    struct futhark_i8_2d *fut_south_west = futhark_new_i8_2d(fc, outer_envelope.south_west.data,
-                                                             outer_envelope.south_west.dimensions[0],
-                                                             outer_envelope.south_west.dimensions[1]);
-
-    struct futhark_i8_2d *fut_west = futhark_new_i8_2d(fc, outer_envelope.west.data,
-                                                       outer_envelope.west.dimensions[0],
-                                                       outer_envelope.west.dimensions[1]);
-
-    struct futhark_i8_2d *fut_north_west = futhark_new_i8_2d(fc, outer_envelope.north_west.data,
-                                                             outer_envelope.north_west.dimensions[0],
-                                                             outer_envelope.north_west.dimensions[1]);
+    struct futhark_i8_2d *fut_outer_envelope[8] = {0};
+    futhark_outer_envelope_new(dc, fc, &outer_envelope,
+                               (void *(*)(struct futhark_context *, uint8_t *, ...)) futhark_new_i8_2d,
+                               (void **) fut_outer_envelope);
 
     struct futhark_i8_2d *fut_chunk_board = futhark_new_i8_2d(fc, ci->data, ci->dimensions[0], ci->dimensions[1]);
     struct futhark_i8_2d *fut_next_chunk_board;
 
     futhark_context_sync(fc);
-    futhark_entry_next_chunk_board(fc, &fut_next_chunk_board, fut_chunk_board, fut_north_west, fut_north,
-                                   fut_north_east, fut_west, fut_east, fut_south_west, fut_south,
-                                   fut_south_east);
+    futhark_entry_next_chunk_board(fc, &fut_next_chunk_board, fut_chunk_board,
+                                   fut_outer_envelope[0], fut_outer_envelope[1], fut_outer_envelope[2],
+                                   fut_outer_envelope[3], fut_outer_envelope[4],
+                                   fut_outer_envelope[5], fut_outer_envelope[6], fut_outer_envelope[7]);
     futhark_context_sync(fc);
 
     futhark_values_i8_2d(fc, fut_next_chunk_board, ci->data);
@@ -77,14 +51,8 @@ void compute_next_chunk_board(struct dispatch_context *dc, struct futhark_contex
 
     futhark_free_i8_2d(fc, fut_next_chunk_board);
     futhark_free_i8_2d(fc, fut_chunk_board);
-    futhark_free_i8_2d(fc, fut_north_west);
-    futhark_free_i8_2d(fc, fut_north);
-    futhark_free_i8_2d(fc, fut_north_east);
-    futhark_free_i8_2d(fc, fut_west);
-    futhark_free_i8_2d(fc, fut_east);
-    futhark_free_i8_2d(fc, fut_south_west);
-    futhark_free_i8_2d(fc, fut_south);
-    futhark_free_i8_2d(fc, fut_south_east);
+    futhark_outer_envelope_free(dc, fc, (int (*)(struct futhark_context *, void *)) futhark_free_i8_2d,
+                                (void **) fut_outer_envelope);
     envelope_free(&outer_envelope);
 }
 
diff --git a/game_of_life/gol.fut b/game_of_life/gol.fut
index 3a1ba4b..224c3c7 100644
--- a/game_of_life/gol.fut
+++ b/game_of_life/gol.fut
@@ -1,5 +1,8 @@
 module env = import "../futhark_mpi/envelope"
 
+-- type envelope_1d_t [n] = env.envelope_1d_t [n]
+-- type envelope_2d_t [n][m][ty][tx] = env.envelope_2d_t [n][m][ty][tx]
+
 entry get_envelope_1d = env.get_envelope_1d
 entry get_envelope_2d = env.get_envelope_2d
 
@@ -46,7 +49,7 @@ let augment_board [n][m] (chunk_board:[n][m]i8)
 entry next_chunk_board [n][m] (chunk_board :[n][m]i8)
                               (nw:[1][1]i8) (no:[1][m]i8) (ne:[1][1]i8)
                                    (we:[n][1]i8) (ea:[n][1]i8)
-                              (sw:[1][1]i8) (so:[1][m]i8) (se:[1][1]i8) :[][]i8 =
+                              (sw:[1][1]i8) (so:[1][m]i8) (se:[1][1]i8) :[n][m]i8 =
     let augmented_board = augment_board chunk_board nw no ne we ea sw so se
     let neighbours = count_neighbours augmented_board
     let next_board = map2 (\augmented_board_r neighbours_r ->
diff --git a/game_of_life/main.c b/game_of_life/main.c
index e58f97b..f393772 100644
--- a/game_of_life/main.c
+++ b/game_of_life/main.c
@@ -31,44 +31,19 @@ void init_chunk_board(chunk_info_t *ci) {
 void compute_next_chunk_board(struct dispatch_context *dc, struct futhark_context *fc, chunk_info_t *ci) {
     envelope_t outer_envelope = get_outer_envelope(dc, fc, 1);
 
-    struct futhark_i8_2d *fut_north = futhark_new_i8_2d(fc, outer_envelope.north.data,
-                                                        outer_envelope.north.dimensions[0],
-                                                        outer_envelope.north.dimensions[1]);
-
-    struct futhark_i8_2d *fut_north_east = futhark_new_i8_2d(fc, outer_envelope.north_east.data,
-                                                             outer_envelope.north_east.dimensions[0],
-                                                             outer_envelope.north_east.dimensions[1]);
-
-    struct futhark_i8_2d *fut_east = futhark_new_i8_2d(fc, outer_envelope.east.data,
-                                                       outer_envelope.east.dimensions[0],
-                                                       outer_envelope.east.dimensions[1]);
-
-    struct futhark_i8_2d *fut_south_east = futhark_new_i8_2d(fc, outer_envelope.south_east.data,
-                                                             outer_envelope.south_east.dimensions[0],
-                                                             outer_envelope.south_east.dimensions[1]);
-
-    struct futhark_i8_2d *fut_south = futhark_new_i8_2d(fc, outer_envelope.south.data,
-                                                        outer_envelope.south.dimensions[0],
-                                                        outer_envelope.south.dimensions[1]);
-
-    struct futhark_i8_2d *fut_south_west = futhark_new_i8_2d(fc, outer_envelope.south_west.data,
-                                                             outer_envelope.south_west.dimensions[0],
-                                                             outer_envelope.south_west.dimensions[1]);
-
-    struct futhark_i8_2d *fut_west = futhark_new_i8_2d(fc, outer_envelope.west.data,
-                                                       outer_envelope.west.dimensions[0],
-                                                       outer_envelope.west.dimensions[1]);
-
-    struct futhark_i8_2d *fut_north_west = futhark_new_i8_2d(fc, outer_envelope.north_west.data,
-                                                             outer_envelope.north_west.dimensions[0],
-                                                             outer_envelope.north_west.dimensions[1]);
+    struct futhark_i8_2d *fut_outer_envelope[8] = {0};
+    futhark_outer_envelope_new(dc, fc, &outer_envelope,
+                               (void *(*)(struct futhark_context *, uint8_t *, ...)) futhark_new_i8_2d,
+                               (void **) fut_outer_envelope);
 
     struct futhark_i8_2d *fut_chunk_board = futhark_new_i8_2d(fc, ci->data, ci->dimensions[0], ci->dimensions[1]);
     struct futhark_i8_2d *fut_next_chunk_board;
 
     futhark_context_sync(fc);
-    futhark_entry_next_chunk_board(fc, &fut_next_chunk_board, fut_chunk_board, fut_north_west, fut_north,
-                                   fut_north_east, fut_west, fut_east, fut_south_west, fut_south, fut_south_east);
+    futhark_entry_next_chunk_board(fc, &fut_next_chunk_board, fut_chunk_board,
+                                   fut_outer_envelope[0], fut_outer_envelope[1], fut_outer_envelope[2],
+                                   fut_outer_envelope[3], fut_outer_envelope[4],
+                                   fut_outer_envelope[5], fut_outer_envelope[6], fut_outer_envelope[7]);
     futhark_context_sync(fc);
 
     futhark_values_i8_2d(fc, fut_next_chunk_board, ci->data);
@@ -76,16 +51,11 @@ void compute_next_chunk_board(struct dispatch_context *dc, struct futhark_contex
 
     futhark_free_i8_2d(fc, fut_next_chunk_board);
     futhark_free_i8_2d(fc, fut_chunk_board);
-    futhark_free_i8_2d(fc, fut_north_west);
-    futhark_free_i8_2d(fc, fut_north);
-    futhark_free_i8_2d(fc, fut_north_east);
-    futhark_free_i8_2d(fc, fut_west);
-    futhark_free_i8_2d(fc, fut_east);
-    futhark_free_i8_2d(fc, fut_south_west);
-    futhark_free_i8_2d(fc, fut_south);
-    futhark_free_i8_2d(fc, fut_south_east);
+    futhark_outer_envelope_free(dc, fc, (int (*)(struct futhark_context *, void *)) futhark_free_i8_2d,
+                                (void **) fut_outer_envelope);
     envelope_free(&outer_envelope);
 }
+
 int main(int argc, char *argv[]) {
     if (argc < 3) {
         printf("usage: mpirun -n <nb_proc> %s <height> <width>\n", argv[0]);
-- 
GitLab