From 8c8d89b0214264314cee6c2338af035b9610a4fb Mon Sep 17 00:00:00 2001 From: fredrikr79 Date: Tue, 16 Sep 2025 06:31:01 +0200 Subject: [PATCH] ex2: add comments --- exercise2/bench.py | 2 ++ exercise2/mandel_mpi.c | 55 ++++++++++++++++++++++++++++++------------ 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/exercise2/bench.py b/exercise2/bench.py index 7127c40..bfc65f9 100755 --- a/exercise2/bench.py +++ b/exercise2/bench.py @@ -1,5 +1,7 @@ #!/usr/bin/env python3 +# this script was AI-generated, but is quick to grasp. + from statistics import mean from subprocess import DEVNULL, run from sys import argv, exit diff --git a/exercise2/mandel_mpi.c b/exercise2/mandel_mpi.c index f729a8f..97b9f79 100644 --- a/exercise2/mandel_mpi.c +++ b/exercise2/mandel_mpi.c @@ -6,7 +6,8 @@ #include #define XSIZE 2560 -#define YSIZE 2048 +#define YSIZE 2048 // if you wish to change this, remember to change the two + // other locations further down as well. #define MAXITER 255 @@ -24,9 +25,12 @@ typedef struct { double real, imag; } complex_t; +// introduce some mpi variables int rank, size; +// do not save the image by default bool save = false; +// this provided code remains untouched void calculate() { for (int i = 0; i < XSIZE; i++) { for (int j = 0; j < YSIZE; j++) { @@ -51,6 +55,9 @@ void calculate() { typedef unsigned char uchar; +// this is also untouched. note: there is a bug/unexpected feature, where the +// provided x and y values are not used to denote the final image size. +// i expected fwrite to use x and y and got punished for it. /* save 24-bits bmp file, buffer must be in bmp format: upside-down */ void savebmp(char *name, uchar *buffer, int x, int y) { FILE *f = fopen(name, "wb"); @@ -67,6 +74,7 @@ void savebmp(char *name, uchar *buffer, int x, int y) { fclose(f); } +// this is also untouched. /* given iteration number, set a colour */ void fancycolour(uchar *p, int iter) { if (iter == MAXITER) @@ -86,6 +94,10 @@ void fancycolour(uchar *p, int iter) { } } +// i only changed main to add mpi functionality, while preserving the choice to +// save the image or not, imposing a retstriction on myself to strictly use the +// provided code, but not modify it. interestingly, i was able to do so by +// redefining the YSIZE macro. int main(int argc, char **argv) { if (argc <= 1) { printf("usage: mandel_mpi [y/n]\n"); @@ -94,28 +106,37 @@ int main(int argc, char **argv) { return 1; } else { char arg = argv[1][0]; - save = arg == 'y' || arg == '1'; + save = arg == 'y' || arg == '1'; // save if y or 1 } + + // initialize MPI MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); +// scale YSIZE so as to give each subprocess one portion of the y-values to +// compute. #undef YSIZE #define YSIZE (2048 / size) + // step, old_yupper and old_ylower remain as in the provided calculations. + // these are used to calculate the bounds for each portion that each + // subprocess will calculate. step = (xright - xleft) / XSIZE; double old_yupper = ycenter + (step * YSIZE * size) / 2; double old_ylower = ycenter - (step * YSIZE * size) / 2; - double delta = (old_yupper - old_ylower) / size; + // delta is the y-size of a portion. + double delta = (old_yupper - old_ylower) / size; + // using the rank, we can create partitions ylower = old_ylower + rank * delta; yupper = old_ylower + (rank + 1) * delta; + // update ycenter (not sure if this helps) ycenter = (ylower + yupper) / 2; calculate(); - printf("after calculate %d\n", rank); - + // note that YSIZE is now (2048 / size). calculate colors as usual const int bufsize = XSIZE * YSIZE * 3; unsigned char *buffer = calloc(bufsize, 1); for (int i = 0; i < XSIZE; i++) { @@ -125,34 +146,38 @@ int main(int argc, char **argv) { } } - printf("after buffer %d\n", rank); - + // only let non-zero ranks send to rank zero if (rank != 0) MPI_Send(buffer, bufsize, MPI_UNSIGNED_CHAR, 0, 0, MPI_COMM_WORLD); - printf("hello again from %d\n", rank); - - // use process 0 as central process: gather calulations and output image + // use process 0 as central process: gather calulations and output image. take + // care to write the data backwards. if (rank == 0) { - unsigned char *total = calloc(bufsize, size); + unsigned char *total = calloc(bufsize, size); // note: we multiply by size, + // which practically undoes + // YSIZE. this could be + // refactored. + // copy the rank 0 calculations to the back of the buffer. memcpy(total + (size - 1) * bufsize, buffer, bufsize); - printf("after memcpy 0\n"); + // note: this essentially serializes the last part of the code. for (int i = 1; i < size; i++) { MPI_Recv(total + (size - 1 - i) * bufsize, bufsize, // write reverse order MPI_UNSIGNED_CHAR, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); - printf("after direct receive %d\n", i); } - printf("after loop\n"); +// redefine YSIZE to its original value, because savebmp needs it to be +// correctly defined, since the given x and y arguments don't determine the +// written file's image size. #undef YSIZE #define YSIZE 2048 if (save) savebmp("mandel.bmp", total, XSIZE, YSIZE); - printf("after save %d\n", save); } + // i could probably (and should prbably) free my buffers here, but this is + // only a toy program. MPI_Finalize(); return 0; }