From c846568cf28b4d128cf893dc0abb6ccb5ccdcc32 Mon Sep 17 00:00:00 2001 From: Logan Hunt Date: Wed, 8 Dec 2021 01:50:12 -0700 Subject: [PATCH] Timing study --- cuda-global/gol | Bin 709816 -> 709816 bytes cuda-global/src/game.cu | 9 ++- cuda-global/src/main.cu | 56 ++++++++------ .../timing-study/output--1000-1000.txt | 4 + .../timing-study/output--1000-1250.txt | 4 + .../timing-study/output--1000-1500.txt | 4 + .../timing-study/output--1000-1750.txt | 4 + .../timing-study/output--1000-2000.txt | 4 + cuda-global/timing-study/output--1000-250.txt | 4 + cuda-global/timing-study/output--1000-500.txt | 4 + cuda-global/timing-study/output--1000-750.txt | 4 + .../timing-study/slurm-3610476.err-notch081 | 0 .../timing-study/slurm-3610476.out-notch081 | 0 .../timing-study/slurm-3611549.err-notch081 | 0 .../timing-study/slurm-3611549.out-notch081 | 0 cuda-global/timing-study/timing_study.sh | 18 +++++ mpi/gol | Bin 155352 -> 152224 bytes mpi/src/main.c | 69 +++++++++++++----- mpi/timing-study/output-1-1000-1000.txt | 4 + mpi/timing-study/output-1-1000-1250.txt | 11 +++ mpi/timing-study/output-1-1000-1500.txt | 4 + mpi/timing-study/output-1-1000-1750.txt | 11 +++ mpi/timing-study/output-1-1000-2000.txt | 4 + mpi/timing-study/output-1-1000-250.txt | 4 + mpi/timing-study/output-1-1000-500.txt | 4 + mpi/timing-study/output-1-1000-750.txt | 4 + mpi/timing-study/output-12-1000-1000.txt | 4 + mpi/timing-study/output-12-1000-1250.txt | 4 + mpi/timing-study/output-12-1000-1500.txt | 11 +++ mpi/timing-study/output-12-1000-1750.txt | 4 + mpi/timing-study/output-12-1000-2000.txt | 11 +++ mpi/timing-study/output-12-1000-250.txt | 4 + mpi/timing-study/output-12-1000-500.txt | 4 + mpi/timing-study/output-12-1000-750.txt | 4 + mpi/timing-study/output-16-1000-1000.txt | 4 + mpi/timing-study/output-16-1000-1250.txt | 4 + mpi/timing-study/output-16-1000-1500.txt | 4 + mpi/timing-study/output-16-1000-1750.txt | 8 ++ mpi/timing-study/output-16-1000-2000.txt | 4 + mpi/timing-study/output-16-1000-250.txt | 4 + mpi/timing-study/output-16-1000-500.txt | 4 + mpi/timing-study/output-16-1000-750.txt | 4 + mpi/timing-study/output-20-1000-250.txt | 0 mpi/timing-study/output-24-1000-1000.txt | 4 + mpi/timing-study/output-24-1000-1250.txt | 4 + mpi/timing-study/output-24-1000-1500.txt | 4 + mpi/timing-study/output-24-1000-1750.txt | 4 + mpi/timing-study/output-24-1000-2000.txt | 4 + mpi/timing-study/output-24-1000-250.txt | 4 + mpi/timing-study/output-24-1000-500.txt | 4 + mpi/timing-study/output-24-1000-750.txt | 4 + mpi/timing-study/output-4-1000-1000.txt | 4 + mpi/timing-study/output-4-1000-1250.txt | 11 +++ mpi/timing-study/output-4-1000-1500.txt | 4 + mpi/timing-study/output-4-1000-1750.txt | 11 +++ mpi/timing-study/output-4-1000-2000.txt | 4 + mpi/timing-study/output-4-1000-250.txt | 4 + mpi/timing-study/output-4-1000-500.txt | 4 + mpi/timing-study/output-4-1000-750.txt | 4 + mpi/timing-study/output-8-1000-1000.txt | 4 + mpi/timing-study/output-8-1000-1250.txt | 11 +++ mpi/timing-study/output-8-1000-1500.txt | 4 + mpi/timing-study/output-8-1000-1750.txt | 4 + mpi/timing-study/output-8-1000-2000.txt | 4 + mpi/timing-study/output-8-1000-250.txt | 4 + mpi/timing-study/output-8-1000-500.txt | 4 + mpi/timing-study/output-8-1000-750.txt | 4 + mpi/timing-study/slurm-10870703.err-kp013 | 11 +++ mpi/timing-study/slurm-10870703.out-kp013 | 0 mpi/timing-study/timing_study.sh | 24 ++++++ openmp/src/create_grid.c | 2 + openmp/src/file.c | 2 + openmp/src/game.c | 5 ++ openmp/src/main.c | 9 ++- openmp/timing-study/output-1-1000-1000.txt | 4 + openmp/timing-study/output-1-1000-1250.txt | 4 + openmp/timing-study/output-1-1000-1500.txt | 4 + openmp/timing-study/output-1-1000-1750.txt | 4 + openmp/timing-study/output-1-1000-2000.txt | 4 + openmp/timing-study/output-1-1000-250.txt | 4 + openmp/timing-study/output-1-1000-500.txt | 4 + openmp/timing-study/output-1-1000-750.txt | 4 + openmp/timing-study/output-12-1000-1000.txt | 4 + openmp/timing-study/output-12-1000-1250.txt | 4 + openmp/timing-study/output-12-1000-1500.txt | 4 + openmp/timing-study/output-12-1000-1750.txt | 4 + openmp/timing-study/output-12-1000-2000.txt | 4 + openmp/timing-study/output-12-1000-250.txt | 4 + openmp/timing-study/output-12-1000-500.txt | 4 + openmp/timing-study/output-12-1000-750.txt | 4 + openmp/timing-study/output-16-1000-1000.txt | 4 + openmp/timing-study/output-16-1000-1250.txt | 4 + openmp/timing-study/output-16-1000-1500.txt | 4 + openmp/timing-study/output-16-1000-1750.txt | 4 + openmp/timing-study/output-16-1000-2000.txt | 4 + openmp/timing-study/output-16-1000-250.txt | 4 + openmp/timing-study/output-16-1000-500.txt | 4 + openmp/timing-study/output-16-1000-750.txt | 4 + openmp/timing-study/output-20-1000-1000.txt | 4 + openmp/timing-study/output-20-1000-1250.txt | 4 + openmp/timing-study/output-20-1000-1500.txt | 4 + openmp/timing-study/output-20-1000-1750.txt | 4 + openmp/timing-study/output-20-1000-2000.txt | 4 + openmp/timing-study/output-20-1000-250.txt | 4 + openmp/timing-study/output-20-1000-500.txt | 4 + openmp/timing-study/output-20-1000-750.txt | 4 + openmp/timing-study/output-24-1000-1000.txt | 4 + openmp/timing-study/output-24-1000-1250.txt | 4 + openmp/timing-study/output-24-1000-1500.txt | 4 + openmp/timing-study/output-24-1000-1750.txt | 4 + openmp/timing-study/output-24-1000-2000.txt | 4 + openmp/timing-study/output-24-1000-250.txt | 4 + openmp/timing-study/output-24-1000-500.txt | 4 + openmp/timing-study/output-24-1000-750.txt | 4 + openmp/timing-study/output-4-1000-1000.txt | 4 + openmp/timing-study/output-4-1000-1250.txt | 4 + openmp/timing-study/output-4-1000-1500.txt | 4 + openmp/timing-study/output-4-1000-1750.txt | 4 + openmp/timing-study/output-4-1000-2000.txt | 4 + openmp/timing-study/output-4-1000-250.txt | 4 + openmp/timing-study/output-4-1000-500.txt | 4 + openmp/timing-study/output-4-1000-750.txt | 4 + openmp/timing-study/output-8-1000-1000.txt | 4 + openmp/timing-study/output-8-1000-1250.txt | 4 + openmp/timing-study/output-8-1000-1500.txt | 4 + openmp/timing-study/output-8-1000-1750.txt | 4 + openmp/timing-study/output-8-1000-2000.txt | 4 + openmp/timing-study/output-8-1000-250.txt | 4 + openmp/timing-study/output-8-1000-500.txt | 4 + openmp/timing-study/output-8-1000-750.txt | 4 + openmp/timing-study/slurm-10870649.err-kp013 | 1 + openmp/timing-study/slurm-10870649.out-kp013 | 0 openmp/timing-study/slurm-10870651.err-kp013 | 1 + openmp/timing-study/slurm-10870651.out-kp013 | 0 openmp/timing-study/slurm-10870663.err-kp013 | 0 openmp/timing-study/slurm-10870663.out-kp013 | 0 openmp/timing-study/timing_study.sh | 23 ++++++ serial/src/create_grid.c | 2 + serial/src/file.c | 2 + serial/src/game.c | 4 + serial/src/main.c | 11 ++- serial/timing-study/output-1-1000-1000.txt | 4 + serial/timing-study/output-1-1000-1250.txt | 4 + serial/timing-study/output-1-1000-1500.txt | 4 + serial/timing-study/output-1-1000-1750.txt | 4 + serial/timing-study/output-1-1000-2000.txt | 4 + serial/timing-study/output-1-1000-250.txt | 4 + serial/timing-study/output-1-1000-500.txt | 4 + serial/timing-study/output-1-1000-750.txt | 4 + serial/timing-study/slurm-10870643.err-kp013 | 0 serial/timing-study/slurm-10870643.out-kp013 | 0 serial/timing-study/timing_study.sh | 19 +++++ 152 files changed, 755 insertions(+), 46 deletions(-) create mode 100644 cuda-global/timing-study/output--1000-1000.txt create mode 100644 cuda-global/timing-study/output--1000-1250.txt create mode 100644 cuda-global/timing-study/output--1000-1500.txt create mode 100644 cuda-global/timing-study/output--1000-1750.txt create mode 100644 cuda-global/timing-study/output--1000-2000.txt create mode 100644 cuda-global/timing-study/output--1000-250.txt create mode 100644 cuda-global/timing-study/output--1000-500.txt create mode 100644 cuda-global/timing-study/output--1000-750.txt create mode 100644 cuda-global/timing-study/slurm-3610476.err-notch081 create mode 100644 cuda-global/timing-study/slurm-3610476.out-notch081 create mode 100644 cuda-global/timing-study/slurm-3611549.err-notch081 create mode 100644 cuda-global/timing-study/slurm-3611549.out-notch081 create mode 100755 cuda-global/timing-study/timing_study.sh create mode 100644 mpi/timing-study/output-1-1000-1000.txt create mode 100644 mpi/timing-study/output-1-1000-1250.txt create mode 100644 mpi/timing-study/output-1-1000-1500.txt create mode 100644 mpi/timing-study/output-1-1000-1750.txt create mode 100644 mpi/timing-study/output-1-1000-2000.txt create mode 100644 mpi/timing-study/output-1-1000-250.txt create mode 100644 mpi/timing-study/output-1-1000-500.txt create mode 100644 mpi/timing-study/output-1-1000-750.txt create mode 100644 mpi/timing-study/output-12-1000-1000.txt create mode 100644 mpi/timing-study/output-12-1000-1250.txt create mode 100644 mpi/timing-study/output-12-1000-1500.txt create mode 100644 mpi/timing-study/output-12-1000-1750.txt create mode 100644 mpi/timing-study/output-12-1000-2000.txt create mode 100644 mpi/timing-study/output-12-1000-250.txt create mode 100644 mpi/timing-study/output-12-1000-500.txt create mode 100644 mpi/timing-study/output-12-1000-750.txt create mode 100644 mpi/timing-study/output-16-1000-1000.txt create mode 100644 mpi/timing-study/output-16-1000-1250.txt create mode 100644 mpi/timing-study/output-16-1000-1500.txt create mode 100644 mpi/timing-study/output-16-1000-1750.txt create mode 100644 mpi/timing-study/output-16-1000-2000.txt create mode 100644 mpi/timing-study/output-16-1000-250.txt create mode 100644 mpi/timing-study/output-16-1000-500.txt create mode 100644 mpi/timing-study/output-16-1000-750.txt create mode 100644 mpi/timing-study/output-20-1000-250.txt create mode 100644 mpi/timing-study/output-24-1000-1000.txt create mode 100644 mpi/timing-study/output-24-1000-1250.txt create mode 100644 mpi/timing-study/output-24-1000-1500.txt create mode 100644 mpi/timing-study/output-24-1000-1750.txt create mode 100644 mpi/timing-study/output-24-1000-2000.txt create mode 100644 mpi/timing-study/output-24-1000-250.txt create mode 100644 mpi/timing-study/output-24-1000-500.txt create mode 100644 mpi/timing-study/output-24-1000-750.txt create mode 100644 mpi/timing-study/output-4-1000-1000.txt create mode 100644 mpi/timing-study/output-4-1000-1250.txt create mode 100644 mpi/timing-study/output-4-1000-1500.txt create mode 100644 mpi/timing-study/output-4-1000-1750.txt create mode 100644 mpi/timing-study/output-4-1000-2000.txt create mode 100644 mpi/timing-study/output-4-1000-250.txt create mode 100644 mpi/timing-study/output-4-1000-500.txt create mode 100644 mpi/timing-study/output-4-1000-750.txt create mode 100644 mpi/timing-study/output-8-1000-1000.txt create mode 100644 mpi/timing-study/output-8-1000-1250.txt create mode 100644 mpi/timing-study/output-8-1000-1500.txt create mode 100644 mpi/timing-study/output-8-1000-1750.txt create mode 100644 mpi/timing-study/output-8-1000-2000.txt create mode 100644 mpi/timing-study/output-8-1000-250.txt create mode 100644 mpi/timing-study/output-8-1000-500.txt create mode 100644 mpi/timing-study/output-8-1000-750.txt create mode 100644 mpi/timing-study/slurm-10870703.err-kp013 create mode 100644 mpi/timing-study/slurm-10870703.out-kp013 create mode 100644 mpi/timing-study/timing_study.sh create mode 100644 openmp/timing-study/output-1-1000-1000.txt create mode 100644 openmp/timing-study/output-1-1000-1250.txt create mode 100644 openmp/timing-study/output-1-1000-1500.txt create mode 100644 openmp/timing-study/output-1-1000-1750.txt create mode 100644 openmp/timing-study/output-1-1000-2000.txt create mode 100644 openmp/timing-study/output-1-1000-250.txt create mode 100644 openmp/timing-study/output-1-1000-500.txt create mode 100644 openmp/timing-study/output-1-1000-750.txt create mode 100644 openmp/timing-study/output-12-1000-1000.txt create mode 100644 openmp/timing-study/output-12-1000-1250.txt create mode 100644 openmp/timing-study/output-12-1000-1500.txt create mode 100644 openmp/timing-study/output-12-1000-1750.txt create mode 100644 openmp/timing-study/output-12-1000-2000.txt create mode 100644 openmp/timing-study/output-12-1000-250.txt create mode 100644 openmp/timing-study/output-12-1000-500.txt create mode 100644 openmp/timing-study/output-12-1000-750.txt create mode 100644 openmp/timing-study/output-16-1000-1000.txt create mode 100644 openmp/timing-study/output-16-1000-1250.txt create mode 100644 openmp/timing-study/output-16-1000-1500.txt create mode 100644 openmp/timing-study/output-16-1000-1750.txt create mode 100644 openmp/timing-study/output-16-1000-2000.txt create mode 100644 openmp/timing-study/output-16-1000-250.txt create mode 100644 openmp/timing-study/output-16-1000-500.txt create mode 100644 openmp/timing-study/output-16-1000-750.txt create mode 100644 openmp/timing-study/output-20-1000-1000.txt create mode 100644 openmp/timing-study/output-20-1000-1250.txt create mode 100644 openmp/timing-study/output-20-1000-1500.txt create mode 100644 openmp/timing-study/output-20-1000-1750.txt create mode 100644 openmp/timing-study/output-20-1000-2000.txt create mode 100644 openmp/timing-study/output-20-1000-250.txt create mode 100644 openmp/timing-study/output-20-1000-500.txt create mode 100644 openmp/timing-study/output-20-1000-750.txt create mode 100644 openmp/timing-study/output-24-1000-1000.txt create mode 100644 openmp/timing-study/output-24-1000-1250.txt create mode 100644 openmp/timing-study/output-24-1000-1500.txt create mode 100644 openmp/timing-study/output-24-1000-1750.txt create mode 100644 openmp/timing-study/output-24-1000-2000.txt create mode 100644 openmp/timing-study/output-24-1000-250.txt create mode 100644 openmp/timing-study/output-24-1000-500.txt create mode 100644 openmp/timing-study/output-24-1000-750.txt create mode 100644 openmp/timing-study/output-4-1000-1000.txt create mode 100644 openmp/timing-study/output-4-1000-1250.txt create mode 100644 openmp/timing-study/output-4-1000-1500.txt create mode 100644 openmp/timing-study/output-4-1000-1750.txt create mode 100644 openmp/timing-study/output-4-1000-2000.txt create mode 100644 openmp/timing-study/output-4-1000-250.txt create mode 100644 openmp/timing-study/output-4-1000-500.txt create mode 100644 openmp/timing-study/output-4-1000-750.txt create mode 100644 openmp/timing-study/output-8-1000-1000.txt create mode 100644 openmp/timing-study/output-8-1000-1250.txt create mode 100644 openmp/timing-study/output-8-1000-1500.txt create mode 100644 openmp/timing-study/output-8-1000-1750.txt create mode 100644 openmp/timing-study/output-8-1000-2000.txt create mode 100644 openmp/timing-study/output-8-1000-250.txt create mode 100644 openmp/timing-study/output-8-1000-500.txt create mode 100644 openmp/timing-study/output-8-1000-750.txt create mode 100644 openmp/timing-study/slurm-10870649.err-kp013 create mode 100644 openmp/timing-study/slurm-10870649.out-kp013 create mode 100644 openmp/timing-study/slurm-10870651.err-kp013 create mode 100644 openmp/timing-study/slurm-10870651.out-kp013 create mode 100644 openmp/timing-study/slurm-10870663.err-kp013 create mode 100644 openmp/timing-study/slurm-10870663.out-kp013 create mode 100644 openmp/timing-study/timing_study.sh create mode 100644 serial/timing-study/output-1-1000-1000.txt create mode 100644 serial/timing-study/output-1-1000-1250.txt create mode 100644 serial/timing-study/output-1-1000-1500.txt create mode 100644 serial/timing-study/output-1-1000-1750.txt create mode 100644 serial/timing-study/output-1-1000-2000.txt create mode 100644 serial/timing-study/output-1-1000-250.txt create mode 100644 serial/timing-study/output-1-1000-500.txt create mode 100644 serial/timing-study/output-1-1000-750.txt create mode 100644 serial/timing-study/slurm-10870643.err-kp013 create mode 100644 serial/timing-study/slurm-10870643.out-kp013 create mode 100644 serial/timing-study/timing_study.sh diff --git a/cuda-global/gol b/cuda-global/gol index 4fb8b817c9ad9dba6673d5dec890232da52a50c7..85af8de88d4c0dc710945aa7bdb5c31c31a88472 100755 GIT binary patch delta 109557 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 WUCQoBZkXhHkWF1{JMKyDpZNbzrtX&j delta 108640 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 TseWSqBW#+#y2GxdzVZJL!oUv9 diff --git a/cuda-global/src/game.cu b/cuda-global/src/game.cu index b0b5f61..abb5ed9 100644 --- a/cuda-global/src/game.cu +++ b/cuda-global/src/game.cu @@ -1,11 +1,12 @@ #include "game.cuh" +// Count the number of life neighbors a cell has __device__ int neighbors(struct GAME game, int x, int y) { int n = 0; for (int dy = -1; dy <= 1; dy++) { for (int dx = -1; dx <= 1; dx++) { - if (!(dx == 0 && dy == 0) && (x+dx) >= 0 && (y+dy) >= 0 && (x+dx) < game.width+(game.padding*2) && (y+dy) < game.height+(game.padding*2)) { + if (!(dx == 0 && dy == 0) && (x+dx) > 0 && (y+dy) > 0 && (x+dx) < game.width+(game.padding*2) && (y+dy) < game.height+(game.padding*2)) { if (game.grid[(y+dy) * (game.width+game.padding*2) + (x+dx)]) { n++; } @@ -15,11 +16,14 @@ __device__ int neighbors(struct GAME game, int x, int y) { return n; } +// Compute the next iteration of a board +// We have to give it the newGrid as a parameter otherwise +// each block will be computing its own version of the next grid __global__ void next(struct GAME game, unsigned char* newGrid) { int idy = blockDim.y * blockIdx.y + threadIdx.y; int idx = blockDim.x * blockIdx.x + threadIdx.x; - if (idy <= game.height+game.padding*2 && idx <= game.width+game.padding*2) { + if (idy < game.height+game.padding*2 && idx < game.width+game.padding*2) { int my_neighbors = neighbors(game, idx, idy); int my_coord = idy * (game.width+game.padding*2) + idx; newGrid[my_coord] = 0; // It's possible that there are artifacts from the last iteration @@ -37,6 +41,7 @@ __global__ void next(struct GAME game, unsigned char* newGrid) { } } +// Randomly assign life value to each cell void randomize(struct GAME* game) { for (int y = game->padding; y < game->height+game->padding; y++) { for (int x = game->padding; x < game->width+game->padding; x++) { diff --git a/cuda-global/src/main.cu b/cuda-global/src/main.cu index f906b2a..41c2abf 100644 --- a/cuda-global/src/main.cu +++ b/cuda-global/src/main.cu @@ -18,7 +18,7 @@ */ #define BLOCK 32 #define PADDING 10 -#define VERBOSE 1 +//#define VERBOSE 1 #define SEED 100 // gpuErrchk source: https://stackoverflow.com/questions/14038589/what-is-the-canonical-way-to-check-for-errors-using-the-cuda-runtime-api @@ -33,14 +33,16 @@ true) { } } +// Do the simulation void simulate(int argc, char** argv) { srand(SEED); - clock_t totalStart = clock(); + clock_t global_start = clock(); char* filename; struct GAME game; game.padding = PADDING; int iterations, log_each_step; if (argc == 7) { + // Parse the arguments filename = argv[2]; game.width = atoi(argv[3]); game.height = atoi(argv[4]); @@ -60,6 +62,7 @@ void simulate(int argc, char** argv) { game.grid = (unsigned char*)malloc(size); memset(game.grid, 0, size); + // Choose where to read initial position if (strcmp(filename, "random") == 0) { randomize(&game); } else { @@ -68,43 +71,53 @@ void simulate(int argc, char** argv) { char iteration_file[1024]; + // Allocate device memory unsigned char* grid_d; unsigned char* newGrid; gpuErrchk(cudaMalloc(&grid_d, size)); - gpuErrchk(cudaMemcpy(grid_d, game.grid, size, cudaMemcpyHostToDevice)); gpuErrchk(cudaMalloc(&newGrid, size)); + gpuErrchk(cudaMemcpy(grid_d, game.grid, size, cudaMemcpyHostToDevice)); // Copy the initial grid to the device + free(game.grid); + game.grid = grid_d; // Use the device copy + // The grid that we will copy results unsigned char* grid_h = (unsigned char*)malloc(size); unsigned char* temp; - game.grid = grid_d; - - int grid_num = (int)ceil((game.width+(2*game.padding))/(float)BLOCK); - dim3 dim_grid(grid_num, grid_num, 1); + // Calculate grid width for kernel + int grid_width = (int)ceil((game.width+(2*game.padding))/(float)BLOCK); + int grid_height = (int)ceil((game.height+(2*game.padding))/(float)BLOCK); + dim3 dim_grid(grid_width, grid_height, 1); dim3 dim_block(BLOCK, BLOCK, 1); - cudaEvent_t startLife, stopLife; - cudaEventCreate(&startLife); - cudaEventCreate(&stopLife); - double timeComputingLife = 0; - float localTime = 0; + // Timing + cudaEvent_t start, end; + cudaEventCreate(&start); + cudaEventCreate(&end); + double time_computing_life = 0; + float local_time = 0; for (int i = 0; i <= iterations; i++) { + // Iteration 0 will just be the initial grid if (i > 0) { - cudaEventRecord(startLife); + cudaEventRecord(start); + // Compute the next grid next<<>>(game, newGrid); - cudaEventRecord(stopLife); - cudaEventSynchronize(stopLife); - cudaEventElapsedTime(&localTime, startLife, stopLife); - timeComputingLife += localTime/1000; + cudaEventRecord(end); + cudaEventSynchronize(end); + cudaEventElapsedTime(&local_time, start, end); + time_computing_life += local_time/1000; + // Swap game.grid and newGrid temp = game.grid; game.grid = newGrid; newGrid = temp; } if (log_each_step) { + // If we are logging each step, perform IO operations gpuErrchk(cudaMemcpy(grid_h, game.grid, size, cudaMemcpyDeviceToHost)); #ifdef VERBOSE + // Print the board without the padding elements printf("\n===Iteration %i===\n", i); for (int y = game.padding; y < game.height+game.padding; y++) { for (int x = game.padding; x < game.width+game.padding; x++) { @@ -114,6 +127,7 @@ void simulate(int argc, char** argv) { } printf("===End iteration %i===\n", i); #endif + // Save to a file sprintf(iteration_file, "output/iteration-%07d.bin", i); temp = game.grid; game.grid = grid_h; @@ -122,13 +136,7 @@ void simulate(int argc, char** argv) { } } - clock_t totalEnd = clock(); - printf("\n===Timing===\nTime computing life: %f\nClock time: %f\n", timeComputingLife, ((double)totalEnd - (double)totalStart)/CLOCKS_PER_SEC); - - cudaFree(&newGrid); - cudaFree(&grid_d); - cudaFree(&game.grid); - free(grid_h); + printf("\n===Timing===\nTime computing life: %f\nClock time: %f\n", time_computing_life, ((double)clock() - (double)global_start)/CLOCKS_PER_SEC); } int main(int argc, char** argv) { diff --git a/cuda-global/timing-study/output--1000-1000.txt b/cuda-global/timing-study/output--1000-1000.txt new file mode 100644 index 0000000..3792efc --- /dev/null +++ b/cuda-global/timing-study/output--1000-1000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 0.169687 +Clock time: 1.560000 diff --git a/cuda-global/timing-study/output--1000-1250.txt b/cuda-global/timing-study/output--1000-1250.txt new file mode 100644 index 0000000..9081eb5 --- /dev/null +++ b/cuda-global/timing-study/output--1000-1250.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 0.254989 +Clock time: 2.240000 diff --git a/cuda-global/timing-study/output--1000-1500.txt b/cuda-global/timing-study/output--1000-1500.txt new file mode 100644 index 0000000..c2fafe8 --- /dev/null +++ b/cuda-global/timing-study/output--1000-1500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 0.354361 +Clock time: 3.050000 diff --git a/cuda-global/timing-study/output--1000-1750.txt b/cuda-global/timing-study/output--1000-1750.txt new file mode 100644 index 0000000..557165e --- /dev/null +++ b/cuda-global/timing-study/output--1000-1750.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 0.480174 +Clock time: 4.070000 diff --git a/cuda-global/timing-study/output--1000-2000.txt b/cuda-global/timing-study/output--1000-2000.txt new file mode 100644 index 0000000..91a9d45 --- /dev/null +++ b/cuda-global/timing-study/output--1000-2000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 0.619636 +Clock time: 5.220000 diff --git a/cuda-global/timing-study/output--1000-250.txt b/cuda-global/timing-study/output--1000-250.txt new file mode 100644 index 0000000..0808a20 --- /dev/null +++ b/cuda-global/timing-study/output--1000-250.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 0.029867 +Clock time: 0.330000 diff --git a/cuda-global/timing-study/output--1000-500.txt b/cuda-global/timing-study/output--1000-500.txt new file mode 100644 index 0000000..913b15e --- /dev/null +++ b/cuda-global/timing-study/output--1000-500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 0.059907 +Clock time: 0.540000 diff --git a/cuda-global/timing-study/output--1000-750.txt b/cuda-global/timing-study/output--1000-750.txt new file mode 100644 index 0000000..e3b8c5d --- /dev/null +++ b/cuda-global/timing-study/output--1000-750.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 0.110954 +Clock time: 1.000000 diff --git a/cuda-global/timing-study/slurm-3610476.err-notch081 b/cuda-global/timing-study/slurm-3610476.err-notch081 new file mode 100644 index 0000000..e69de29 diff --git a/cuda-global/timing-study/slurm-3610476.out-notch081 b/cuda-global/timing-study/slurm-3610476.out-notch081 new file mode 100644 index 0000000..e69de29 diff --git a/cuda-global/timing-study/slurm-3611549.err-notch081 b/cuda-global/timing-study/slurm-3611549.err-notch081 new file mode 100644 index 0000000..e69de29 diff --git a/cuda-global/timing-study/slurm-3611549.out-notch081 b/cuda-global/timing-study/slurm-3611549.out-notch081 new file mode 100644 index 0000000..e69de29 diff --git a/cuda-global/timing-study/timing_study.sh b/cuda-global/timing-study/timing_study.sh new file mode 100755 index 0000000..ef7ebcb --- /dev/null +++ b/cuda-global/timing-study/timing_study.sh @@ -0,0 +1,18 @@ +#!/bin/bash +#SBATCH --time=0:30:00 # walltime, abbreviated by -t +#SBATCH --nodes=1 # number of cluster nodes, abbreviated by -N +#SBATCH -o slurm-%j.out-%N # name of the stdout, using the job number (%j) and the first node (%N) +#SBATCH -e slurm-%j.err-%N # name of the stderr, using job and first node values +#SBATCH --ntasks=1 # number of MPI tasks, abbreviated by -n +# additional information for allocated clusters +#SBATCH --account=notchpeak-shared-short # account - abbreviated by -A +#SBATCH --partition=notchpeak-shared-short # partition, abbreviated by -p +#SBATCH --gres=gpu:k80:1 + +cd $HOME/gol/cuda-global + +iterations=1000 +for size in 250 500 750 1000 1250 1500 1750 2000 +do + srun ./gol simulate random $size $size $iterations 1 > timing-study/output-$cores-$iterations-$size.txt +done diff --git a/mpi/gol b/mpi/gol index f7d934c6acd10b5827f6fb91cf88f58ec5e3ecb3..f9518e909262d1dc0eb4575f8eda8ac0282a1295 100755 GIT binary patch delta 28518 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 qUJ9j7faNS~tkSb>wN(?Ph`pH0S?poC4a*v \n"); + printf("Usage: ./gol simulate \n"); filename = "random"; args.height = 5; args.width = 5; @@ -107,12 +116,17 @@ void simulate(int argc, char** argv) { args.log_each_step = 0; } + global_start = MPI_Wtime(); + + // Figure out how much work the average node will be doing args.rows_per_proc = (args.height + args.padding*2)/args.process_count; args.data_per_proc = args.rows_per_proc * (args.width + args.padding*2); } broadcast_and_receive_input(comm, &args); + // Calculate the exact work each thread will do and arguments for + // the Scatterv to scatter the grid int grid_size = ((args.width + args.padding*2)*(args.height + args.padding*2)); int* data_counts = malloc(sizeof(int) * args.process_count); int* displacements = malloc(sizeof(int) * args.process_count); @@ -123,19 +137,20 @@ void simulate(int argc, char** argv) { data_counts[args.process_count-1] += grid_size % (args.data_per_proc * args.process_count); unsigned char* local_data = malloc(data_counts[rank]*sizeof(unsigned char)); memset(local_data, 0, sizeof(unsigned char) * data_counts[rank]); + + // Scatter the data among nodes scatter_data(comm, &args, local_data, rank, data_counts, displacements, filename); - // Allocate space for current grid (1 byte per tile) char iteration_file[1024]; - double timeComputingLife = 0; - float localTime = 0; - + // Local_game is our current job struct GAME local_game; local_game.grid = local_data; local_game.width = args.width; local_game.height = data_counts[rank] / (args.width + args.padding*2); local_game.padding = args.padding; + + // Assign halo elements to send to be received from above and below nodes unsigned char* halo_above = NULL; unsigned char* halo_below = NULL; if (rank > 0) { @@ -148,32 +163,46 @@ void simulate(int argc, char** argv) { } unsigned char* global_data; + if (rank == 0) { + global_data = malloc(sizeof(unsigned char) * grid_size); + memset(global_data, 0, sizeof(unsigned char) * grid_size); + } + + // Timing code + double time_computing_life = 0; + double start,end; for (int i = 0; i <= args.iterations; i++) { + // Iteration 0 will just be the initial grid if (i > 0) { int total_width = args.width + args.padding*2; + + MPI_Status status; if (rank < args.process_count - 1) { MPI_Send(&local_game.grid[(local_game.height-1) * total_width], total_width, MPI_UNSIGNED_CHAR, rank+1, 1, comm); } if (rank > 0) { - MPI_Recv(halo_above, total_width, MPI_UNSIGNED_CHAR, rank-1, 1, comm, NULL); + MPI_Recv(halo_above, total_width, MPI_UNSIGNED_CHAR, rank-1, 1, comm, &status); MPI_Send(&local_game.grid[0], total_width, MPI_UNSIGNED_CHAR, rank-1, 0, comm); } if (rank < args.process_count - 1) { - MPI_Recv(halo_below, total_width, MPI_UNSIGNED_CHAR, rank+1, 0, comm, NULL); + MPI_Recv(halo_below, total_width, MPI_UNSIGNED_CHAR, rank+1, 0, comm, &status); } MPI_Barrier(comm); + start = MPI_Wtime(); + // Compute the next grid next(&local_game, halo_above, halo_below); + end = MPI_Wtime(); + time_computing_life += end-start; } if (args.log_each_step) { - if (rank == 0) { - global_data = malloc(sizeof(unsigned char) * grid_size); - memset(global_data, 0, sizeof(unsigned char) * grid_size); - } + // If we are logging each step, perform IO operations + // Gather all of the local grids into global_data MPI_Gatherv(local_game.grid, data_counts[rank], MPI_UNSIGNED_CHAR, global_data, data_counts, displacements, MPI_UNSIGNED_CHAR, 0, comm); if (rank == 0) { - #ifdef VERBOSE + #if VERBOSE == 1 printf("\n===Iteration %i===\n", i); + // Print the baord without the padding elements for (int y = args.padding; y < args.height+args.padding; y++) { for (int x = args.padding; x < args.width+args.padding; x++) { printf("%s ", global_data[y*(args.width+2*args.padding) + x] ? "X" : " "); @@ -183,6 +212,7 @@ void simulate(int argc, char** argv) { printf("===End iteration %i===\n", i); #endif + // Save to a file struct GAME global_game; global_game.grid = global_data; global_game.width = args.width; @@ -194,12 +224,15 @@ void simulate(int argc, char** argv) { } } - double totalEnd = MPI_Wtime(); - MPI_Finalize(); + double total_end = MPI_Wtime(); if (rank == 0) { - printf("\n===Timing===\nTime computing life: %f\nClock time: %f\n", timeComputingLife, (totalEnd - totalStart)); + printf("\n===Timing===\nTime computing life: %f\nClock time: %f\n", time_computing_life, (total_end - global_start)); + free(local_game.grid); + free(data_counts); + free(halo_above); + free(halo_below); } - + MPI_Finalize(); } int main(int argc, char** argv) { diff --git a/mpi/timing-study/output-1-1000-1000.txt b/mpi/timing-study/output-1-1000-1000.txt new file mode 100644 index 0000000..f500f74 --- /dev/null +++ b/mpi/timing-study/output-1-1000-1000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 33.832562 +Clock time: 37.939663 diff --git a/mpi/timing-study/output-1-1000-1250.txt b/mpi/timing-study/output-1-1000-1250.txt new file mode 100644 index 0000000..f928063 --- /dev/null +++ b/mpi/timing-study/output-1-1000-1250.txt @@ -0,0 +1,11 @@ + +=================================================================================== += BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES += PID 21716 RUNNING AT kp013 += EXIT CODE: 11 += CLEANING UP REMAINING PROCESSES += YOU CAN IGNORE THE BELOW CLEANUP MESSAGES +=================================================================================== +YOUR APPLICATION TERMINATED WITH THE EXIT STRING: Segmentation fault (signal 11) +This typically refers to a problem with your application. +Please see the FAQ page for debugging suggestions diff --git a/mpi/timing-study/output-1-1000-1500.txt b/mpi/timing-study/output-1-1000-1500.txt new file mode 100644 index 0000000..d31db96 --- /dev/null +++ b/mpi/timing-study/output-1-1000-1500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 75.141736 +Clock time: 83.149478 diff --git a/mpi/timing-study/output-1-1000-1750.txt b/mpi/timing-study/output-1-1000-1750.txt new file mode 100644 index 0000000..6bbaf1f --- /dev/null +++ b/mpi/timing-study/output-1-1000-1750.txt @@ -0,0 +1,11 @@ + +=================================================================================== += BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES += PID 21837 RUNNING AT kp013 += EXIT CODE: 11 += CLEANING UP REMAINING PROCESSES += YOU CAN IGNORE THE BELOW CLEANUP MESSAGES +=================================================================================== +YOUR APPLICATION TERMINATED WITH THE EXIT STRING: Segmentation fault (signal 11) +This typically refers to a problem with your application. +Please see the FAQ page for debugging suggestions diff --git a/mpi/timing-study/output-1-1000-2000.txt b/mpi/timing-study/output-1-1000-2000.txt new file mode 100644 index 0000000..3ba37f2 --- /dev/null +++ b/mpi/timing-study/output-1-1000-2000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 132.636661 +Clock time: 145.001708 diff --git a/mpi/timing-study/output-1-1000-250.txt b/mpi/timing-study/output-1-1000-250.txt new file mode 100644 index 0000000..544de8e --- /dev/null +++ b/mpi/timing-study/output-1-1000-250.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 2.383001 +Clock time: 4.113476 diff --git a/mpi/timing-study/output-1-1000-500.txt b/mpi/timing-study/output-1-1000-500.txt new file mode 100644 index 0000000..dfa5abb --- /dev/null +++ b/mpi/timing-study/output-1-1000-500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 8.793952 +Clock time: 9.832794 diff --git a/mpi/timing-study/output-1-1000-750.txt b/mpi/timing-study/output-1-1000-750.txt new file mode 100644 index 0000000..e1437a3 --- /dev/null +++ b/mpi/timing-study/output-1-1000-750.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 19.270078 +Clock time: 21.813069 diff --git a/mpi/timing-study/output-12-1000-1000.txt b/mpi/timing-study/output-12-1000-1000.txt new file mode 100644 index 0000000..2d1c3b3 --- /dev/null +++ b/mpi/timing-study/output-12-1000-1000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 2.833550 +Clock time: 6.323680 diff --git a/mpi/timing-study/output-12-1000-1250.txt b/mpi/timing-study/output-12-1000-1250.txt new file mode 100644 index 0000000..5e8cbfb --- /dev/null +++ b/mpi/timing-study/output-12-1000-1250.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 4.347700 +Clock time: 9.178630 diff --git a/mpi/timing-study/output-12-1000-1500.txt b/mpi/timing-study/output-12-1000-1500.txt new file mode 100644 index 0000000..206bf6c --- /dev/null +++ b/mpi/timing-study/output-12-1000-1500.txt @@ -0,0 +1,11 @@ + +=================================================================================== += BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES += PID 23209 RUNNING AT kp013 += EXIT CODE: 11 += CLEANING UP REMAINING PROCESSES += YOU CAN IGNORE THE BELOW CLEANUP MESSAGES +=================================================================================== +YOUR APPLICATION TERMINATED WITH THE EXIT STRING: Segmentation fault (signal 11) +This typically refers to a problem with your application. +Please see the FAQ page for debugging suggestions diff --git a/mpi/timing-study/output-12-1000-1750.txt b/mpi/timing-study/output-12-1000-1750.txt new file mode 100644 index 0000000..f2798ae --- /dev/null +++ b/mpi/timing-study/output-12-1000-1750.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 8.483342 +Clock time: 17.330302 diff --git a/mpi/timing-study/output-12-1000-2000.txt b/mpi/timing-study/output-12-1000-2000.txt new file mode 100644 index 0000000..165b598 --- /dev/null +++ b/mpi/timing-study/output-12-1000-2000.txt @@ -0,0 +1,11 @@ + +=================================================================================== += BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES += PID 23290 RUNNING AT kp013 += EXIT CODE: 11 += CLEANING UP REMAINING PROCESSES += YOU CAN IGNORE THE BELOW CLEANUP MESSAGES +=================================================================================== +YOUR APPLICATION TERMINATED WITH THE EXIT STRING: Segmentation fault (signal 11) +This typically refers to a problem with your application. +Please see the FAQ page for debugging suggestions diff --git a/mpi/timing-study/output-12-1000-250.txt b/mpi/timing-study/output-12-1000-250.txt new file mode 100644 index 0000000..e4be53e --- /dev/null +++ b/mpi/timing-study/output-12-1000-250.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 0.198089 +Clock time: 2.217166 diff --git a/mpi/timing-study/output-12-1000-500.txt b/mpi/timing-study/output-12-1000-500.txt new file mode 100644 index 0000000..51bc78b --- /dev/null +++ b/mpi/timing-study/output-12-1000-500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 0.735509 +Clock time: 2.513034 diff --git a/mpi/timing-study/output-12-1000-750.txt b/mpi/timing-study/output-12-1000-750.txt new file mode 100644 index 0000000..c9351f2 --- /dev/null +++ b/mpi/timing-study/output-12-1000-750.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 1.617002 +Clock time: 4.091923 diff --git a/mpi/timing-study/output-16-1000-1000.txt b/mpi/timing-study/output-16-1000-1000.txt new file mode 100644 index 0000000..4b98fae --- /dev/null +++ b/mpi/timing-study/output-16-1000-1000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 2.106571 +Clock time: 7.500836 diff --git a/mpi/timing-study/output-16-1000-1250.txt b/mpi/timing-study/output-16-1000-1250.txt new file mode 100644 index 0000000..183314c --- /dev/null +++ b/mpi/timing-study/output-16-1000-1250.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 3.445883 +Clock time: 11.167682 diff --git a/mpi/timing-study/output-16-1000-1500.txt b/mpi/timing-study/output-16-1000-1500.txt new file mode 100644 index 0000000..a08be6f --- /dev/null +++ b/mpi/timing-study/output-16-1000-1500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 4.741983 +Clock time: 16.777514 diff --git a/mpi/timing-study/output-16-1000-1750.txt b/mpi/timing-study/output-16-1000-1750.txt new file mode 100644 index 0000000..cd6757e --- /dev/null +++ b/mpi/timing-study/output-16-1000-1750.txt @@ -0,0 +1,8 @@ + +=================================================================================== += BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES += PID 34784 RUNNING AT kp160 += EXIT CODE: 11 += CLEANING UP REMAINING PROCESSES += YOU CAN IGNORE THE BELOW CLEANUP MESSAGES +=================================================================================== diff --git a/mpi/timing-study/output-16-1000-2000.txt b/mpi/timing-study/output-16-1000-2000.txt new file mode 100644 index 0000000..4bfa78c --- /dev/null +++ b/mpi/timing-study/output-16-1000-2000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 8.301682 +Clock time: 28.791425 diff --git a/mpi/timing-study/output-16-1000-250.txt b/mpi/timing-study/output-16-1000-250.txt new file mode 100644 index 0000000..2f97b52 --- /dev/null +++ b/mpi/timing-study/output-16-1000-250.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 0.145483 +Clock time: 2.572587 diff --git a/mpi/timing-study/output-16-1000-500.txt b/mpi/timing-study/output-16-1000-500.txt new file mode 100644 index 0000000..adc146c --- /dev/null +++ b/mpi/timing-study/output-16-1000-500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 0.570992 +Clock time: 3.899400 diff --git a/mpi/timing-study/output-16-1000-750.txt b/mpi/timing-study/output-16-1000-750.txt new file mode 100644 index 0000000..961b2a9 --- /dev/null +++ b/mpi/timing-study/output-16-1000-750.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 1.215016 +Clock time: 5.047125 diff --git a/mpi/timing-study/output-20-1000-250.txt b/mpi/timing-study/output-20-1000-250.txt new file mode 100644 index 0000000..e69de29 diff --git a/mpi/timing-study/output-24-1000-1000.txt b/mpi/timing-study/output-24-1000-1000.txt new file mode 100644 index 0000000..b1fd01d --- /dev/null +++ b/mpi/timing-study/output-24-1000-1000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 1.414322 +Clock time: 9.439315 diff --git a/mpi/timing-study/output-24-1000-1250.txt b/mpi/timing-study/output-24-1000-1250.txt new file mode 100644 index 0000000..08acf8e --- /dev/null +++ b/mpi/timing-study/output-24-1000-1250.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 2.171989 +Clock time: 13.927639 diff --git a/mpi/timing-study/output-24-1000-1500.txt b/mpi/timing-study/output-24-1000-1500.txt new file mode 100644 index 0000000..e8452d5 --- /dev/null +++ b/mpi/timing-study/output-24-1000-1500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 3.133675 +Clock time: 19.271850 diff --git a/mpi/timing-study/output-24-1000-1750.txt b/mpi/timing-study/output-24-1000-1750.txt new file mode 100644 index 0000000..9757c78 --- /dev/null +++ b/mpi/timing-study/output-24-1000-1750.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 4.398371 +Clock time: 25.650748 diff --git a/mpi/timing-study/output-24-1000-2000.txt b/mpi/timing-study/output-24-1000-2000.txt new file mode 100644 index 0000000..8fd3c60 --- /dev/null +++ b/mpi/timing-study/output-24-1000-2000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 5.639865 +Clock time: 33.529967 diff --git a/mpi/timing-study/output-24-1000-250.txt b/mpi/timing-study/output-24-1000-250.txt new file mode 100644 index 0000000..e6ddcb7 --- /dev/null +++ b/mpi/timing-study/output-24-1000-250.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 0.100765 +Clock time: 2.412458 diff --git a/mpi/timing-study/output-24-1000-500.txt b/mpi/timing-study/output-24-1000-500.txt new file mode 100644 index 0000000..8f6af46 --- /dev/null +++ b/mpi/timing-study/output-24-1000-500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 0.465147 +Clock time: 3.942927 diff --git a/mpi/timing-study/output-24-1000-750.txt b/mpi/timing-study/output-24-1000-750.txt new file mode 100644 index 0000000..1329b1b --- /dev/null +++ b/mpi/timing-study/output-24-1000-750.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 0.815429 +Clock time: 5.642879 diff --git a/mpi/timing-study/output-4-1000-1000.txt b/mpi/timing-study/output-4-1000-1000.txt new file mode 100644 index 0000000..14dc1e9 --- /dev/null +++ b/mpi/timing-study/output-4-1000-1000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 8.467197 +Clock time: 11.707533 diff --git a/mpi/timing-study/output-4-1000-1250.txt b/mpi/timing-study/output-4-1000-1250.txt new file mode 100644 index 0000000..408cfeb --- /dev/null +++ b/mpi/timing-study/output-4-1000-1250.txt @@ -0,0 +1,11 @@ + +=================================================================================== += BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES += PID 22126 RUNNING AT kp013 += EXIT CODE: 11 += CLEANING UP REMAINING PROCESSES += YOU CAN IGNORE THE BELOW CLEANUP MESSAGES +=================================================================================== +YOUR APPLICATION TERMINATED WITH THE EXIT STRING: Segmentation fault (signal 11) +This typically refers to a problem with your application. +Please see the FAQ page for debugging suggestions diff --git a/mpi/timing-study/output-4-1000-1500.txt b/mpi/timing-study/output-4-1000-1500.txt new file mode 100644 index 0000000..d304a5d --- /dev/null +++ b/mpi/timing-study/output-4-1000-1500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 18.823087 +Clock time: 26.449810 diff --git a/mpi/timing-study/output-4-1000-1750.txt b/mpi/timing-study/output-4-1000-1750.txt new file mode 100644 index 0000000..ab98c94 --- /dev/null +++ b/mpi/timing-study/output-4-1000-1750.txt @@ -0,0 +1,11 @@ + +=================================================================================== += BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES += PID 22197 RUNNING AT kp013 += EXIT CODE: 11 += CLEANING UP REMAINING PROCESSES += YOU CAN IGNORE THE BELOW CLEANUP MESSAGES +=================================================================================== +YOUR APPLICATION TERMINATED WITH THE EXIT STRING: Segmentation fault (signal 11) +This typically refers to a problem with your application. +Please see the FAQ page for debugging suggestions diff --git a/mpi/timing-study/output-4-1000-2000.txt b/mpi/timing-study/output-4-1000-2000.txt new file mode 100644 index 0000000..2c85e0c --- /dev/null +++ b/mpi/timing-study/output-4-1000-2000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 33.274214 +Clock time: 45.841294 diff --git a/mpi/timing-study/output-4-1000-250.txt b/mpi/timing-study/output-4-1000-250.txt new file mode 100644 index 0000000..8b1fa3c --- /dev/null +++ b/mpi/timing-study/output-4-1000-250.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 0.599813 +Clock time: 2.807879 diff --git a/mpi/timing-study/output-4-1000-500.txt b/mpi/timing-study/output-4-1000-500.txt new file mode 100644 index 0000000..b3ce6ae --- /dev/null +++ b/mpi/timing-study/output-4-1000-500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 2.212790 +Clock time: 4.133439 diff --git a/mpi/timing-study/output-4-1000-750.txt b/mpi/timing-study/output-4-1000-750.txt new file mode 100644 index 0000000..59aa17f --- /dev/null +++ b/mpi/timing-study/output-4-1000-750.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 4.830949 +Clock time: 6.854574 diff --git a/mpi/timing-study/output-8-1000-1000.txt b/mpi/timing-study/output-8-1000-1000.txt new file mode 100644 index 0000000..c063ee2 --- /dev/null +++ b/mpi/timing-study/output-8-1000-1000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 4.226861 +Clock time: 7.517444 diff --git a/mpi/timing-study/output-8-1000-1250.txt b/mpi/timing-study/output-8-1000-1250.txt new file mode 100644 index 0000000..4be7ca8 --- /dev/null +++ b/mpi/timing-study/output-8-1000-1250.txt @@ -0,0 +1,11 @@ + +=================================================================================== += BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES += PID 22852 RUNNING AT kp013 += EXIT CODE: 11 += CLEANING UP REMAINING PROCESSES += YOU CAN IGNORE THE BELOW CLEANUP MESSAGES +=================================================================================== +YOUR APPLICATION TERMINATED WITH THE EXIT STRING: Segmentation fault (signal 11) +This typically refers to a problem with your application. +Please see the FAQ page for debugging suggestions diff --git a/mpi/timing-study/output-8-1000-1500.txt b/mpi/timing-study/output-8-1000-1500.txt new file mode 100644 index 0000000..957fc99 --- /dev/null +++ b/mpi/timing-study/output-8-1000-1500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 9.416485 +Clock time: 16.706325 diff --git a/mpi/timing-study/output-8-1000-1750.txt b/mpi/timing-study/output-8-1000-1750.txt new file mode 100644 index 0000000..8dbd945 --- /dev/null +++ b/mpi/timing-study/output-8-1000-1750.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 12.741221 +Clock time: 22.281683 diff --git a/mpi/timing-study/output-8-1000-2000.txt b/mpi/timing-study/output-8-1000-2000.txt new file mode 100644 index 0000000..9610e3f --- /dev/null +++ b/mpi/timing-study/output-8-1000-2000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 16.578412 +Clock time: 26.921717 diff --git a/mpi/timing-study/output-8-1000-250.txt b/mpi/timing-study/output-8-1000-250.txt new file mode 100644 index 0000000..ca01ca3 --- /dev/null +++ b/mpi/timing-study/output-8-1000-250.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 0.296146 +Clock time: 2.211905 diff --git a/mpi/timing-study/output-8-1000-500.txt b/mpi/timing-study/output-8-1000-500.txt new file mode 100644 index 0000000..3e3b83c --- /dev/null +++ b/mpi/timing-study/output-8-1000-500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 1.111486 +Clock time: 2.710176 diff --git a/mpi/timing-study/output-8-1000-750.txt b/mpi/timing-study/output-8-1000-750.txt new file mode 100644 index 0000000..4a98753 --- /dev/null +++ b/mpi/timing-study/output-8-1000-750.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 2.419305 +Clock time: 4.675962 diff --git a/mpi/timing-study/slurm-10870703.err-kp013 b/mpi/timing-study/slurm-10870703.err-kp013 new file mode 100644 index 0000000..4bdaa5d --- /dev/null +++ b/mpi/timing-study/slurm-10870703.err-kp013 @@ -0,0 +1,11 @@ +mkdir: cannot create directory ‘timing-study’: File exists +[proxy:0:0@kp013] HYD_pmcd_pmip_control_cmd_cb (../../../../../../srcdir/mpich/3.2.1/src/pm/hydra/pm/pmiserv/pmip_cb.c:887): assert (!closed) failed +[proxy:0:0@kp013] HYDT_dmxu_poll_wait_for_event (../../../../../../srcdir/mpich/3.2.1/src/pm/hydra/tools/demux/demux_poll.c:76): callback returned error status +[proxy:0:0@kp013] main (../../../../../../srcdir/mpich/3.2.1/src/pm/hydra/pm/pmiserv/pmip.c:202): demux engine error waiting for event +srun: error: kp013: task 0: Exited with exit code 7 +[mpiexec@kp013] HYDT_bscu_wait_for_completion (../../../../../../srcdir/mpich/3.2.1/src/pm/hydra/tools/bootstrap/utils/bscu_wait.c:76): one of the processes terminated badly; aborting +[mpiexec@kp013] HYDT_bsci_wait_for_completion (../../../../../../srcdir/mpich/3.2.1/src/pm/hydra/tools/bootstrap/src/bsci_wait.c:23): launcher returned error waiting for completion +[mpiexec@kp013] HYD_pmci_wait_for_completion (../../../../../../srcdir/mpich/3.2.1/src/pm/hydra/pm/pmiserv/pmiserv_pmci.c:218): launcher returned error waiting for completion +[mpiexec@kp013] main (../../../../../../srcdir/mpich/3.2.1/src/pm/hydra/ui/mpich/mpiexec.c:340): process manager error waiting for completion +srun: error: Unable to create step for job 10870703: Job/step already completing or completed +slurmstepd: error: *** JOB 10870703 ON kp013 CANCELLED AT 2021-12-08T01:29:02 DUE TO TIME LIMIT *** diff --git a/mpi/timing-study/slurm-10870703.out-kp013 b/mpi/timing-study/slurm-10870703.out-kp013 new file mode 100644 index 0000000..e69de29 diff --git a/mpi/timing-study/timing_study.sh b/mpi/timing-study/timing_study.sh new file mode 100644 index 0000000..04b64ff --- /dev/null +++ b/mpi/timing-study/timing_study.sh @@ -0,0 +1,24 @@ +#!/bin/bash +#SBATCH --time=0:10:00 # walltime, abbreviated by -t +#SBATCH --nodes=2 # number of cluster nodes, abbreviated by -N +#SBATCH -o slurm-%j.out-%N # name of the stdout, using the job number (%j) and the first node (%N) +#SBATCH -e slurm-%j.err-%N # name of the stderr, using job and first node values +#SBATCH --ntasks=24 # number of MPI tasks, abbreviated by -n +# additional information for allocated clusters +#SBATCH --account=usucs5030 # account - abbreviated by -A +#SBATCH --partition=kingspeak # partition, abbreviated by -p + +cd $HOME/gol/mpi +mkdir timing-study + +module load intel mpich + +iterations=1000 + +for cores in 1 4 8 12 16 20 #24 +do + for size in 250 500 750 1000 1250 1500 1750 2000 + do + mpirun -np $cores ./gol simulate random $size $size $iterations 1 > timing-study/output-$cores-$iterations-$size.txt + done +done diff --git a/openmp/src/create_grid.c b/openmp/src/create_grid.c index d6a5b94..a48317d 100644 --- a/openmp/src/create_grid.c +++ b/openmp/src/create_grid.c @@ -1,5 +1,6 @@ #include "create_grid.h" +// Print entirety of a grid to verify input void print_grid(struct GAME* game) { printf("\n===GRID===\n"); for (int y = 0; y < game->height; y++) { @@ -10,6 +11,7 @@ void print_grid(struct GAME* game) { } } +// Go through user input void create_grid(int argc, char** argv) { char* filename; struct GAME game; diff --git a/openmp/src/file.c b/openmp/src/file.c index 3ecb613..e10b667 100644 --- a/openmp/src/file.c +++ b/openmp/src/file.c @@ -1,5 +1,6 @@ #include "file.h" +// Read a grid from a binary file into the space without padding void read_in(char* filename, struct GAME* game) { FILE* file = fopen(filename, "rb"); for (int i = game->padding; i < game->height+game->padding; i++) { @@ -8,6 +9,7 @@ void read_in(char* filename, struct GAME* game) { fclose(file); } +// Write a grid to a binary file into the space without padding void write_out(char* filename, struct GAME* game) { FILE* file = fopen(filename, "w+"); for (int i = game->padding; i < game->height+game->padding; i++) { diff --git a/openmp/src/game.c b/openmp/src/game.c index b5e786d..cac6fa0 100644 --- a/openmp/src/game.c +++ b/openmp/src/game.c @@ -1,5 +1,6 @@ #include "game.h" +// Calculate the number of live neighbors a cell has int neighbors(struct GAME* game, int x, int y) { int n = 0; for (int dy = -1; dy <= 1; dy++) { @@ -15,6 +16,7 @@ int neighbors(struct GAME* game, int x, int y) { return n; } +// Compute the next iteration of a board void next(struct GAME* game, int threads) { unsigned char** newGrid = malloc(sizeof(unsigned char*) * (game->height+(game->padding*2))); int y,x,i,size; @@ -30,10 +32,12 @@ void next(struct GAME* game, int threads) { #pragma omp parallel num_threads(threads) shared(per_thread, threads, total_width, total_height, newGrid, game) private(y,x,i) { + // Each thread gets a number of cells to compute int me = omp_get_thread_num(); int thread_start = per_thread * me; int thread_end = thread_start + per_thread + (me == threads-1 ? (total_width*total_height) % per_thread : 0); for (i = thread_start; i < thread_end; i++) { + // Iterate through each cell assigned for this thread y = i / total_width; x = i % total_width; int my_neighbors = neighbors(game, x, y); @@ -55,6 +59,7 @@ void next(struct GAME* game, int threads) { game->grid = newGrid; } +//Rnadomly assign life value to each cell void randomize(struct GAME* game) { for (int y = game->padding; y < game->height+game->padding; y++) { for (int x = game->padding; x < game->width+game->padding; x++) { diff --git a/openmp/src/main.c b/openmp/src/main.c index 68ec0bd..50fb096 100644 --- a/openmp/src/main.c +++ b/openmp/src/main.c @@ -19,6 +19,7 @@ //#define VERBOSE 1 #define SEED 100 +// Do the simulation void simulate(int argc, char** argv) { srand(SEED); char* filename; @@ -26,6 +27,7 @@ void simulate(int argc, char** argv) { game.padding = PADDING; int iterations, log_each_step, threads; if (argc == 8) { + // Parse the arguments filename = argv[2]; game.width = atoi(argv[3]); game.height = atoi(argv[4]); @@ -51,6 +53,7 @@ void simulate(int argc, char** argv) { memset(game.grid[i], 0, game.width+(2*game.padding)); } + // Choose where to read initial position if (strcmp(filename, "random") == 0) { randomize(&game); } else { @@ -62,16 +65,19 @@ void simulate(int argc, char** argv) { double start, end; for (int i = 0; i <= iterations; i++) { + // Iteration 0 will just be the initial grid if (i > 0) { - // Iteration 0 is just the input board start = omp_get_wtime(); + // Compute the next grid with threads next(&game, threads); end = omp_get_wtime(); time_computing_life += ((double) (end - start)); } if (log_each_step) { + // If we are logging each step, perform IO operations #if VERBOSE == 1 printf("\n===Iteration %i===\n", i); + // Print the board without the padding elements for (int y = game.padding; y < game.height+game.padding; y++) { for (int x = game.padding; x < game.width+game.padding; x++) { printf("%s ", game.grid[y][x] ? "X" : " "); @@ -80,6 +86,7 @@ void simulate(int argc, char** argv) { } printf("===End iteration %i===\n", i); #endif + // Save to a file sprintf(iteration_file, "output/iteration-%07d.bin", i); write_out(iteration_file, &game); } diff --git a/openmp/timing-study/output-1-1000-1000.txt b/openmp/timing-study/output-1-1000-1000.txt new file mode 100644 index 0000000..42681a1 --- /dev/null +++ b/openmp/timing-study/output-1-1000-1000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 73.312715 +Clock time: 77.450210 diff --git a/openmp/timing-study/output-1-1000-1250.txt b/openmp/timing-study/output-1-1000-1250.txt new file mode 100644 index 0000000..ba1464f --- /dev/null +++ b/openmp/timing-study/output-1-1000-1250.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 113.646203 +Clock time: 118.646829 diff --git a/openmp/timing-study/output-1-1000-1500.txt b/openmp/timing-study/output-1-1000-1500.txt new file mode 100644 index 0000000..7d09b62 --- /dev/null +++ b/openmp/timing-study/output-1-1000-1500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 163.034248 +Clock time: 171.017339 diff --git a/openmp/timing-study/output-1-1000-1750.txt b/openmp/timing-study/output-1-1000-1750.txt new file mode 100644 index 0000000..66bcb80 --- /dev/null +++ b/openmp/timing-study/output-1-1000-1750.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 220.656360 +Clock time: 231.050593 diff --git a/openmp/timing-study/output-1-1000-2000.txt b/openmp/timing-study/output-1-1000-2000.txt new file mode 100644 index 0000000..a11469d --- /dev/null +++ b/openmp/timing-study/output-1-1000-2000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 287.698970 +Clock time: 300.176503 diff --git a/openmp/timing-study/output-1-1000-250.txt b/openmp/timing-study/output-1-1000-250.txt new file mode 100644 index 0000000..420bfe2 --- /dev/null +++ b/openmp/timing-study/output-1-1000-250.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 5.088550 +Clock time: 5.963468 diff --git a/openmp/timing-study/output-1-1000-500.txt b/openmp/timing-study/output-1-1000-500.txt new file mode 100644 index 0000000..066b863 --- /dev/null +++ b/openmp/timing-study/output-1-1000-500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 18.956314 +Clock time: 20.440567 diff --git a/openmp/timing-study/output-1-1000-750.txt b/openmp/timing-study/output-1-1000-750.txt new file mode 100644 index 0000000..991980d --- /dev/null +++ b/openmp/timing-study/output-1-1000-750.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 41.660313 +Clock time: 44.581177 diff --git a/openmp/timing-study/output-12-1000-1000.txt b/openmp/timing-study/output-12-1000-1000.txt new file mode 100644 index 0000000..613af8c --- /dev/null +++ b/openmp/timing-study/output-12-1000-1000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 7.026118 +Clock time: 10.251363 diff --git a/openmp/timing-study/output-12-1000-1250.txt b/openmp/timing-study/output-12-1000-1250.txt new file mode 100644 index 0000000..57fbe93 --- /dev/null +++ b/openmp/timing-study/output-12-1000-1250.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 10.801676 +Clock time: 15.900482 diff --git a/openmp/timing-study/output-12-1000-1500.txt b/openmp/timing-study/output-12-1000-1500.txt new file mode 100644 index 0000000..0211559 --- /dev/null +++ b/openmp/timing-study/output-12-1000-1500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 25.918769 +Clock time: 34.562182 diff --git a/openmp/timing-study/output-12-1000-1750.txt b/openmp/timing-study/output-12-1000-1750.txt new file mode 100644 index 0000000..0cf8832 --- /dev/null +++ b/openmp/timing-study/output-12-1000-1750.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 25.862278 +Clock time: 34.828966 diff --git a/openmp/timing-study/output-12-1000-2000.txt b/openmp/timing-study/output-12-1000-2000.txt new file mode 100644 index 0000000..b407d23 --- /dev/null +++ b/openmp/timing-study/output-12-1000-2000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 30.705054 +Clock time: 43.042410 diff --git a/openmp/timing-study/output-12-1000-250.txt b/openmp/timing-study/output-12-1000-250.txt new file mode 100644 index 0000000..5c7f4a4 --- /dev/null +++ b/openmp/timing-study/output-12-1000-250.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 0.860293 +Clock time: 3.331446 diff --git a/openmp/timing-study/output-12-1000-500.txt b/openmp/timing-study/output-12-1000-500.txt new file mode 100644 index 0000000..2af2794 --- /dev/null +++ b/openmp/timing-study/output-12-1000-500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 2.097878 +Clock time: 3.643646 diff --git a/openmp/timing-study/output-12-1000-750.txt b/openmp/timing-study/output-12-1000-750.txt new file mode 100644 index 0000000..5e235a9 --- /dev/null +++ b/openmp/timing-study/output-12-1000-750.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 4.321400 +Clock time: 6.663178 diff --git a/openmp/timing-study/output-16-1000-1000.txt b/openmp/timing-study/output-16-1000-1000.txt new file mode 100644 index 0000000..7f376d5 --- /dev/null +++ b/openmp/timing-study/output-16-1000-1000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 9.131005 +Clock time: 12.449032 diff --git a/openmp/timing-study/output-16-1000-1250.txt b/openmp/timing-study/output-16-1000-1250.txt new file mode 100644 index 0000000..d57a287 --- /dev/null +++ b/openmp/timing-study/output-16-1000-1250.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 13.434282 +Clock time: 18.116181 diff --git a/openmp/timing-study/output-16-1000-1500.txt b/openmp/timing-study/output-16-1000-1500.txt new file mode 100644 index 0000000..8b11fc0 --- /dev/null +++ b/openmp/timing-study/output-16-1000-1500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 16.706991 +Clock time: 24.712374 diff --git a/openmp/timing-study/output-16-1000-1750.txt b/openmp/timing-study/output-16-1000-1750.txt new file mode 100644 index 0000000..c0018ec --- /dev/null +++ b/openmp/timing-study/output-16-1000-1750.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 23.733395 +Clock time: 33.306681 diff --git a/openmp/timing-study/output-16-1000-2000.txt b/openmp/timing-study/output-16-1000-2000.txt new file mode 100644 index 0000000..bd9c5d0 --- /dev/null +++ b/openmp/timing-study/output-16-1000-2000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 30.429469 +Clock time: 42.369926 diff --git a/openmp/timing-study/output-16-1000-250.txt b/openmp/timing-study/output-16-1000-250.txt new file mode 100644 index 0000000..dc8331f --- /dev/null +++ b/openmp/timing-study/output-16-1000-250.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 0.738930 +Clock time: 3.383995 diff --git a/openmp/timing-study/output-16-1000-500.txt b/openmp/timing-study/output-16-1000-500.txt new file mode 100644 index 0000000..f86a977 --- /dev/null +++ b/openmp/timing-study/output-16-1000-500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 2.352756 +Clock time: 3.601057 diff --git a/openmp/timing-study/output-16-1000-750.txt b/openmp/timing-study/output-16-1000-750.txt new file mode 100644 index 0000000..75efb03 --- /dev/null +++ b/openmp/timing-study/output-16-1000-750.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 5.147589 +Clock time: 7.427564 diff --git a/openmp/timing-study/output-20-1000-1000.txt b/openmp/timing-study/output-20-1000-1000.txt new file mode 100644 index 0000000..206d879 --- /dev/null +++ b/openmp/timing-study/output-20-1000-1000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 7.390921 +Clock time: 11.239737 diff --git a/openmp/timing-study/output-20-1000-1250.txt b/openmp/timing-study/output-20-1000-1250.txt new file mode 100644 index 0000000..86f7469 --- /dev/null +++ b/openmp/timing-study/output-20-1000-1250.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 11.254777 +Clock time: 16.136264 diff --git a/openmp/timing-study/output-20-1000-1500.txt b/openmp/timing-study/output-20-1000-1500.txt new file mode 100644 index 0000000..3c905b0 --- /dev/null +++ b/openmp/timing-study/output-20-1000-1500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 16.076534 +Clock time: 23.718524 diff --git a/openmp/timing-study/output-20-1000-1750.txt b/openmp/timing-study/output-20-1000-1750.txt new file mode 100644 index 0000000..db999b9 --- /dev/null +++ b/openmp/timing-study/output-20-1000-1750.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 21.727030 +Clock time: 31.285851 diff --git a/openmp/timing-study/output-20-1000-2000.txt b/openmp/timing-study/output-20-1000-2000.txt new file mode 100644 index 0000000..b8c5e44 --- /dev/null +++ b/openmp/timing-study/output-20-1000-2000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 28.363274 +Clock time: 40.847248 diff --git a/openmp/timing-study/output-20-1000-250.txt b/openmp/timing-study/output-20-1000-250.txt new file mode 100644 index 0000000..1dc5094 --- /dev/null +++ b/openmp/timing-study/output-20-1000-250.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 0.555697 +Clock time: 2.156701 diff --git a/openmp/timing-study/output-20-1000-500.txt b/openmp/timing-study/output-20-1000-500.txt new file mode 100644 index 0000000..d394ec5 --- /dev/null +++ b/openmp/timing-study/output-20-1000-500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 1.944395 +Clock time: 3.506218 diff --git a/openmp/timing-study/output-20-1000-750.txt b/openmp/timing-study/output-20-1000-750.txt new file mode 100644 index 0000000..a52ddf0 --- /dev/null +++ b/openmp/timing-study/output-20-1000-750.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 4.297441 +Clock time: 6.404743 diff --git a/openmp/timing-study/output-24-1000-1000.txt b/openmp/timing-study/output-24-1000-1000.txt new file mode 100644 index 0000000..8f4e5a3 --- /dev/null +++ b/openmp/timing-study/output-24-1000-1000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 6.344307 +Clock time: 9.689612 diff --git a/openmp/timing-study/output-24-1000-1250.txt b/openmp/timing-study/output-24-1000-1250.txt new file mode 100644 index 0000000..819e097 --- /dev/null +++ b/openmp/timing-study/output-24-1000-1250.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 9.870428 +Clock time: 14.864989 diff --git a/openmp/timing-study/output-24-1000-1500.txt b/openmp/timing-study/output-24-1000-1500.txt new file mode 100644 index 0000000..f19ee37 --- /dev/null +++ b/openmp/timing-study/output-24-1000-1500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 13.883823 +Clock time: 21.691046 diff --git a/openmp/timing-study/output-24-1000-1750.txt b/openmp/timing-study/output-24-1000-1750.txt new file mode 100644 index 0000000..a1079b9 --- /dev/null +++ b/openmp/timing-study/output-24-1000-1750.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 18.691083 +Clock time: 26.919679 diff --git a/openmp/timing-study/output-24-1000-2000.txt b/openmp/timing-study/output-24-1000-2000.txt new file mode 100644 index 0000000..e21c9f1 --- /dev/null +++ b/openmp/timing-study/output-24-1000-2000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 24.792304 +Clock time: 36.801597 diff --git a/openmp/timing-study/output-24-1000-250.txt b/openmp/timing-study/output-24-1000-250.txt new file mode 100644 index 0000000..eaa55fb --- /dev/null +++ b/openmp/timing-study/output-24-1000-250.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 0.613609 +Clock time: 3.196133 diff --git a/openmp/timing-study/output-24-1000-500.txt b/openmp/timing-study/output-24-1000-500.txt new file mode 100644 index 0000000..a0c8a7f --- /dev/null +++ b/openmp/timing-study/output-24-1000-500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 1.735787 +Clock time: 3.401682 diff --git a/openmp/timing-study/output-24-1000-750.txt b/openmp/timing-study/output-24-1000-750.txt new file mode 100644 index 0000000..7f4e763 --- /dev/null +++ b/openmp/timing-study/output-24-1000-750.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 3.754690 +Clock time: 5.885699 diff --git a/openmp/timing-study/output-4-1000-1000.txt b/openmp/timing-study/output-4-1000-1000.txt new file mode 100644 index 0000000..488f5bf --- /dev/null +++ b/openmp/timing-study/output-4-1000-1000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 19.561461 +Clock time: 23.064553 diff --git a/openmp/timing-study/output-4-1000-1250.txt b/openmp/timing-study/output-4-1000-1250.txt new file mode 100644 index 0000000..0c61b09 --- /dev/null +++ b/openmp/timing-study/output-4-1000-1250.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 29.425730 +Clock time: 34.283721 diff --git a/openmp/timing-study/output-4-1000-1500.txt b/openmp/timing-study/output-4-1000-1500.txt new file mode 100644 index 0000000..040f8b7 --- /dev/null +++ b/openmp/timing-study/output-4-1000-1500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 42.126591 +Clock time: 50.662123 diff --git a/openmp/timing-study/output-4-1000-1750.txt b/openmp/timing-study/output-4-1000-1750.txt new file mode 100644 index 0000000..83870a1 --- /dev/null +++ b/openmp/timing-study/output-4-1000-1750.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 57.302075 +Clock time: 66.844318 diff --git a/openmp/timing-study/output-4-1000-2000.txt b/openmp/timing-study/output-4-1000-2000.txt new file mode 100644 index 0000000..149b7a2 --- /dev/null +++ b/openmp/timing-study/output-4-1000-2000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 76.421121 +Clock time: 88.379760 diff --git a/openmp/timing-study/output-4-1000-250.txt b/openmp/timing-study/output-4-1000-250.txt new file mode 100644 index 0000000..9623aa2 --- /dev/null +++ b/openmp/timing-study/output-4-1000-250.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 1.413768 +Clock time: 3.713147 diff --git a/openmp/timing-study/output-4-1000-500.txt b/openmp/timing-study/output-4-1000-500.txt new file mode 100644 index 0000000..0c18324 --- /dev/null +++ b/openmp/timing-study/output-4-1000-500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 4.947206 +Clock time: 6.380269 diff --git a/openmp/timing-study/output-4-1000-750.txt b/openmp/timing-study/output-4-1000-750.txt new file mode 100644 index 0000000..9086291 --- /dev/null +++ b/openmp/timing-study/output-4-1000-750.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 10.829915 +Clock time: 13.182029 diff --git a/openmp/timing-study/output-8-1000-1000.txt b/openmp/timing-study/output-8-1000-1000.txt new file mode 100644 index 0000000..ebe72e8 --- /dev/null +++ b/openmp/timing-study/output-8-1000-1000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 9.924235 +Clock time: 13.583743 diff --git a/openmp/timing-study/output-8-1000-1250.txt b/openmp/timing-study/output-8-1000-1250.txt new file mode 100644 index 0000000..ec82ee8 --- /dev/null +++ b/openmp/timing-study/output-8-1000-1250.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 15.336835 +Clock time: 20.191594 diff --git a/openmp/timing-study/output-8-1000-1500.txt b/openmp/timing-study/output-8-1000-1500.txt new file mode 100644 index 0000000..7741d7f --- /dev/null +++ b/openmp/timing-study/output-8-1000-1500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 21.996220 +Clock time: 30.139829 diff --git a/openmp/timing-study/output-8-1000-1750.txt b/openmp/timing-study/output-8-1000-1750.txt new file mode 100644 index 0000000..f62ef5a --- /dev/null +++ b/openmp/timing-study/output-8-1000-1750.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 29.524371 +Clock time: 39.165025 diff --git a/openmp/timing-study/output-8-1000-2000.txt b/openmp/timing-study/output-8-1000-2000.txt new file mode 100644 index 0000000..da43dc5 --- /dev/null +++ b/openmp/timing-study/output-8-1000-2000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 38.636923 +Clock time: 50.111060 diff --git a/openmp/timing-study/output-8-1000-250.txt b/openmp/timing-study/output-8-1000-250.txt new file mode 100644 index 0000000..6301921 --- /dev/null +++ b/openmp/timing-study/output-8-1000-250.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 0.803572 +Clock time: 3.170951 diff --git a/openmp/timing-study/output-8-1000-500.txt b/openmp/timing-study/output-8-1000-500.txt new file mode 100644 index 0000000..da9f4a2 --- /dev/null +++ b/openmp/timing-study/output-8-1000-500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 2.643531 +Clock time: 4.040041 diff --git a/openmp/timing-study/output-8-1000-750.txt b/openmp/timing-study/output-8-1000-750.txt new file mode 100644 index 0000000..70b85a1 --- /dev/null +++ b/openmp/timing-study/output-8-1000-750.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 5.837011 +Clock time: 8.027314 diff --git a/openmp/timing-study/slurm-10870649.err-kp013 b/openmp/timing-study/slurm-10870649.err-kp013 new file mode 100644 index 0000000..5e4a08a --- /dev/null +++ b/openmp/timing-study/slurm-10870649.err-kp013 @@ -0,0 +1 @@ +slurmstepd: error: *** JOB 10870649 ON kp013 CANCELLED AT 2021-12-07T21:36:02 DUE TO TIME LIMIT *** diff --git a/openmp/timing-study/slurm-10870649.out-kp013 b/openmp/timing-study/slurm-10870649.out-kp013 new file mode 100644 index 0000000..e69de29 diff --git a/openmp/timing-study/slurm-10870651.err-kp013 b/openmp/timing-study/slurm-10870651.err-kp013 new file mode 100644 index 0000000..367d47f --- /dev/null +++ b/openmp/timing-study/slurm-10870651.err-kp013 @@ -0,0 +1 @@ +slurmstepd: error: *** JOB 10870651 ON kp013 CANCELLED AT 2021-12-07T22:07:02 DUE TO TIME LIMIT *** diff --git a/openmp/timing-study/slurm-10870651.out-kp013 b/openmp/timing-study/slurm-10870651.out-kp013 new file mode 100644 index 0000000..e69de29 diff --git a/openmp/timing-study/slurm-10870663.err-kp013 b/openmp/timing-study/slurm-10870663.err-kp013 new file mode 100644 index 0000000..e69de29 diff --git a/openmp/timing-study/slurm-10870663.out-kp013 b/openmp/timing-study/slurm-10870663.out-kp013 new file mode 100644 index 0000000..e69de29 diff --git a/openmp/timing-study/timing_study.sh b/openmp/timing-study/timing_study.sh new file mode 100644 index 0000000..16771a6 --- /dev/null +++ b/openmp/timing-study/timing_study.sh @@ -0,0 +1,23 @@ +#!/bin/bash +#SBATCH --time=0:30:00 # walltime, abbreviated by -t +#SBATCH --nodes=2 # number of cluster nodes, abbreviated by -N +#SBATCH -o slurm-%j.out-%N # name of the stdout, using the job number (%j) and the first node (%N) +#SBATCH -e slurm-%j.err-%N # name of the stderr, using job and first node values +#SBATCH --ntasks=32 +# additional information for allocated clusters +#SBATCH --account=usucs5030 # account - abbreviated by -A +#SBATCH --partition=kingspeak # partition, abbreviated by -p + +cd $HOME/gol/openmp + +module load intel openmpi + +iterations=1000 + +for threads in 20 24 #1 4 8 12 16 20 24 +do + for size in 250 500 750 1000 1250 1500 1750 2000 + do + ./gol simulate random $size $size $iterations 1 $threads > timing-study/output-$threads-$iterations-$size.txt + done +done diff --git a/serial/src/create_grid.c b/serial/src/create_grid.c index d6a5b94..a48317d 100644 --- a/serial/src/create_grid.c +++ b/serial/src/create_grid.c @@ -1,5 +1,6 @@ #include "create_grid.h" +// Print entirety of a grid to verify input void print_grid(struct GAME* game) { printf("\n===GRID===\n"); for (int y = 0; y < game->height; y++) { @@ -10,6 +11,7 @@ void print_grid(struct GAME* game) { } } +// Go through user input void create_grid(int argc, char** argv) { char* filename; struct GAME game; diff --git a/serial/src/file.c b/serial/src/file.c index 3ecb613..e10b667 100644 --- a/serial/src/file.c +++ b/serial/src/file.c @@ -1,5 +1,6 @@ #include "file.h" +// Read a grid from a binary file into the space without padding void read_in(char* filename, struct GAME* game) { FILE* file = fopen(filename, "rb"); for (int i = game->padding; i < game->height+game->padding; i++) { @@ -8,6 +9,7 @@ void read_in(char* filename, struct GAME* game) { fclose(file); } +// Write a grid to a binary file into the space without padding void write_out(char* filename, struct GAME* game) { FILE* file = fopen(filename, "w+"); for (int i = game->padding; i < game->height+game->padding; i++) { diff --git a/serial/src/game.c b/serial/src/game.c index 2921e3c..ebaab1b 100644 --- a/serial/src/game.c +++ b/serial/src/game.c @@ -1,5 +1,6 @@ #include "game.h" +// Calculate the number of live neighbors a cell has int neighbors(struct GAME* game, int x, int y) { int n = 0; for (int dy = -1; dy <= 1; dy++) { @@ -15,6 +16,7 @@ int neighbors(struct GAME* game, int x, int y) { return n; } +// Compute the next iteration of a board void next(struct GAME* game) { unsigned char** newGrid = malloc(sizeof(unsigned char*) * (game->height+(game->padding*2))); int size = sizeof(unsigned char) * (game->width+(game->padding*2)); @@ -23,6 +25,7 @@ void next(struct GAME* game) { memset(newGrid[y], 0, size); } + // Iterate through each cell for (int y = 0; y < game->height+(game->padding*2); y++) { for (int x = 0; x < game->width+(game->padding*2); x++) { int my_neighbors = neighbors(game, x, y); @@ -44,6 +47,7 @@ void next(struct GAME* game) { game->grid = newGrid; } +// Randomly assign life value to each cell void randomize(struct GAME* game) { for (int y = game->padding; y < game->height+game->padding; y++) { for (int x = game->padding; x < game->width+game->padding; x++) { diff --git a/serial/src/main.c b/serial/src/main.c index f4c8141..c7cdacf 100644 --- a/serial/src/main.c +++ b/serial/src/main.c @@ -18,6 +18,7 @@ //#define VERBOSE 1 #define SEED 100 +// Do the simulation void simulate(int argc, char** argv) { srand(SEED); char* filename; @@ -25,6 +26,7 @@ void simulate(int argc, char** argv) { game.padding = PADDING; int iterations, log_each_step; if (argc == 7) { + // Parse the arguments filename = argv[2]; game.width = atoi(argv[3]); game.height = atoi(argv[4]); @@ -48,6 +50,7 @@ void simulate(int argc, char** argv) { memset(game.grid[i], 0, game.width+(2*game.padding)); } + // Choose where to read initial position if (strcmp(filename, "random") == 0) { randomize(&game); } else { @@ -55,20 +58,25 @@ void simulate(int argc, char** argv) { } char iteration_file[1024]; + + // Timing code double time_computing_life = 0; clock_t start, end; for (int i = 0; i <= iterations; i++) { + // Iteration 0 will just be the initial grid if (i > 0) { - // Iteration 0 is just the input board start = clock(); + // Compute the next grid next(&game); end = clock(); time_computing_life += ((double) (end - start)) / CLOCKS_PER_SEC; } if (log_each_step) { + // If we are logging each step, perform IO operations #if VERBOSE == 1 printf("\n===Iteration %i===\n", i); + // Print the board without the padding elements for (int y = game.padding; y < game.height+game.padding; y++) { for (int x = game.padding; x < game.width+game.padding; x++) { printf("%s ", game.grid[y][x] ? "X" : " "); @@ -77,6 +85,7 @@ void simulate(int argc, char** argv) { } printf("===End iteration %i===\n", i); #endif + // Save to a file sprintf(iteration_file, "output/iteration-%07d.bin", i); write_out(iteration_file, &game); } diff --git a/serial/timing-study/output-1-1000-1000.txt b/serial/timing-study/output-1-1000-1000.txt new file mode 100644 index 0000000..4445862 --- /dev/null +++ b/serial/timing-study/output-1-1000-1000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 65.330000 +Clock time: 66.520000 diff --git a/serial/timing-study/output-1-1000-1250.txt b/serial/timing-study/output-1-1000-1250.txt new file mode 100644 index 0000000..5adeb8d --- /dev/null +++ b/serial/timing-study/output-1-1000-1250.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 101.210000 +Clock time: 103.190000 diff --git a/serial/timing-study/output-1-1000-1500.txt b/serial/timing-study/output-1-1000-1500.txt new file mode 100644 index 0000000..30ddd59 --- /dev/null +++ b/serial/timing-study/output-1-1000-1500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 145.440000 +Clock time: 148.020000 diff --git a/serial/timing-study/output-1-1000-1750.txt b/serial/timing-study/output-1-1000-1750.txt new file mode 100644 index 0000000..25fa9c5 --- /dev/null +++ b/serial/timing-study/output-1-1000-1750.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 196.590000 +Clock time: 200.020000 diff --git a/serial/timing-study/output-1-1000-2000.txt b/serial/timing-study/output-1-1000-2000.txt new file mode 100644 index 0000000..3582584 --- /dev/null +++ b/serial/timing-study/output-1-1000-2000.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 256.560000 +Clock time: 260.770000 diff --git a/serial/timing-study/output-1-1000-250.txt b/serial/timing-study/output-1-1000-250.txt new file mode 100644 index 0000000..c7652f2 --- /dev/null +++ b/serial/timing-study/output-1-1000-250.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 4.560000 +Clock time: 4.830000 diff --git a/serial/timing-study/output-1-1000-500.txt b/serial/timing-study/output-1-1000-500.txt new file mode 100644 index 0000000..c6b006d --- /dev/null +++ b/serial/timing-study/output-1-1000-500.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 16.990000 +Clock time: 17.340000 diff --git a/serial/timing-study/output-1-1000-750.txt b/serial/timing-study/output-1-1000-750.txt new file mode 100644 index 0000000..fddfee8 --- /dev/null +++ b/serial/timing-study/output-1-1000-750.txt @@ -0,0 +1,4 @@ + +===Timing=== +Time computing life: 36.980000 +Clock time: 37.830000 diff --git a/serial/timing-study/slurm-10870643.err-kp013 b/serial/timing-study/slurm-10870643.err-kp013 new file mode 100644 index 0000000..e69de29 diff --git a/serial/timing-study/slurm-10870643.out-kp013 b/serial/timing-study/slurm-10870643.out-kp013 new file mode 100644 index 0000000..e69de29 diff --git a/serial/timing-study/timing_study.sh b/serial/timing-study/timing_study.sh new file mode 100644 index 0000000..20f405d --- /dev/null +++ b/serial/timing-study/timing_study.sh @@ -0,0 +1,19 @@ +#!/bin/bash +#SBATCH --time=0:35:00 # walltime, abbreviated by -t +#SBATCH --nodes=1 # number of cluster nodes, abbreviated by -N +#SBATCH -o slurm-%j.out-%N # name of the stdout, using the job number (%j) and the first node (%N) +#SBATCH -e slurm-%j.err-%N # name of the stderr, using job and first node values +#SBATCH --ntasks=1 # number of MPI tasks, abbreviated by -n +# additional information for allocated clusters +#SBATCH --account=usucs5030 # account - abbreviated by -A +#SBATCH --partition=kingspeak # partition, abbreviated by -p + +cd $HOME/gol/serial + +iterations=1000 +cores=1 + +for size in 250 500 750 1000 1250 1500 1750 2000 +do + ./gol simulate random $size $size $iterations 1 > timing-study/output-$cores-$iterations-$size.txt +done