diff --git a/.gitignore b/.gitignore index 62ed0f0bc78bb3400e8b0bf1b81101a09f995f4d..f0dcbe2dd0805bd43c3063cff1b65f5c45f223a0 100644 --- a/.gitignore +++ b/.gitignore @@ -68,4 +68,3 @@ Temporary Items .apdisk .idea -game_of_life/benchmark/*.png diff --git a/futhark_mpi/.gitignore b/futhark_mpi/.gitignore index 4a4fe12cf442706310b1ad0fe5cd3e799a9e91df..d839d8ee26d09927d1d6528ed1577fd639d06f92 100644 --- a/futhark_mpi/.gitignore +++ b/futhark_mpi/.gitignore @@ -126,5 +126,5 @@ fabric.properties .idea/caches/build_file_checksums.ser .idea -gol.h -gol.c +envelope.h +envelope.c diff --git a/futhark_mpi/chunk_info.c b/futhark_mpi/chunk_info.c index 0ee7d081a2e83ed4ae1161928cf34402135ae97f..7e1d4ef350629b0d0cd3c6b22e1f75a7d8218462 100644 --- a/futhark_mpi/chunk_info.c +++ b/futhark_mpi/chunk_info.c @@ -3,15 +3,18 @@ #include <assert.h> #include "chunk_info.h" -extern void chunk_info_init(chunk_info_t *ci, int type, const int dimensions[2], int y, int x, bool allocate_data) { +extern void +chunk_info_init(chunk_info_t *ci, int type, const int dimensions[3], int y, int x, int z, bool allocate_data) { ci->dimensions[0] = dimensions[0]; ci->dimensions[1] = dimensions[1]; - ci->count = (size_t) ci->dimensions[0] * (size_t) ci->dimensions[1]; + ci->dimensions[2] = dimensions[2]; + ci->count = (size_t) ci->dimensions[0] * (size_t) ci->dimensions[1] * (size_t) ci->dimensions[2]; if (allocate_data) { chunk_info_allocate_data(ci, type); } ci->y = y; ci->x = x; + ci->z = z; } extern void chunk_info_allocate_data(chunk_info_t *ci, int type) { @@ -20,8 +23,8 @@ extern void chunk_info_allocate_data(chunk_info_t *ci, int type) { } void chunk_info_print(chunk_info_t *ci) { - printf("[chunk_info_t] data = %p, dimensions = [%d][%d], count = %zu, YX = (%d, %d)\n", - ci->data, ci->dimensions[0], ci->dimensions[1], ci->count, ci->y, ci->x); + printf("[chunk_info_t] data = %p, dimensions = [%d][%d][%d], count = %zu, YXZ = (%d, %d, %d)\n", + ci->data, ci->dimensions[0], ci->dimensions[1], ci->dimensions[2], ci->count, ci->y, ci->x, ci->z); } extern void chunk_info_free(chunk_info_t *ci) { diff --git a/futhark_mpi/chunk_info.h b/futhark_mpi/chunk_info.h index 3dcd7c1ef97fa8e9e97b778128f945b75e4fe1ad..46340f2e9fddb87b2d82c25a82d93641e994adc2 100644 --- a/futhark_mpi/chunk_info.h +++ b/futhark_mpi/chunk_info.h @@ -5,13 +5,15 @@ typedef struct chunk_info { void *data; - int dimensions[2]; + int dimensions[3]; size_t count; int y; int x; + int z; } chunk_info_t; -extern void chunk_info_init(chunk_info_t *ci, int type, const int dimensions[2], int y, int x, bool allocate_data); +extern void +chunk_info_init(chunk_info_t *ci, int type, const int dimensions[3], int y, int x, int z, bool allocate_data); extern void chunk_info_allocate_data(chunk_info_t *ci, int type); diff --git a/futhark_mpi/dispatch.c b/futhark_mpi/dispatch.c index 1dc7217b8063f188daf6797fe21de13a6a93351e..7c86efeebaf2d761676b7c2dd495d51a29cb3f75 100644 --- a/futhark_mpi/dispatch.c +++ b/futhark_mpi/dispatch.c @@ -38,10 +38,10 @@ struct dispatch_context { int world_size; int my_cart_rank; int coordinates[2]; - MPI_Comm communicators[3]; /* cart_comm, row_comm, column_comm */ + MPI_Comm communicators[4]; /* cart_comm, row_comm, column_comm, depth_comm */ + int network_dimensions[3]; + int data_dimensions[3]; MPI_Datatype datatype; - int network_dimensions[2]; - int data_dimensions[2]; size_t count; int n_dimensions; chunk_info_t *chunk_info; @@ -58,57 +58,80 @@ static void get_my_rank(struct dispatch_context *dc) { MPI_Comm_rank(MPI_COMM_WORLD, &dc->my_rank); } +static void find_best_factors(int n, int factors[2]) { + int result[2] = {0}; + int limit = (int) sqrt(n); + bool first_pass = true; + for (int i = 1; i <= limit; ++i) { + if (n % i == 0) { + int factor1 = i; + int factor2 = n / i; + int current_difference = abs(result[0] - result[1]); + int new_difference = abs(factor1 - factor2); + if (first_pass || current_difference > new_difference) { + result[0] = factor1; + result[1] = factor2; + } + first_pass = false; + } + } + factors[0] = result[0]; + factors[1] = result[1]; +} + static void find_network_dimensions(struct dispatch_context *dc) { /* 1D */ if (dc->n_dimensions == 1) { dc->network_dimensions[0] = 1; dc->network_dimensions[1] = dc->world_size; + dc->network_dimensions[2] = 1; } else { /* 2D */ - int limit = (int) sqrt(dc->world_size); - bool first_pass = true; - for (int i = 1; i <= limit; ++i) { - if (dc->world_size % i == 0) { - int new_grid_ny = i; - int new_grid_nx = dc->world_size / i; - int current_difference = abs(dc->network_dimensions[0] - dc->network_dimensions[1]); - int new_difference = abs(new_grid_ny - new_grid_nx); - if (first_pass || current_difference > new_difference) { - dc->network_dimensions[0] = new_grid_ny; - dc->network_dimensions[1] = new_grid_nx; - } - first_pass = false; - } - } + find_best_factors(dc->world_size, dc->network_dimensions); + dc->network_dimensions[2] = 1; + /* 3D */ if (dc->n_dimensions == 3) { - /* 3D */ - + int factors[2] = {0}; + find_best_factors(dc->network_dimensions[1], factors); + if (factors[0] < factors[1]) { + dc->network_dimensions[1] = factors[1]; + dc->network_dimensions[2] = factors[0]; + } else { + dc->network_dimensions[1] = factors[0]; + dc->network_dimensions[2] = factors[1]; + } } } } static void create_network_communicators(struct dispatch_context *dc) { - int periods[2] = {true, true}; // Cyclic on row-column-depth + int periods[3] = {true, true, true}; // Cyclic on row-column-depth - MPI_Cart_create(MPI_COMM_WORLD, 2, dc->network_dimensions, periods, 1, &dc->communicators[0]); + MPI_Cart_create(MPI_COMM_WORLD, 3, dc->network_dimensions, periods, 1, &dc->communicators[0]); /* Create row communicator */ - int remain_dims[2] = {false, true}; + int remain_dims[3] = {false, true, false}; MPI_Cart_sub(dc->communicators[0], remain_dims, &dc->communicators[1]); /* Create column communicator */ remain_dims[0] = true; // row remain_dims[1] = false; // column + remain_dims[2] = false; // depth MPI_Cart_sub(dc->communicators[0], remain_dims, &dc->communicators[2]); + /* Create depth communicator */ + remain_dims[0] = false; // row + remain_dims[1] = false; // column + remain_dims[2] = true; // depth + MPI_Cart_sub(dc->communicators[0], remain_dims, &dc->communicators[3]); + MPI_Comm_rank(dc->communicators[0], &dc->my_cart_rank); - MPI_Cart_coords(dc->communicators[0], dc->my_cart_rank, 2, dc->coordinates); + MPI_Cart_coords(dc->communicators[0], dc->my_cart_rank, 3, dc->coordinates); } static void divide_data(struct dispatch_context *dc) { dc->chunks_info = calloc((size_t) dc->world_size, sizeof(chunk_info_t)); - assert(dc->chunks_info != NULL); int nb_rows_per_process = dc->data_dimensions[0] / dc->network_dimensions[0]; int remaining_rows = dc->data_dimensions[0] % dc->network_dimensions[0]; @@ -116,7 +139,10 @@ static void divide_data(struct dispatch_context *dc) { int nb_columns_per_process = dc->data_dimensions[1] / dc->network_dimensions[1]; int remaining_columns = dc->data_dimensions[1] % dc->network_dimensions[1]; - for (int i = 0, y = 0, x = 0; i < dc->world_size; ++i) { + int nb_depths_per_process = dc->data_dimensions[2] / dc->network_dimensions[2]; + int remaining_depths = dc->data_dimensions[2] % dc->network_dimensions[2]; + + for (int i = 0, y = 0, x = 0, z = 0; i < dc->world_size; ++i) { int nb_rows = nb_rows_per_process; if (remaining_rows > 0) { ++nb_rows; @@ -126,9 +152,13 @@ static void divide_data(struct dispatch_context *dc) { ++nb_columns; --remaining_columns; } + int nb_depths = nb_depths_per_process; + if (remaining_depths > 0) { + ++nb_depths; + } - int dimensions[2] = {nb_rows, nb_columns}; - chunk_info_init(&dc->chunks_info[i], dc->type, dimensions, y, x, i == dc->my_rank); + int dimensions[3] = {nb_rows, nb_columns, nb_depths}; + chunk_info_init(&dc->chunks_info[i], dc->type, dimensions, y, x, z, i == dc->my_rank); x += nb_columns; if (x >= dc->data_dimensions[1]) { @@ -137,6 +167,12 @@ static void divide_data(struct dispatch_context *dc) { remaining_columns = dc->data_dimensions[1] % dc->network_dimensions[1]; --remaining_rows; } + if ((i + 1) % (dc->network_dimensions[0] * dc->network_dimensions[1]) == 0) { + z += nb_depths; + y = 0; + remaining_columns = dc->data_dimensions[1] % dc->network_dimensions[1]; + --remaining_depths; + } } dc->chunk_info = &dc->chunks_info[dc->my_rank]; } @@ -154,19 +190,24 @@ extern struct dispatch_context *dispatch_context_new(const int *dimensions, MPI_ case 1: dc->data_dimensions[0] = 1; dc->data_dimensions[1] = dimensions[0]; + dc->data_dimensions[2] = 1; break; case 2: dc->data_dimensions[0] = dimensions[0]; dc->data_dimensions[1] = dimensions[1]; + dc->data_dimensions[2] = 1; break; case 3: - return NULL; + dc->data_dimensions[0] = dimensions[0]; + dc->data_dimensions[1] = dimensions[1]; + dc->data_dimensions[2] = dimensions[2]; + break; default: fprintf(stderr, "Invalid dimensions size."); MPI_Abort(MPI_COMM_WORLD, 1); break; } - dc->count = (size_t) dc->data_dimensions[0] * (size_t) dc->data_dimensions[1]; + dc->count = (size_t) dc->data_dimensions[0] * (size_t) dc->data_dimensions[1] * (size_t) dc->data_dimensions[2]; find_network_dimensions(dc); create_network_communicators(dc); @@ -176,43 +217,58 @@ extern struct dispatch_context *dispatch_context_new(const int *dimensions, MPI_ } extern void dispatch_context_print(struct dispatch_context *dc) { - printf("[dispatch_context] my_rank = %d, world_size = %d, network_dimensions = [%d][%d], n_dimensions = %d, data_dimensions = [%d][%d]\n", - dc->my_rank, dc->world_size, dc->network_dimensions[0], dc->network_dimensions[1], dc->n_dimensions, - dc->data_dimensions[0], dc->data_dimensions[1]); + printf("[dispatch_context] my_rank = %d, world_size = %d, network_dimensions = [%d][%d][%d], n_dimensions = %d, data_dimensions = [%d][%d][%d]\n", + dc->my_rank, dc->world_size, dc->network_dimensions[0], dc->network_dimensions[1], dc->network_dimensions[2], + dc->n_dimensions, + dc->data_dimensions[0], dc->data_dimensions[1], dc->data_dimensions[2]); } +struct futhark_opaque_envelope_1d_t { + struct futhark_i8_1d *v0; + struct futhark_i8_1d *v1; +}; + +struct futhark_opaque_envelope_2d_t { + struct futhark_i8_2d *v0; + struct futhark_i8_2d *v1; + struct futhark_i8_2d *v2; + struct futhark_i8_2d *v3; + struct futhark_i8_2d *v4; + struct futhark_i8_2d *v5; + struct futhark_i8_2d *v6; + struct futhark_i8_2d *v7; +}; + static envelope_t get_inner_envelope_1d(struct dispatch_context *dc, struct futhark_context *fc, int thickness) { struct futhark_u8_1d *fut_chunk_data = futhark_new_u8_1d(fc, dc->chunk_info->data, dc->chunk_info->dimensions[1] * dc->type); - struct futhark_u8_1d *fut_west; - struct futhark_u8_1d *fut_east; int thickness_x = min(thickness, dc->chunk_info->dimensions[1]); - int dimensions[2] = {1, thickness_x}; + int dimensions[3] = {1, thickness_x, 1}; + struct futhark_opaque_envelope_1d_t *fut_inner_envelope; futhark_context_sync(fc); - futhark_entry_get_envelope_1d(fc, &fut_west, &fut_east, fut_chunk_data, dimensions[1] * dc->type); + futhark_entry_get_envelope_1d(fc, &fut_inner_envelope, fut_chunk_data, dimensions[1] * dc->type); futhark_context_sync(fc); - futhark_free_u8_1d(fc, fut_chunk_data); envelope_t inner_envelope = (envelope_t) {0}; // West { int start_x = dc->chunk_info->x; - chunk_info_init(&inner_envelope.west, dc->type, dimensions, 0, start_x, false); - futhark_values_u8_1d(fc, fut_west, inner_envelope.west.data); + chunk_info_init(&inner_envelope.west, dc->type, dimensions, 0, start_x, 0, true); + futhark_values_i8_1d(fc, fut_inner_envelope->v1, 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, false); - futhark_values_u8_1d(fc, fut_east, inner_envelope.east.data); + chunk_info_init(&inner_envelope.east, dc->type, dimensions, 0, start_x, 0, true); + futhark_values_i8_1d(fc, fut_inner_envelope->v0, inner_envelope.east.data); } futhark_context_sync(fc); - futhark_free_u8_1d(fc, fut_west); - futhark_free_u8_1d(fc, fut_east); + futhark_free_opaque_envelope_1d_t(fc, fut_inner_envelope); + futhark_free_u8_1d(fc, fut_chunk_data); return inner_envelope; } @@ -221,163 +277,184 @@ static envelope_t get_inner_envelope_2d(struct dispatch_context *dc, struct futh dc->active_domain.dimensions[0], dc->active_domain.dimensions[1] * dc->type); - struct futhark_u8_2d *fut_north_west; - struct futhark_u8_2d *fut_north; - struct futhark_u8_2d *fut_north_east; - struct futhark_u8_2d *fut_west; - struct futhark_u8_2d *fut_east; - struct futhark_u8_2d *fut_south_west; - struct futhark_u8_2d *fut_south; - struct futhark_u8_2d *fut_south_east; - int thickness_y = min(thickness, dc->active_domain.dimensions[0]); int thickness_x = min(thickness, dc->active_domain.dimensions[1]); + + struct futhark_opaque_envelope_2d_t *fut_inner_envelope; + futhark_context_sync(fc); - futhark_entry_get_envelope_2d(fc, &fut_north_west, &fut_west, &fut_south_west, - &fut_south, &fut_south_east, - &fut_east, &fut_north_east, &fut_north, - fut_chunk_data, thickness_y,thickness_x * dc->type); + futhark_entry_get_envelope_2d(fc, &fut_inner_envelope, fut_chunk_data, thickness_y, thickness_x * dc->type); futhark_context_sync(fc); - futhark_free_u8_2d(fc, fut_chunk_data); envelope_t inner_envelope = (envelope_t) {0}; - // North-West { - int dimensions[2] = {thickness_y, thickness_x}; + int dimensions[3] = {thickness_y, thickness_x, 1}; int start_y = dc->active_domain.y; int start_x = dc->active_domain.x; - chunk_info_init(&inner_envelope.north_west, dc->type, dimensions, start_y, start_x, true); - futhark_values_u8_2d(fc, fut_north_west, inner_envelope.north_west.data); + chunk_info_init(&inner_envelope.north_west, dc->type, dimensions, start_y, start_x, 0, true); + futhark_values_i8_2d(fc, fut_inner_envelope->v3, inner_envelope.north_west.data); } // North { - int dimensions[2] = {thickness_y, dc->active_domain.dimensions[1]}; + int dimensions[3] = {thickness_y, dc->active_domain.dimensions[1], 1}; int start_y = dc->active_domain.y; int start_x = dc->active_domain.x; - chunk_info_init(&inner_envelope.north, dc->type, dimensions, start_y, start_x, true); - futhark_values_u8_2d(fc, fut_north, inner_envelope.north.data); + chunk_info_init(&inner_envelope.north, dc->type, dimensions, start_y, start_x, 0, true); + futhark_values_i8_2d(fc, fut_inner_envelope->v1, inner_envelope.north.data); } // North-East { - int dimensions[2] = {thickness_y, thickness_x}; + int dimensions[3] = {thickness_y, thickness_x, 1}; int start_y = dc->active_domain.y; int start_x = dc->active_domain.x + dc->active_domain.dimensions[1] - thickness_x; - chunk_info_init(&inner_envelope.north_east, dc->type, dimensions, start_y, start_x, true); - futhark_values_u8_2d(fc, fut_north_east, inner_envelope.north_east.data); + chunk_info_init(&inner_envelope.north_east, dc->type, dimensions, start_y, start_x, 0, true); + futhark_values_i8_2d(fc, fut_inner_envelope->v2, inner_envelope.north_east.data); } // West { - int dimensions[2] = {dc->active_domain.dimensions[0], thickness_x}; + int dimensions[3] = {dc->active_domain.dimensions[0], thickness_x, 1}; int start_y = dc->active_domain.y; int start_x = dc->active_domain.x; - chunk_info_init(&inner_envelope.west, dc->type, dimensions, start_y, start_x, true); - futhark_values_u8_2d(fc, fut_west, inner_envelope.west.data); + chunk_info_init(&inner_envelope.west, dc->type, dimensions, start_y, start_x, 0, true); + futhark_values_i8_2d(fc, fut_inner_envelope->v7, inner_envelope.west.data); } // East { - int dimensions[2] = {dc->chunk_info->dimensions[0], thickness_x}; + int dimensions[3] = {dc->chunk_info->dimensions[0], thickness_x, 1}; int start_y = dc->active_domain.y; int start_x = dc->active_domain.x + dc->active_domain.dimensions[1] - thickness_x; - chunk_info_init(&inner_envelope.east, dc->type, dimensions, start_y, start_x, true); - futhark_values_u8_2d(fc, fut_east, inner_envelope.east.data); + chunk_info_init(&inner_envelope.east, dc->type, dimensions, start_y, start_x, 0, true); + futhark_values_i8_2d(fc, fut_inner_envelope->v0, inner_envelope.east.data); } // South-West { - int dimensions[2] = {thickness_y, thickness_x}; + int dimensions[3] = {thickness_y, thickness_x, 1}; int start_y = dc->active_domain.y + dc->active_domain.dimensions[0] - thickness_y; int start_x = dc->active_domain.x; - chunk_info_init(&inner_envelope.south_west, dc->type, dimensions, start_y, start_x, true); - futhark_values_u8_2d(fc, fut_south_west, inner_envelope.south_west.data); + chunk_info_init(&inner_envelope.south_west, dc->type, dimensions, start_y, start_x, 0, true); + futhark_values_i8_2d(fc, fut_inner_envelope->v6, inner_envelope.south_west.data); } // South { - int dimensions[2] = {thickness_y, dc->active_domain.dimensions[1]}; + int dimensions[3] = {thickness_y, dc->active_domain.dimensions[1], 1}; int start_y = dc->active_domain.y + dc->active_domain.dimensions[0] - thickness_y; int start_x = dc->active_domain.x; - chunk_info_init(&inner_envelope.south, dc->type, dimensions, start_y, start_x, true); - futhark_values_u8_2d(fc, fut_south, inner_envelope.south.data); + chunk_info_init(&inner_envelope.south, dc->type, dimensions, start_y, start_x, 0, true); + futhark_values_i8_2d(fc, fut_inner_envelope->v4, inner_envelope.south.data); } // South-East { - int dimensions[2] = {thickness_y, thickness_x}; + int dimensions[3] = {thickness_y, thickness_x, 1}; int start_y = dc->active_domain.y + dc->active_domain.dimensions[0] - thickness_y; int start_x = dc->active_domain.x + dc->active_domain.dimensions[1] - thickness_x; - chunk_info_init(&inner_envelope.south_east, dc->type, dimensions, start_y, start_x, true); - futhark_values_u8_2d(fc, fut_south_east, inner_envelope.south_east.data); + chunk_info_init(&inner_envelope.south_east, dc->type, dimensions, start_y, start_x, 0, true); + futhark_values_i8_2d(fc, fut_inner_envelope->v5, inner_envelope.south_east.data); } futhark_context_sync(fc); - futhark_free_u8_2d(fc, fut_north_west); - futhark_free_u8_2d(fc, fut_north); - futhark_free_u8_2d(fc, fut_north_east); - futhark_free_u8_2d(fc, fut_west); - futhark_free_u8_2d(fc, fut_east); - futhark_free_u8_2d(fc, fut_south_west); - futhark_free_u8_2d(fc, fut_south); - futhark_free_u8_2d(fc, fut_south_east); + futhark_free_u8_2d(fc, fut_chunk_data); + futhark_free_opaque_envelope_2d_t(fc, fut_inner_envelope); 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 uint8_t *chunk_info_to_futhark(struct dispatch_context *dc, uint8_t *out, chunk_info_t *ci, char *fut_type) { + *out++ = 'b'; + *out++ = 2; + *out++ = dc->n_dimensions; + memcpy(out, fut_type, 4); + out += 4; + + int64_t dimensions64[3]; + dimensions64[0] = (int64_t) ci->dimensions[0]; + dimensions64[1] = (int64_t) ci->dimensions[1]; + dimensions64[2] = (int64_t) ci->dimensions[2]; + + if (dc->n_dimensions == 1) { + memcpy(out, &dimensions64[1], 1 * sizeof(int64_t)); + } else if (dc->n_dimensions == 2) { + memcpy(out, dimensions64, 2 * sizeof(int64_t)); + } + out += dc->n_dimensions * sizeof(int64_t); + memcpy(out, ci->data, ci->count * dc->type); + out += ci->count * dc->type; + return out; } -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]); +static void * +futhark_outer_envelope_1d_new(struct dispatch_context *dc, struct futhark_context *fc, envelope_t *outer_envelope, + void *f(struct futhark_context *, const void *), char *fut_type) { + int64_t size_0 = 7 + 1 * sizeof(int64_t) + outer_envelope->east.count * dc->type; + int64_t size_1 = 7 + 1 * sizeof(int64_t) + outer_envelope->west.count * dc->type; - futhark_envelope[1] = f(fc, outer_envelope->west.data, outer_envelope->west.dimensions[0], - outer_envelope->west.dimensions[1]); + void *opaque_struct = calloc(size_0 * size_1, sizeof(uint8_t)); + uint8_t *out = (uint8_t *) opaque_struct; - futhark_envelope[2] = f(fc, outer_envelope->south_west.data, outer_envelope->south_west.dimensions[0], - outer_envelope->south_west.dimensions[1]); + // East + out = chunk_info_to_futhark(dc, out, &outer_envelope->east, fut_type); - futhark_envelope[3] = f(fc, outer_envelope->south.data, outer_envelope->south.dimensions[0], - outer_envelope->south.dimensions[1]); + // West + chunk_info_to_futhark(dc, out, &outer_envelope->west, fut_type); - futhark_envelope[4] = f(fc, outer_envelope->south_east.data, outer_envelope->south_east.dimensions[0], - outer_envelope->south_east.dimensions[1]); + void *fut_opaque_struct = f(fc, opaque_struct); + futhark_context_sync(fc); - futhark_envelope[5] = f(fc, outer_envelope->east.data, outer_envelope->east.dimensions[0], - outer_envelope->east.dimensions[1]); + free(opaque_struct); + return fut_opaque_struct; +} - futhark_envelope[6] = f(fc, outer_envelope->north_east.data, outer_envelope->north_east.dimensions[0], - outer_envelope->north_east.dimensions[1]); +static void * +futhark_outer_envelope_2d_new(struct dispatch_context *dc, struct futhark_context *fc, envelope_t *outer_envelope, + void *f(struct futhark_context *, const void *), + char *fut_type) { + + int64_t size_0 = 7 + 2 * sizeof(int64_t) + outer_envelope->east.count * dc->type; + int64_t size_1 = 7 + 2 * sizeof(int64_t) + outer_envelope->north.count * dc->type; + int64_t size_2 = 7 + 2 * sizeof(int64_t) + outer_envelope->north_east.count * dc->type; + int64_t size_3 = 7 + 2 * sizeof(int64_t) + outer_envelope->north_west.count * dc->type; + int64_t size_4 = 7 + 2 * sizeof(int64_t) + outer_envelope->south.count * dc->type; + int64_t size_5 = 7 + 2 * sizeof(int64_t) + outer_envelope->south_east.count * dc->type; + int64_t size_6 = 7 + 2 * sizeof(int64_t) + outer_envelope->south_west.count * dc->type; + int64_t size_7 = 7 + 2 * sizeof(int64_t) + outer_envelope->west.count * dc->type; + + void *opaque_struct = calloc(size_0 + size_1 + size_2 + size_3 + size_4 + size_5 + size_6 + size_7, + sizeof(uint8_t)); + uint8_t *out = (uint8_t *) opaque_struct; + + out = chunk_info_to_futhark(dc, out, &outer_envelope->east, fut_type); + out = chunk_info_to_futhark(dc, out, &outer_envelope->north, fut_type); + out = chunk_info_to_futhark(dc, out, &outer_envelope->north_east, fut_type); + out = chunk_info_to_futhark(dc, out, &outer_envelope->north_west, fut_type); + out = chunk_info_to_futhark(dc, out, &outer_envelope->south, fut_type); + out = chunk_info_to_futhark(dc, out, &outer_envelope->south_east, fut_type); + out = chunk_info_to_futhark(dc, out, &outer_envelope->south_west, fut_type); + chunk_info_to_futhark(dc, out, &outer_envelope->west, fut_type); + + void *fut_opaque_struct = f(fc, opaque_struct); + futhark_context_sync(fc); - futhark_envelope[7] = f(fc, outer_envelope->north.data, outer_envelope->north.dimensions[0], - outer_envelope->north.dimensions[1]); + free(opaque_struct); + return fut_opaque_struct; } -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 void *futhark_outer_envelope_new(struct dispatch_context *dc, struct futhark_context *fc, + envelope_t *outer_envelope, void *f(struct futhark_context *, const void *), + char *fut_type) { 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; + return futhark_outer_envelope_1d_new(dc, fc, outer_envelope, f, fut_type); case 2: - futhark_outer_envelope_2d_new(fc, outer_envelope, - (void *(*)(struct futhark_context *, uint8_t *, int64_t, int64_t)) f, - futhark_envelope); - break; + return futhark_outer_envelope_2d_new(dc, fc, outer_envelope, f, fut_type); default: - break; + return NULL; } } @@ -397,9 +474,9 @@ static envelope_t get_outer_envelope_1d(struct dispatch_context *dc, int thickne MPI_Isend(inner_envelope->west.data, send_count, dc->datatype, dest_source_x, WEST_COLUMN_TAG, dc->communicators[1], &requests[i_request++]); - int dimensions[2] = {1, min(thickness, dc->chunks_info[dest_source].dimensions[1])}; + int dimensions[3] = {1, min(thickness, dc->chunks_info[dest_source].dimensions[1]), 1}; int start_x = dc->chunks_info[dest_source].x + dc->chunks_info[dest_source].dimensions[1] - dimensions[1]; - chunk_info_init(&outer_envelope.west, dc->type, dimensions, 0, start_x, true); + chunk_info_init(&outer_envelope.west, dc->type, dimensions, 0, start_x, 0, true); MPI_Irecv(outer_envelope.west.data, (int) outer_envelope.west.count, dc->datatype, dest_source_x, EAST_COLUMN_TAG, dc->communicators[1], &requests[i_request++]); @@ -418,9 +495,9 @@ static envelope_t get_outer_envelope_1d(struct dispatch_context *dc, int thickne MPI_Isend(inner_envelope_east, send_count, dc->datatype, dest_source_x, EAST_COLUMN_TAG, dc->communicators[1], &requests[i_request++]); - int dimensions[2] = {1, min(thickness, dc->chunks_info[dest_source].dimensions[1])}; + int dimensions[3] = {1, min(thickness, dc->chunks_info[dest_source].dimensions[1]), 1}; int start_x = dc->chunks_info[dest_source].x + dimensions[1]; - chunk_info_init(&outer_envelope.east, dc->type, dimensions, 0, start_x, true); + chunk_info_init(&outer_envelope.east, dc->type, dimensions, 0, start_x, 0, true); MPI_Irecv(outer_envelope.east.data, (int) outer_envelope.east.count, dc->datatype, dest_source_x, WEST_COLUMN_TAG, dc->communicators[1], &requests[i_request]); @@ -449,13 +526,13 @@ static envelope_t get_outer_envelope_2d(struct dispatch_context *dc, int thickne dc->communicators[2], &requests[i_request++]); /* Neighbour send south row, which correspond to north envelope */ - int dimensions[2] = { + int dimensions[3] = { min(thickness, dc->chunks_info[dest_source].dimensions[0]), - dc->chunks_info[dest_source].dimensions[1] + dc->chunks_info[dest_source].dimensions[1], 1 }; int start_y = dc->chunks_info[dest_source].y + dc->chunks_info[dest_source].dimensions[0] - dimensions[0]; int start_x = dc->chunks_info[dest_source].x; - chunk_info_init(&outer_envelope.north, dc->type, dimensions, start_y, start_x, true); + chunk_info_init(&outer_envelope.north, dc->type, dimensions, start_y, start_x, 0, true); MPI_Irecv(outer_envelope.north.data, (int) outer_envelope.north.count, dc->datatype, dest_source_y, SOUTH_ROW_TAG, dc->communicators[2], &requests[i_request++]); @@ -472,13 +549,13 @@ static envelope_t get_outer_envelope_2d(struct dispatch_context *dc, int thickne dc->communicators[1], &requests[i_request++]); /* Neighbour send west column, which correspond to east envelope */ - int dimensions[2] = { + int dimensions[3] = { dc->chunks_info[dest_source].dimensions[0], - min(thickness, dc->chunks_info[dest_source].dimensions[1]) + min(thickness, dc->chunks_info[dest_source].dimensions[1]), 1 }; int start_y = dc->chunks_info[dest_source].y; int start_x = dc->chunks_info[dest_source].x + dc->chunks_info[dest_source].dimensions[1] - dimensions[1]; - chunk_info_init(&outer_envelope.east, dc->type, dimensions, start_y, start_x, true); + chunk_info_init(&outer_envelope.east, dc->type, dimensions, start_y, start_x, 0, true); MPI_Irecv(outer_envelope.east.data, (int) outer_envelope.east.count, dc->datatype, dest_source_x, WEST_COLUMN_TAG, dc->communicators[1], &requests[i_request++]); } @@ -494,13 +571,13 @@ static envelope_t get_outer_envelope_2d(struct dispatch_context *dc, int thickne dc->communicators[2], &requests[i_request++]); /* Neighbour send north row, which correspond to south envelope */ - int dimensions[2] = { + int dimensions[3] = { min(thickness, dc->chunks_info[dest_source].dimensions[0]), - dc->chunks_info[dest_source].dimensions[1] + dc->chunks_info[dest_source].dimensions[1], 1 }; int start_y = dc->chunks_info[dest_source].y; int start_x = dc->chunks_info[dest_source].x; - chunk_info_init(&outer_envelope.south, dc->type, dimensions, start_y, start_x, true); + chunk_info_init(&outer_envelope.south, dc->type, dimensions, start_y, start_x, 0, true); MPI_Irecv(outer_envelope.south.data, (int) outer_envelope.south.count, dc->datatype, dest_source_y, NORTH_ROW_TAG, dc->communicators[2], &requests[i_request++]); } @@ -515,13 +592,13 @@ static envelope_t get_outer_envelope_2d(struct dispatch_context *dc, int thickne dc->communicators[1], &requests[i_request++]); /* Neighbour send west column, which correspond to east envelope */ - int dimensions[2] = { + int dimensions[3] = { dc->chunks_info[dest_source].dimensions[0], - min(thickness, dc->chunks_info[dest_source].dimensions[1]) + min(thickness, dc->chunks_info[dest_source].dimensions[1]), 1 }; int start_y = dc->chunks_info[dest_source].y; int start_x = dc->chunks_info[dest_source].x; - chunk_info_init(&outer_envelope.west, dc->type, dimensions, start_y, start_x, true); + chunk_info_init(&outer_envelope.west, dc->type, dimensions, start_y, start_x, 0, true); MPI_Irecv(outer_envelope.west.data, (int) outer_envelope.west.count, dc->datatype, dest_source_x, EAST_COLUMN_TAG, dc->communicators[1], &requests[i_request++]); } @@ -537,10 +614,10 @@ static envelope_t get_outer_envelope_2d(struct dispatch_context *dc, int thickne MPI_COMM_WORLD, &requests[i_request++]); /* Neighbour send south-west cell, which correspond to north-east cell */ - int dimensions[2] = {thickness, thickness}; + int dimensions[3] = {thickness, thickness, 1}; int start_y = dc->chunks_info[dest_source].y + dc->chunks_info[dest_source].dimensions[0] + dimensions[0]; int start_x = dc->chunks_info[dest_source].x; - chunk_info_init(&outer_envelope.north_east, dc->type, dimensions, start_y, start_x, true); + chunk_info_init(&outer_envelope.north_east, dc->type, dimensions, start_y, start_x, 0, true); MPI_Irecv(outer_envelope.north_east.data, (int) outer_envelope.north_east.count, dc->datatype, dest_source, SOUTH_WEST_CELLS_TAG, MPI_COMM_WORLD, &requests[i_request++]); } @@ -556,10 +633,10 @@ static envelope_t get_outer_envelope_2d(struct dispatch_context *dc, int thickne MPI_COMM_WORLD, &requests[i_request++]); /* Neighbour send north-west cell, which correspond to south-east cell */ - int dimensions[2] = {thickness, thickness}; + int dimensions[3] = {thickness, thickness, 1}; int start_y = dc->chunks_info[dest_source].y; int start_x = dc->chunks_info[dest_source].x; - chunk_info_init(&outer_envelope.south_east, dc->type, dimensions, start_y, start_x, true); + chunk_info_init(&outer_envelope.south_east, dc->type, dimensions, start_y, start_x, 0, true); MPI_Irecv(outer_envelope.south_east.data, (int) outer_envelope.south_east.count, dc->datatype, dest_source, NORTH_WEST_CELLS_TAG, MPI_COMM_WORLD, &requests[i_request++]); } @@ -575,10 +652,10 @@ static envelope_t get_outer_envelope_2d(struct dispatch_context *dc, int thickne MPI_COMM_WORLD, &requests[i_request++]); /* Neighbour send north-east cell, which correspond to south-west cell */ - int dimensions[2] = {thickness, thickness}; + int dimensions[3] = {thickness, thickness, 1}; int start_y = dc->chunks_info[dest_source].y; int start_x = dc->chunks_info[dest_source].x + dc->chunks_info[dest_source].dimensions[1] - thickness; - chunk_info_init(&outer_envelope.south_west, dc->type, dimensions, start_y, start_x, true); + chunk_info_init(&outer_envelope.south_west, dc->type, dimensions, start_y, start_x, 0, true); MPI_Irecv(outer_envelope.south_west.data, (int) outer_envelope.south_west.count, dc->datatype, dest_source, NORTH_EAST_CELLS_TAG, MPI_COMM_WORLD, &requests[i_request++]); } @@ -594,10 +671,10 @@ static envelope_t get_outer_envelope_2d(struct dispatch_context *dc, int thickne MPI_COMM_WORLD, &requests[i_request++]); /* Neighbour send south-east cell, which correspond to north-west cell */ - int dimensions[2] = {thickness, thickness}; + int dimensions[3] = {thickness, thickness, 1}; int start_y = dc->chunks_info[dest_source].y + dc->chunks_info[dest_source].dimensions[0] - thickness; int start_x = dc->chunks_info[dest_source].x + dc->chunks_info[dest_source].dimensions[1] - thickness; - chunk_info_init(&outer_envelope.north_west, dc->type, dimensions, start_y, start_x, true); + chunk_info_init(&outer_envelope.north_west, dc->type, dimensions, start_y, start_x, 0, true); MPI_Irecv(outer_envelope.north_west.data, (int) outer_envelope.north_west.count, dc->datatype, dest_source, SOUTH_EAST_CELLS_TAG, MPI_COMM_WORLD, &requests[i_request++]); } @@ -694,20 +771,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]); - } -} - -static void set_active_domain_1d( struct dispatch_context *dc, struct futhark_context *fc, int dimensions[1], int x) { - chunk_info_init(&dc->active_domain, dc->type, dimensions, 0, x, true); +static void set_active_domain_1d(struct dispatch_context *dc, struct futhark_context *fc, int dimensions[1], int x) { + chunk_info_init(&dc->active_domain, dc->type, dimensions, 0, x, 0, true); int64_t dimensions64[1]; dimensions64[0] = dimensions[0] * dc->type; struct futhark_u8_1d *fut_chunk_data = futhark_new_u8_1d(fc, dc->chunk_info->data, dimensions64[0] * dc->type); - struct futhark_i64_1d* fut_dimension = futhark_new_i64_1d(fc, dimensions64, 1); + struct futhark_i64_1d *fut_dimension = futhark_new_i64_1d(fc, dimensions64, 1); struct futhark_u8_1d *subdomain; futhark_context_sync(fc); @@ -720,9 +790,10 @@ static void set_active_domain_1d( struct dispatch_context *dc, struct futhark_co futhark_free_i64_1d(fc, fut_dimension); futhark_free_u8_1d(fc, subdomain); } + static void set_active_domain_2d(struct dispatch_context *dc, struct futhark_context *fc, int dimensions[2], int y, int x) { - chunk_info_init(&dc->active_domain, dc->type, dimensions, y, x, true); + chunk_info_init(&dc->active_domain, dc->type, dimensions, y, x, 0, true); int64_t dimensions64[2]; dimensions64[0] = dimensions[0]; @@ -746,7 +817,35 @@ set_active_domain_2d(struct dispatch_context *dc, struct futhark_context *fc, in futhark_free_u8_2d(fc, subdomain); } -extern void set_active_domain(struct dispatch_context *dc, struct futhark_context *fc, int *dimensions, int y, int x) { +static void +set_active_domain_3d(struct dispatch_context *dc, struct futhark_context *fc, int dimensions[3], int y, int x, int z) { + chunk_info_init(&dc->active_domain, dc->type, dimensions, y, x, z, true); + + int64_t dimensions64[3]; + dimensions64[0] = dimensions[0]; + dimensions64[1] = dimensions[1] * dc->type; + dimensions64[2] = dimensions[2]; + + struct futhark_u8_3d *fut_chunk_data = futhark_new_u8_3d(fc, dc->chunk_info->data, dimensions64[0], + dimensions64[1], dimensions64[2]); + + struct futhark_i64_1d *fut_dimensions = futhark_new_i64_1d(fc, dimensions64, 3); + struct futhark_u8_3d *subdomain; + + futhark_context_sync(fc); + futhark_entry_get_subdomain_3d(fc, &subdomain, fut_chunk_data, y, x * dc->type, z, fut_dimensions); + + futhark_context_sync(fc); + futhark_values_u8_3d(fc, subdomain, dc->active_domain.data); + futhark_context_sync(fc); + + futhark_free_u8_3d(fc, fut_chunk_data); + futhark_free_i64_1d(fc, fut_dimensions); + futhark_free_u8_3d(fc, subdomain); +} + +extern void +set_active_domain(struct dispatch_context *dc, struct futhark_context *fc, int *dimensions, int y, int x, int z) { switch (dc->n_dimensions) { case 1: set_active_domain_1d(dc, fc, dimensions, x); @@ -754,6 +853,9 @@ extern void set_active_domain(struct dispatch_context *dc, struct futhark_contex case 2: set_active_domain_2d(dc, fc, dimensions, y, x); break; + case 3: + set_active_domain_3d(dc, fc, dimensions, y, x, z); + break; default: break; } diff --git a/futhark_mpi/dispatch.h b/futhark_mpi/dispatch.h index df9df9c33473795147231b742226231fb1f01f45..f39db1a2fe8e68f605fa9cb236ca0b30a83a734b 100644 --- a/futhark_mpi/dispatch.h +++ b/futhark_mpi/dispatch.h @@ -1,9 +1,20 @@ #ifndef _DISPATCH_H_ #define _DISPATCH_H_ -#include "futhark.h" +#include "../game_of_life/gol.h" #include "chunk_info.h" +#define FUT_I8 " i8" +#define FUT_U8 " i8" +#define FUT_I16 " i16" +#define FUT_U16 " i16" +#define FUT_I32 " i32" +#define FUT_U32 " i32" +#define FUT_I64 " i64" +#define FUT_U64 " i64" +#define FUT_F32 " f32" +#define FUT_F64 " f64" + struct dispatch_context; typedef struct envelope { @@ -25,9 +36,9 @@ 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 void * +futhark_outer_envelope_new(struct dispatch_context *dc, struct futhark_context *fc, envelope_t *outer_envelope, + void *f(struct futhark_context *, const void *), char *fut_type); extern chunk_info_t get_chunk_info(struct dispatch_context *dc); @@ -35,8 +46,8 @@ 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 +set_active_domain(struct dispatch_context *dc, struct futhark_context *fc, int *dimensions, int y, int x, int z); extern void envelope_free(envelope_t *envelope); diff --git a/futhark_mpi/envelope.fut b/futhark_mpi/envelope.fut index 2bebb9345feb818d19afdb5b2d9fdb33e9764d99..1798ecca04da25e89d9c55db8d327f7c84c3a9a0 100644 --- a/futhark_mpi/envelope.fut +++ b/futhark_mpi/envelope.fut @@ -1,9 +1,25 @@ -entry get_envelope_1d [n] (xs: [n]u8) (thickness: i64) : ([]u8, []u8) = +type envelope_1d_t [n] = { + west: [n]u8, -- 1 + east: [n]u8 -- 0 +} + +type envelope_2d_t [n][m][ty][tx] = { + north_west: [ty][tx]u8, -- 3 + west: [n][tx]u8, -- 7 + south_west: [ty][tx]u8, -- 6 + south: [ty][m]u8, -- 4 + south_east: [ty][tx]u8, -- 5 + east: [n][tx]u8, -- 0 + north_east: [ty][tx]u8, -- 2 + north: [ty][m]u8 -- 1 +} + +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) + 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) = +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 @@ -17,10 +33,51 @@ entry get_envelope_2d [n][m] (matrix: [n][m]u8) (thickness_y: i64) (thickness_x: let east = matrix[:,m - (thickness_x):] :> [n][thickness_x]u8 let west = matrix[:,0:thickness_x] :> [n][thickness_x]u8 - in (north_west, west, south_west, south, south_east, east, north_east, north) + in {north_west, west, south_west, south, south_east, east, north_east, north} + + -- entry get_envelope_3d [n][m][l] (cube:[n][m][l]u8) (thickness_y: i64) (thickness_x: i64) (thickness_z: i64): + -- let north_front = matrix[0:thickness_y,:,0:thickness_z] + -- let south_front = matrix[n - thickness_y:,:,0:thickness_z] + + -- let west_front = matrix[:,0:thickness_x:0:thickness_z] + -- let east_front = matrix[:,m - (thickness_x):0:thickness_z] + + -- let north_west_front = matrix[0:thickness_y,0:thickness_x,0:thickness_z] + -- let north_east_front = matrix[0:thickness_y,m - thickness_x:m,0:thickness_z] + -- let south_east_front = matrix[n - thickness_y:n,m - thickness_x:m,0:thickness_z] + -- let south_west_front = matrix[n - thickness_y:n,0:thickness_x,0:thickness_z] + + -- let north_back = matrix[0:thickness_y,:,0:l-thickness_z] + -- let south_back = matrix[n - thickness_y:,:,0:l-thickness_z] + + -- let west_back = matrix[:,0:thickness_x:0:l-thickness_z] + -- let east_back = matrix[:,m - (thickness_x):l-thickness_z] + + -- let north_west_back = matrix[0:thickness_y,0:thickness_x,l-thickness_z] + -- let north_east_back = matrix[0:thickness_y,m - thickness_x:m,l-thickness_z] + -- let south_east_back = matrix[n - thickness_y:n,m - thickness_x:m,l-thickness_z] + -- let south_west_back = matrix[n - thickness_y:n,0:thickness_x,l-thickness_z] + + + -- -- let north_right = matrix[0:thickness_y,m-1:m,:] + -- -- let south_right = matrix[n - thickness_y:m-1:m,:] + + -- -- let west_back = matrix[:,0:thickness_x:0:l-thickness_z] + -- -- let east_back = matrix[:,m - (thickness_x):l-thickness_z] + + -- -- let north_west_back = matrix[0:thickness_y,0:thickness_x,l-thickness_z] + -- -- let north_east_back = matrix[0:thickness_y,m - thickness_x:m,l-thickness_z] + -- -- let south_east_back = matrix[n - thickness_y:n,m - thickness_x:m,l-thickness_z] + -- -- let south_west_back = matrix[n - thickness_y:n,0:thickness_x,l-thickness_z] + + + -- in (north_west, west, south_west, south, south_east, east, north_east, north) entry get_subdomain_1d [n] (xs: [n]u8) (x:i64) (dimensions: [1]i64) : []u8 = xs[x:x+dimensions[0]] entry get_subdomain_2d [n][m] (matrix: [n][m]u8) (y:i64) (x:i64) (dimensions: [2]i64) : [][]u8 = matrix[y:y+dimensions[0],x:x+dimensions[1]] + +entry get_subdomain_3d [n][m][l] (cube:[n][m][l]u8) (y:i64) (x:i64) (z:i64) (dimensions: [3]i64) : [][][]u8 = + cube[y:y+dimensions[0],x:x+dimensions[1],z:z+dimensions[2]] diff --git a/futhark_mpi/futhark.h b/futhark_mpi/futhark.h deleted file mode 100644 index 111f74f76b5fff0cfb7024a9048ea8f9d6b709ae..0000000000000000000000000000000000000000 --- a/futhark_mpi/futhark.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * File to resolve symbol when programming - */ -#ifndef _FUTHARK_H_ -#define _FUTHARK_H_ -#include <stdint.h> - -struct futhark_context; - -struct futhark_u8_1d; -struct futhark_u8_2d; - -struct futhark_u8_1d *futhark_new_u8_1d(struct futhark_context *ctx, const -uint8_t *data, int64_t dim0); - -int futhark_free_u8_1d(struct futhark_context *ctx, struct futhark_u8_1d *arr); - -int futhark_values_u8_1d(struct futhark_context *ctx, struct futhark_u8_1d *arr, - uint8_t *data); - -int futhark_entry_get_envelope_1d(struct futhark_context *ctx, - struct futhark_u8_1d **out0, - struct futhark_u8_1d **out1, const - struct futhark_u8_1d *in0, int64_t in1); - -int futhark_entry_get_envelope_2d(struct futhark_context *ctx, - struct futhark_u8_2d **out0, - struct futhark_u8_2d **out1, - struct futhark_u8_2d **out2, - struct futhark_u8_2d **out3, - struct futhark_u8_2d **out4, - struct futhark_u8_2d **out5, - struct futhark_u8_2d **out6, - struct futhark_u8_2d **out7, const - struct futhark_u8_2d *in0, int64_t in1, - int64_t in2); - -int futhark_entry_get_subdomain_1d(struct futhark_context *ctx, - struct futhark_u8_1d **out0, const - struct futhark_u8_1d *in0, const int64_t in1, - const struct futhark_i64_1d *in2); -int futhark_entry_get_subdomain_2d(struct futhark_context *ctx, - struct futhark_u8_2d **out0, const - struct futhark_u8_2d *in0, const int64_t in1, - const int64_t in2, const - struct futhark_i64_1d *in3); - -struct futhark_u8_1d *futhark_new_u8_1d(struct futhark_context *ctx, const uint8_t *data, int64_t dim0); - -struct futhark_u8_2d *futhark_new_u8_2d(struct futhark_context *ctx, const -uint8_t *data, int64_t dim0, int64_t dim1); - -int futhark_free_u8_2d(struct futhark_context *ctx, struct futhark_u8_2d *arr); - -int futhark_values_u8_2d(struct futhark_context *ctx, struct futhark_u8_2d *arr, - uint8_t *data); - -int futhark_context_sync(struct futhark_context *ctx); - -struct futhark_i64_1d ; -struct futhark_i64_1d *futhark_new_i64_1d(struct futhark_context *ctx, const -int64_t *data, int64_t dim0); -int futhark_free_i64_1d(struct futhark_context *ctx, - struct futhark_i64_1d *arr); -int futhark_values_i64_1d(struct futhark_context *ctx, - struct futhark_i64_1d *arr, int64_t *data); - -#endif //_FUTHARK_H_ diff --git a/game_of_life/.gitignore b/game_of_life/.gitignore index 4a4fe12cf442706310b1ad0fe5cd3e799a9e91df..c8ce81d6bddf761b53cfda7b6ac5f495c07f7893 100644 --- a/game_of_life/.gitignore +++ b/game_of_life/.gitignore @@ -128,3 +128,4 @@ fabric.properties .idea gol.h gol.c +benchmark/*.png diff --git a/game_of_life/benchmark/main.c b/game_of_life/benchmark/main.c index 67f58deafe9a941c599b551c4908d1e6a7afd88f..8e9e802286f240b15a22bba0ccbd2a33fe277b16 100644 --- a/game_of_life/benchmark/main.c +++ b/game_of_life/benchmark/main.c @@ -31,19 +31,15 @@ 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_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_opaque_envelope_2d_i8 *fut_outer_envelope = futhark_outer_envelope_new(dc, fc, &outer_envelope, + futhark_restore_opaque_envelope_2d_i8, + FUT_I8); 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_outer_envelope[0], fut_outer_envelope[7], fut_outer_envelope[6], - fut_outer_envelope[1], fut_outer_envelope[5], - fut_outer_envelope[2], fut_outer_envelope[3], fut_outer_envelope[4]); + futhark_entry_next_chunk_board(fc, &fut_next_chunk_board, fut_chunk_board, fut_outer_envelope); futhark_context_sync(fc); futhark_values_i8_2d(fc, fut_next_chunk_board, ci->data); @@ -51,8 +47,7 @@ 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_outer_envelope_free(dc, fc, (int (*)(struct futhark_context *, void *)) futhark_free_i8_2d, - (void **) fut_outer_envelope); + futhark_free_opaque_envelope_2d_i8(fc, fut_outer_envelope); envelope_free(&outer_envelope); } @@ -70,6 +65,7 @@ int main(int argc, char *argv[]) { struct futhark_context_config *fut_config = futhark_context_config_new(); int nb_devices = atoi(argv[1]); #if defined(FUTHARK_BACKEND_cuda) || defined(FUTHARK_BACKEND_opencl) + futhark_context_config_list_devices(fut_config); char device[4] = {0}; snprintf(device, sizeof(device), "#%d", my_rank % nb_devices); futhark_context_config_set_device(fut_config, device); diff --git a/game_of_life/benchmark/plot_result.py b/game_of_life/benchmark/plot_result.py old mode 100644 new mode 100755 index 692d9cf153159da1e1665f899dba4ad57d933607..fb43ade73e3571161eb7c94ec90ac3a03fbbe806 --- a/game_of_life/benchmark/plot_result.py +++ b/game_of_life/benchmark/plot_result.py @@ -12,9 +12,9 @@ RESULT_APPEND_FILENAME = "result_and_speedup.png" def plot(xs, ys, stds): fig, ax = plt.subplots() - ax.plot(xs, ys, label="Multicore") + ax.plot(xs, ys, label="OpenCL") ax.set(xlabel="Nombre de tâches", ylabel='Temps (secondes)', - title=f"Jeu de la vie\nCalcul de la prochaine génération avec\n une matrice de 60000x60000") + title=f"Jeu de la vie\nCalcul de 100 générations avec \nune matrice de 30'000x30'000") ax.grid() plt.tight_layout() plt.legend() @@ -27,7 +27,7 @@ def plot_speedup(xs, ys): ax.plot(xs, ys, label="Speedup obtenu") ax.plot(xs, xs, label="Speedup idéal") ax.set(xlabel="Nombre de tâches", ylabel='Speedup', - title=f"Jeu de la vie\nSpeedup du calcul de la prochaine génération avec\n une matrice de 60000x60000") + title=f"Jeu de la vie\nSpeedup du calcul de 100 générations avec \nune matrice de 30'000x30'000") ax.grid() plt.tight_layout() plt.legend() @@ -36,7 +36,7 @@ def plot_speedup(xs, ys): def main(): - results = np.genfromtxt('results/gol-multicore-2021-06-05.csv', delimiter=';') + results = np.genfromtxt('results/gol-opencl-2021-06-13.csv', delimiter=';') results_ordered = {} for result in results: key = int(result[0]) diff --git a/game_of_life/gol.fut b/game_of_life/gol.fut index 98a053873a87255b39df13dcf2540c865bf9b33e..55cd8f3c76b0663087ac2fceabcc44d9a1d6fff8 100644 --- a/game_of_life/gol.fut +++ b/game_of_life/gol.fut @@ -1,9 +1,33 @@ module env = import "../futhark_mpi/envelope" -entry get_envelope_1d = env.get_envelope_1d -entry get_envelope_2d = env.get_envelope_2d +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] + +type~ envelope_1d_i8 = { + west: []i8, -- 1 + east: []i8 -- 0 +} + +type~ envelope_2d_i8 = { + north_west: [][]i8, -- 3 + west: [][]i8, -- 7 + south_west: [][]i8, -- 6 + south: [][]i8, -- 4 + south_east: [][]i8, -- 5 + east: [][]i8, -- 0 + north_east: [][]i8, -- 2 + north: [][]i8 -- 1 +} + +entry get_envelope_1d [n] (xs: [n]u8) (thickness: i64) : envelope_1d_t [thickness] = + env.get_envelope_1d xs thickness + +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] = + env.get_envelope_2d matrix thickness_y thickness_x + entry get_subdomain_1d = env.get_subdomain_1d entry get_subdomain_2d = env.get_subdomain_2d +entry get_subdomain_3d = env.get_subdomain_3d let count_neighbours [n][m] (board: [n][m]i8) : [n][m]i8 = let north = rotate (-1) board @@ -21,35 +45,33 @@ let count_neighbours [n][m] (board: [n][m]i8) : [n][m]i8 = (zip3 nwr nr ner) (zip3 wr br er) (zip3 swr sr ser)) (zip3 north_west north north_east) (zip3 west board east) (zip3 south_west south south_east) -let augment_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 = +let augment_board [n][m] (chunk_board:[n][m]i8) (envelope: envelope_2d_i8) :[][]i8 = tabulate_2d (n+2) (m+2) (\i j -> -- North-West - if (i == 0 && j == 0) then nw[0,0] + if (i == 0 && j == 0) then envelope.north_west[0,0] -- North-East - else if (i == 0 && j == m+1) then ne[0,0] + else if (i == 0 && j == m+1) then envelope.north_east[0,0] -- South-West - else if (i == n+1 && j == 0) then sw[0,0] + else if (i == n+1 && j == 0) then envelope.south_west[0,0] -- South-East - else if (i == n+1 && j == m+1) then se[0,0] + else if (i == n+1 && j == m+1) then envelope.south_east[0,0] -- North - else if (i == 0) then no[0, j-1] + else if (i == 0) then envelope.north[0, j-1] -- West - else if (j == 0) then we[i-1, 0] + else if (j == 0) then envelope.west[i-1, 0] -- East - else if (j == m + 1) then ea[i-1, 0] + else if (j == m + 1) then envelope.east[i-1, 0] -- South - else if (i == n+1) then so[0,j-1] + else if (i == n+1) then envelope.south[0,j-1] else chunk_board[i-1, j-1] ) -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) :[n][m]i8 = - let augmented_board = augment_board chunk_board nw no ne we ea sw so se +-- (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) + +entry next_chunk_board [n][m] (chunk_board :[n][m]i8) (envelope: envelope_2d_i8) :[n][m]i8 = + let augmented_board = augment_board chunk_board envelope let neighbours = count_neighbours augmented_board let next_board = map2 (\augmented_board_r neighbours_r -> map2(\cell nb_alive_cells -> diff --git a/game_of_life/main.c b/game_of_life/main.c index f393772549a45083237820ebddba8c9ca9849b5d..ec5cef6e59cd6a3ac01ada8270df0854ba5c0054 100644 --- a/game_of_life/main.c +++ b/game_of_life/main.c @@ -31,19 +31,15 @@ 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_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_opaque_envelope_2d_i8 *fut_outer_envelope = futhark_outer_envelope_new(dc, fc, &outer_envelope, + futhark_restore_opaque_envelope_2d_i8, + FUT_I8); 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_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_entry_next_chunk_board(fc, &fut_next_chunk_board, fut_chunk_board, fut_outer_envelope); futhark_context_sync(fc); futhark_values_i8_2d(fc, fut_next_chunk_board, ci->data); @@ -51,8 +47,7 @@ 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_outer_envelope_free(dc, fc, (int (*)(struct futhark_context *, void *)) futhark_free_i8_2d, - (void **) fut_outer_envelope); + futhark_free_opaque_envelope_2d_i8(fc, fut_outer_envelope); envelope_free(&outer_envelope); }