From a3b849b79c49a2d6761981decf94e53d0dd2d3a7 Mon Sep 17 00:00:00 2001 From: Daniil Vorobyev Date: Thu, 8 Oct 2020 18:41:33 +0300 Subject: [PATCH 01/22] OpenMP2 task solution is added --- OpenMP2/src/main.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/OpenMP2/src/main.cpp b/OpenMP2/src/main.cpp index 8dab215..61f2dcd 100644 --- a/OpenMP2/src/main.cpp +++ b/OpenMP2/src/main.cpp @@ -2,10 +2,22 @@ #include #include #include +#include double calc(uint32_t x_last, uint32_t num_threads) { - return 0; + double res = 0; + double* a = (double*)malloc(x_last * sizeof(double));; + + #pragma omp parallel for num_threads(num_threads) + for (uint32_t i = 0; i < x_last; i++) { + a[i] = 1.0 / (i + 1); + } + for (uint32_t i = x_last; i > 0; i--) { + res += a[i - 1]; + } + free(a); + return res; } int main(int argc, char** argv) From 3a2f82c31e57d8735896cef542f6366d34c61428 Mon Sep 17 00:00:00 2001 From: Daniil Vorobyev Date: Thu, 8 Oct 2020 18:41:33 +0300 Subject: [PATCH 02/22] OpenMP2 task solution is added --- OpenMP2/src/main.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/OpenMP2/src/main.cpp b/OpenMP2/src/main.cpp index 8dab215..61f2dcd 100644 --- a/OpenMP2/src/main.cpp +++ b/OpenMP2/src/main.cpp @@ -2,10 +2,22 @@ #include #include #include +#include double calc(uint32_t x_last, uint32_t num_threads) { - return 0; + double res = 0; + double* a = (double*)malloc(x_last * sizeof(double));; + + #pragma omp parallel for num_threads(num_threads) + for (uint32_t i = 0; i < x_last; i++) { + a[i] = 1.0 / (i + 1); + } + for (uint32_t i = x_last; i > 0; i--) { + res += a[i - 1]; + } + free(a); + return res; } int main(int argc, char** argv) From 10a6210e140da35afda73f9b8662ef09c390f8ae Mon Sep 17 00:00:00 2001 From: Daniil Vorobyev Date: Fri, 16 Oct 2020 16:38:10 +0300 Subject: [PATCH 03/22] OpenMP3 task is done --- OpenMP3/src/main.cpp | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/OpenMP3/src/main.cpp b/OpenMP3/src/main.cpp index 416ee06..2ae7077 100644 --- a/OpenMP3/src/main.cpp +++ b/OpenMP3/src/main.cpp @@ -9,9 +9,36 @@ double func(double x) return sin(x); } +double trapezoid(double x0, double x1, double dx) { + return dx * (func(x0) + func(x1)) * 0.5; +} + double calc(double x0, double x1, double dx, uint32_t num_threads) { - return 0; + int num_of_dots = (x1 - x0) / dx + 1; + double* dots = (double*)malloc(num_of_dots * sizeof(double)); + double res = 0.0; + double trap = 0.0; + double c = 0.0; + double y = 0.0; + double t = 0.0; + #pragma omp parallel num_threads(num_threads) + { + #pragma omp for + for (int i = 0; i < num_of_dots; i++) { + dots[i] = x0 + i * dx; + } + #pragma omp for reduction(+:res) private(y, t, c, trap) + for (int i = 0; i < num_of_dots - 1; i++) { + trap = trapezoid(dots[i], dots[i+1], dx); + y = trap - c; + t = res + y; + c = (t - res) - y; + res = t; + } + } + free(dots); + return res; } int main(int argc, char** argv) From 805ceaaf20ea9904329f14dcf2daa56032c6737b Mon Sep 17 00:00:00 2001 From: Daniil Vorobyev Date: Mon, 19 Oct 2020 10:42:29 +0300 Subject: [PATCH 04/22] OpenMP4 task is done --- OpenMP4/src/main.cpp | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/OpenMP4/src/main.cpp b/OpenMP4/src/main.cpp index 036d8e3..0a5e133 100644 --- a/OpenMP4/src/main.cpp +++ b/OpenMP4/src/main.cpp @@ -5,7 +5,32 @@ double calc(uint32_t x_last, uint32_t num_threads) { - return 0; + double* loc_res = (double*)calloc(num_threads, sizeof(double)); + double* loc_fact = (double*)malloc(num_threads * sizeof(double)); + + #pragma omp parallel num_threads(num_threads) + { + int tid = omp_get_thread_num(); + loc_fact[tid] = 1.0; + + #pragma omp for + for (uint32_t i = 1; i < x_last; i++) { + loc_fact[tid] /= double(i); + loc_res[tid] += loc_fact[tid]; + } + } + + double res = 1.0; + double fact = 1.0; + + for (uint32_t tid = 0; tid < num_threads; tid++) { + res += loc_res[tid] * fact; + fact *= loc_fact[tid]; + } + + free(loc_fact); + free(loc_res); + return res; } int main(int argc, char** argv) From 6a84822d1a4796b7221d787d136e01188b292ca7 Mon Sep 17 00:00:00 2001 From: Daniil Vorobyev Date: Thu, 8 Oct 2020 18:41:33 +0300 Subject: [PATCH 05/22] OpenMP2 task solution is added --- OpenMP2/src/main.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/OpenMP2/src/main.cpp b/OpenMP2/src/main.cpp index 8dab215..61f2dcd 100644 --- a/OpenMP2/src/main.cpp +++ b/OpenMP2/src/main.cpp @@ -2,10 +2,22 @@ #include #include #include +#include double calc(uint32_t x_last, uint32_t num_threads) { - return 0; + double res = 0; + double* a = (double*)malloc(x_last * sizeof(double));; + + #pragma omp parallel for num_threads(num_threads) + for (uint32_t i = 0; i < x_last; i++) { + a[i] = 1.0 / (i + 1); + } + for (uint32_t i = x_last; i > 0; i--) { + res += a[i - 1]; + } + free(a); + return res; } int main(int argc, char** argv) From 8adfc45d8c15156a39becaf62617d4107ebf39a9 Mon Sep 17 00:00:00 2001 From: Daniil Vorobyev Date: Fri, 16 Oct 2020 16:38:10 +0300 Subject: [PATCH 06/22] OpenMP3 task is done --- OpenMP3/src/main.cpp | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/OpenMP3/src/main.cpp b/OpenMP3/src/main.cpp index 416ee06..2ae7077 100644 --- a/OpenMP3/src/main.cpp +++ b/OpenMP3/src/main.cpp @@ -9,9 +9,36 @@ double func(double x) return sin(x); } +double trapezoid(double x0, double x1, double dx) { + return dx * (func(x0) + func(x1)) * 0.5; +} + double calc(double x0, double x1, double dx, uint32_t num_threads) { - return 0; + int num_of_dots = (x1 - x0) / dx + 1; + double* dots = (double*)malloc(num_of_dots * sizeof(double)); + double res = 0.0; + double trap = 0.0; + double c = 0.0; + double y = 0.0; + double t = 0.0; + #pragma omp parallel num_threads(num_threads) + { + #pragma omp for + for (int i = 0; i < num_of_dots; i++) { + dots[i] = x0 + i * dx; + } + #pragma omp for reduction(+:res) private(y, t, c, trap) + for (int i = 0; i < num_of_dots - 1; i++) { + trap = trapezoid(dots[i], dots[i+1], dx); + y = trap - c; + t = res + y; + c = (t - res) - y; + res = t; + } + } + free(dots); + return res; } int main(int argc, char** argv) From 5d7ac405ec6a37234004de8bacb9d58b8e46b2cd Mon Sep 17 00:00:00 2001 From: Daniil Vorobyev Date: Thu, 22 Oct 2020 10:53:12 +0300 Subject: [PATCH 07/22] OpenMP5 task is done --- OpenMP5/src/main.cpp | 88 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 2 deletions(-) diff --git a/OpenMP5/src/main.cpp b/OpenMP5/src/main.cpp index bf042c5..b24b04e 100644 --- a/OpenMP5/src/main.cpp +++ b/OpenMP5/src/main.cpp @@ -5,7 +5,91 @@ void calc(uint32_t xSize, uint32_t ySize, uint32_t iterations, uint32_t num_threads, uint8_t* inputFrame, uint8_t* outputFrame) { + int* inFrame = (int*)malloc(xSize*ySize * sizeof(int)); + int* outFrame = (int *)malloc(xSize*ySize * sizeof(int)); + for (uint32_t y = 0; y < ySize; y++) { + for (uint32_t x = 0; x < xSize; x++) { + outFrame[y * xSize + x] = (int)inputFrame[y * xSize + x]; + } + } + uint32_t block_size = xSize / num_threads; + uint32_t block_extra = xSize % num_threads; + #pragma omp parallel num_threads(num_threads) + { + uint32_t tid = omp_get_thread_num(); + + uint32_t first = tid * block_size; + uint32_t last = (tid + 1) * block_size; + + if (tid == num_threads - 1) { + last += block_extra; + } + + + for (uint32_t i = 0; i < iterations; i++) { + #pragma omp barrier + #pragma omp single + { + int* ptr = inFrame; + inFrame = outFrame; + outFrame = ptr; + } + for (uint32_t x = first; x < last; x++) { + for (uint32_t y = 0; y < ySize; y++) { + uint32_t count = 0; + + uint32_t x1 = x == 0 ? xSize - 1 : x - 1; + uint32_t x2 = x == xSize - 1 ? 0 : x + 1; + uint32_t y1 = y == 0 ? ySize - 1 : y - 1; + uint32_t y2 = y == ySize - 1 ? 0 : y + 1; + + + if (inFrame[y1 * xSize + x] == 1){ + count++; + } + if (inFrame[y1 * xSize + x1] == 1) { + count++; + } + if (inFrame[y1 * xSize + x2] == 1) { + count++; + } + if (inFrame[y2 * xSize + x1] == 1) { + count++; + } + if (inFrame[y2 * xSize + x2] == 1) { + count++; + } + + if (inFrame[y2 * xSize + x] == 1) { + count++; + } + if (inFrame[y * xSize + x1] == 1) { + count++; + } + if (inFrame[y * xSize + x2] == 1) { + count++; + } + + if (inFrame[y * xSize + x] == 0 && count == 3) { + outFrame[y * xSize + x] = 1; + } else if (inFrame[y * xSize + x] == 1 && (count < 2 || count > 3)) { + outFrame[y * xSize + x] = 0; + } else { + outFrame[y * xSize + x] = inFrame[y * xSize + x]; + } + } + } + } + } + + for (uint32_t y = 0; y < ySize; y++) { + for (uint32_t x = 0; x < xSize; x++) { + outputFrame[y * xSize + x] = outFrame[y * xSize + x]; + } + } + free(inFrame); + free(outFrame); } int main(int argc, char** argv) @@ -63,8 +147,8 @@ int main(int argc, char** argv) } // Prepare to exit - delete outputFrame; - delete inputFrame; + delete[] outputFrame; + delete[] inputFrame; output.close(); input.close(); return 0; From 8940fe202f3adb52b03f9d292760d90853c67f03 Mon Sep 17 00:00:00 2001 From: Daniil Vorobyev Date: Thu, 8 Oct 2020 18:41:33 +0300 Subject: [PATCH 08/22] OpenMP2 task solution is added --- OpenMP2/src/main.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/OpenMP2/src/main.cpp b/OpenMP2/src/main.cpp index 8dab215..61f2dcd 100644 --- a/OpenMP2/src/main.cpp +++ b/OpenMP2/src/main.cpp @@ -2,10 +2,22 @@ #include #include #include +#include double calc(uint32_t x_last, uint32_t num_threads) { - return 0; + double res = 0; + double* a = (double*)malloc(x_last * sizeof(double));; + + #pragma omp parallel for num_threads(num_threads) + for (uint32_t i = 0; i < x_last; i++) { + a[i] = 1.0 / (i + 1); + } + for (uint32_t i = x_last; i > 0; i--) { + res += a[i - 1]; + } + free(a); + return res; } int main(int argc, char** argv) From ebf64a4019cb9a55e1466ceec29febf0c5564f01 Mon Sep 17 00:00:00 2001 From: Daniil Vorobyev Date: Fri, 16 Oct 2020 16:38:10 +0300 Subject: [PATCH 09/22] OpenMP3 task is done --- OpenMP3/src/main.cpp | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/OpenMP3/src/main.cpp b/OpenMP3/src/main.cpp index 416ee06..2ae7077 100644 --- a/OpenMP3/src/main.cpp +++ b/OpenMP3/src/main.cpp @@ -9,9 +9,36 @@ double func(double x) return sin(x); } +double trapezoid(double x0, double x1, double dx) { + return dx * (func(x0) + func(x1)) * 0.5; +} + double calc(double x0, double x1, double dx, uint32_t num_threads) { - return 0; + int num_of_dots = (x1 - x0) / dx + 1; + double* dots = (double*)malloc(num_of_dots * sizeof(double)); + double res = 0.0; + double trap = 0.0; + double c = 0.0; + double y = 0.0; + double t = 0.0; + #pragma omp parallel num_threads(num_threads) + { + #pragma omp for + for (int i = 0; i < num_of_dots; i++) { + dots[i] = x0 + i * dx; + } + #pragma omp for reduction(+:res) private(y, t, c, trap) + for (int i = 0; i < num_of_dots - 1; i++) { + trap = trapezoid(dots[i], dots[i+1], dx); + y = trap - c; + t = res + y; + c = (t - res) - y; + res = t; + } + } + free(dots); + return res; } int main(int argc, char** argv) From a5f5485144f5729dbef53a967b92edc0895d8b12 Mon Sep 17 00:00:00 2001 From: Daniil Vorobyev Date: Mon, 19 Oct 2020 10:42:29 +0300 Subject: [PATCH 10/22] OpenMP4 task is done --- OpenMP4/src/main.cpp | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/OpenMP4/src/main.cpp b/OpenMP4/src/main.cpp index 036d8e3..0a5e133 100644 --- a/OpenMP4/src/main.cpp +++ b/OpenMP4/src/main.cpp @@ -5,7 +5,32 @@ double calc(uint32_t x_last, uint32_t num_threads) { - return 0; + double* loc_res = (double*)calloc(num_threads, sizeof(double)); + double* loc_fact = (double*)malloc(num_threads * sizeof(double)); + + #pragma omp parallel num_threads(num_threads) + { + int tid = omp_get_thread_num(); + loc_fact[tid] = 1.0; + + #pragma omp for + for (uint32_t i = 1; i < x_last; i++) { + loc_fact[tid] /= double(i); + loc_res[tid] += loc_fact[tid]; + } + } + + double res = 1.0; + double fact = 1.0; + + for (uint32_t tid = 0; tid < num_threads; tid++) { + res += loc_res[tid] * fact; + fact *= loc_fact[tid]; + } + + free(loc_fact); + free(loc_res); + return res; } int main(int argc, char** argv) From 27fd01b18ae1ae92c70503354969bed5fb075e65 Mon Sep 17 00:00:00 2001 From: Daniil Vorobyev Date: Thu, 22 Oct 2020 10:53:12 +0300 Subject: [PATCH 11/22] OpenMP5 task is done --- OpenMP5/src/main.cpp | 88 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 2 deletions(-) diff --git a/OpenMP5/src/main.cpp b/OpenMP5/src/main.cpp index bf042c5..b24b04e 100644 --- a/OpenMP5/src/main.cpp +++ b/OpenMP5/src/main.cpp @@ -5,7 +5,91 @@ void calc(uint32_t xSize, uint32_t ySize, uint32_t iterations, uint32_t num_threads, uint8_t* inputFrame, uint8_t* outputFrame) { + int* inFrame = (int*)malloc(xSize*ySize * sizeof(int)); + int* outFrame = (int *)malloc(xSize*ySize * sizeof(int)); + for (uint32_t y = 0; y < ySize; y++) { + for (uint32_t x = 0; x < xSize; x++) { + outFrame[y * xSize + x] = (int)inputFrame[y * xSize + x]; + } + } + uint32_t block_size = xSize / num_threads; + uint32_t block_extra = xSize % num_threads; + #pragma omp parallel num_threads(num_threads) + { + uint32_t tid = omp_get_thread_num(); + + uint32_t first = tid * block_size; + uint32_t last = (tid + 1) * block_size; + + if (tid == num_threads - 1) { + last += block_extra; + } + + + for (uint32_t i = 0; i < iterations; i++) { + #pragma omp barrier + #pragma omp single + { + int* ptr = inFrame; + inFrame = outFrame; + outFrame = ptr; + } + for (uint32_t x = first; x < last; x++) { + for (uint32_t y = 0; y < ySize; y++) { + uint32_t count = 0; + + uint32_t x1 = x == 0 ? xSize - 1 : x - 1; + uint32_t x2 = x == xSize - 1 ? 0 : x + 1; + uint32_t y1 = y == 0 ? ySize - 1 : y - 1; + uint32_t y2 = y == ySize - 1 ? 0 : y + 1; + + + if (inFrame[y1 * xSize + x] == 1){ + count++; + } + if (inFrame[y1 * xSize + x1] == 1) { + count++; + } + if (inFrame[y1 * xSize + x2] == 1) { + count++; + } + if (inFrame[y2 * xSize + x1] == 1) { + count++; + } + if (inFrame[y2 * xSize + x2] == 1) { + count++; + } + + if (inFrame[y2 * xSize + x] == 1) { + count++; + } + if (inFrame[y * xSize + x1] == 1) { + count++; + } + if (inFrame[y * xSize + x2] == 1) { + count++; + } + + if (inFrame[y * xSize + x] == 0 && count == 3) { + outFrame[y * xSize + x] = 1; + } else if (inFrame[y * xSize + x] == 1 && (count < 2 || count > 3)) { + outFrame[y * xSize + x] = 0; + } else { + outFrame[y * xSize + x] = inFrame[y * xSize + x]; + } + } + } + } + } + + for (uint32_t y = 0; y < ySize; y++) { + for (uint32_t x = 0; x < xSize; x++) { + outputFrame[y * xSize + x] = outFrame[y * xSize + x]; + } + } + free(inFrame); + free(outFrame); } int main(int argc, char** argv) @@ -63,8 +147,8 @@ int main(int argc, char** argv) } // Prepare to exit - delete outputFrame; - delete inputFrame; + delete[] outputFrame; + delete[] inputFrame; output.close(); input.close(); return 0; From cf486ebcb8069fb5284e78d879e401b39296253e Mon Sep 17 00:00:00 2001 From: Daniil Vorobyev Date: Wed, 28 Oct 2020 22:06:51 +0300 Subject: [PATCH 12/22] heatmap is done --- heatmap.c | 50 +++++++++++++++++++++++++++++++++++++++++++ heatmap/heatmap.c | 50 +++++++++++++++++++++++++++++++++++++++++++ heatmap/heatmap.xlsx | Bin 0 -> 18138 bytes 3 files changed, 100 insertions(+) create mode 100644 heatmap.c create mode 100644 heatmap/heatmap.c create mode 100644 heatmap/heatmap.xlsx diff --git a/heatmap.c b/heatmap.c new file mode 100644 index 0000000..916f90d --- /dev/null +++ b/heatmap.c @@ -0,0 +1,50 @@ +#include +#include + +int create_thread(int n) +{ + int res = 0; + #pragma omp parallel num_threads(n) + { + res++; + } + return res; +} + +int main() +{ + FILE * fp; + fp = fopen("heatmap.csv","w"); + for (int x = 0; x <= 30; x++) { + if (x != 30) { + fprintf(fp, "%d,", x); + } else { + fprintf(fp, "%d\n", x); + } + } + + omp_set_nested(1); + for (int y = 1; y <= 30; y++) { + fprintf(fp, "%d,", y); + for (int x = 1; x <= 30; x++) { + double start = omp_get_wtime(); + int res = 0; + #pragma omp parallel for num_threads(x) + for (int i = 0; i < 1000; i++) { + res += create_thread(y); + } + double end = omp_get_wtime(); + if (x != 30) { + fprintf(fp, "%lf,", end - start); + } else { + fprintf(fp, "%lf\n", end - start); + } + } + } + + int res = 0; + + + + return 0; +} \ No newline at end of file diff --git a/heatmap/heatmap.c b/heatmap/heatmap.c new file mode 100644 index 0000000..916f90d --- /dev/null +++ b/heatmap/heatmap.c @@ -0,0 +1,50 @@ +#include +#include + +int create_thread(int n) +{ + int res = 0; + #pragma omp parallel num_threads(n) + { + res++; + } + return res; +} + +int main() +{ + FILE * fp; + fp = fopen("heatmap.csv","w"); + for (int x = 0; x <= 30; x++) { + if (x != 30) { + fprintf(fp, "%d,", x); + } else { + fprintf(fp, "%d\n", x); + } + } + + omp_set_nested(1); + for (int y = 1; y <= 30; y++) { + fprintf(fp, "%d,", y); + for (int x = 1; x <= 30; x++) { + double start = omp_get_wtime(); + int res = 0; + #pragma omp parallel for num_threads(x) + for (int i = 0; i < 1000; i++) { + res += create_thread(y); + } + double end = omp_get_wtime(); + if (x != 30) { + fprintf(fp, "%lf,", end - start); + } else { + fprintf(fp, "%lf\n", end - start); + } + } + } + + int res = 0; + + + + return 0; +} \ No newline at end of file diff --git a/heatmap/heatmap.xlsx b/heatmap/heatmap.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..e83a72d5d0207029c34d8b8cabb37d369a818344 GIT binary patch literal 18138 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 Date: Wed, 28 Oct 2020 22:08:32 +0300 Subject: [PATCH 13/22] deleted heatmap.c --- heatmap.c | 50 -------------------------------------------------- 1 file changed, 50 deletions(-) delete mode 100644 heatmap.c diff --git a/heatmap.c b/heatmap.c deleted file mode 100644 index 916f90d..0000000 --- a/heatmap.c +++ /dev/null @@ -1,50 +0,0 @@ -#include -#include - -int create_thread(int n) -{ - int res = 0; - #pragma omp parallel num_threads(n) - { - res++; - } - return res; -} - -int main() -{ - FILE * fp; - fp = fopen("heatmap.csv","w"); - for (int x = 0; x <= 30; x++) { - if (x != 30) { - fprintf(fp, "%d,", x); - } else { - fprintf(fp, "%d\n", x); - } - } - - omp_set_nested(1); - for (int y = 1; y <= 30; y++) { - fprintf(fp, "%d,", y); - for (int x = 1; x <= 30; x++) { - double start = omp_get_wtime(); - int res = 0; - #pragma omp parallel for num_threads(x) - for (int i = 0; i < 1000; i++) { - res += create_thread(y); - } - double end = omp_get_wtime(); - if (x != 30) { - fprintf(fp, "%lf,", end - start); - } else { - fprintf(fp, "%lf\n", end - start); - } - } - } - - int res = 0; - - - - return 0; -} \ No newline at end of file From d2f51029638417edaa2ffb7d71723bc2c2819564 Mon Sep 17 00:00:00 2001 From: Daniil Vorobyev Date: Mon, 2 Nov 2020 00:59:42 +0300 Subject: [PATCH 14/22] Loop1 is done --- Loop1/src/main.cpp | 51 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/Loop1/src/main.cpp b/Loop1/src/main.cpp index 318f940..5380c5c 100644 --- a/Loop1/src/main.cpp +++ b/Loop1/src/main.cpp @@ -5,18 +5,49 @@ #include #include +void sum(double* res, uint32_t xSize, uint32_t ySize) { + for (uint32_t y = 0; y < ySize; y++) { + for (uint32_t x = 0; x < xSize; x++) { + res[y*xSize + x] = sin(0.00001*res[y*xSize + x]); + } + } +} + + void calc(double* arr, uint32_t ySize, uint32_t xSize, int rank, int size) { - if (rank == 0 && size > 0) - { - for (uint32_t y = 0; y < ySize; y++) - { - for (uint32_t x = 0; x < xSize; x++) - { - arr[y*xSize + x] = sin(0.00001*arr[y*xSize + x]); - } - } - } + MPI_Bcast(&ySize, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(&xSize, 1, MPI_INT, 0, MPI_COMM_WORLD); + uint32_t loc_ySize = ySize / size; + if (rank < (int)ySize % size) { + loc_ySize++; + } + double* res = (double*)malloc(loc_ySize * xSize * sizeof(double)); + + if (rank == 0) { + int* displs = (int*)malloc(size * sizeof(int)); + int* sendcounts = (int*)malloc(size * sizeof(int)); + int offset = 0; + for (int i = 0; i < size; i++) { + displs[i] = offset; + sendcounts[i] = ySize / size; + if (i < (int)ySize % size) { + sendcounts[i]++; + } + sendcounts[i] *= xSize; + offset += sendcounts[i]; + } + MPI_Scatterv(arr, sendcounts, displs, MPI_DOUBLE, res, loc_ySize * xSize, MPI_DOUBLE, 0, MPI_COMM_WORLD); + sum(res, xSize, loc_ySize); + MPI_Gatherv(res, loc_ySize * xSize, MPI_DOUBLE, arr, sendcounts, displs, MPI_DOUBLE, 0, MPI_COMM_WORLD); + free(displs); + free(sendcounts); + } else { + MPI_Scatterv(NULL, NULL, NULL, 0, res, loc_ySize * xSize, MPI_DOUBLE, 0, MPI_COMM_WORLD); + sum(res, xSize, loc_ySize); + MPI_Gatherv(res, loc_ySize * xSize, MPI_DOUBLE, NULL, NULL, NULL, 0, 0, MPI_COMM_WORLD); + } + free(res); } int main(int argc, char** argv) From 7242c01798a00ef8f368aa54e6d1501690a6510d Mon Sep 17 00:00:00 2001 From: Daniil Vorobyev Date: Wed, 4 Nov 2020 04:44:52 +0300 Subject: [PATCH 15/22] Loop2 is done --- Loop2/src/main.cpp | 57 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/Loop2/src/main.cpp b/Loop2/src/main.cpp index 51ea220..da67f0d 100644 --- a/Loop2/src/main.cpp +++ b/Loop2/src/main.cpp @@ -5,17 +5,60 @@ #include #include +void sum(double* res, uint32_t xSize, uint32_t ySize) { + for (uint32_t y = 0; y < ySize - 1; y++) { + for (uint32_t x = 3; x < xSize; x++) { + res[y*xSize + x] = sin(0.00001*res[(y+1)*xSize + x - 3]); + } + } +} + + void calc(double* arr, uint32_t ySize, uint32_t xSize, int rank, int size) { - if (rank == 0 && size > 0) - { - for (uint32_t y = 0; y < ySize - 1; y++) - { - for (uint32_t x = 3; x < xSize; x++) - { - arr[y*xSize + x] = sin(0.00001*arr[(y + 1)*xSize + x - 3]); + MPI_Status status; + MPI_Bcast(&ySize, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(&xSize, 1, MPI_INT, 0, MPI_COMM_WORLD); + uint32_t loc_ySize = ySize / size; + if (rank < (int)(ySize % size)){ + loc_ySize++; + } + if (rank == size - 1) { + loc_ySize--; + } + if (rank == 0) { + uint32_t send_ySize = loc_ySize; + uint32_t send_yAddr = loc_ySize; + for (int i = 1; i < size; i++) { + if (i == (int)(ySize % size)) { + send_ySize--; + } + if (i == size - 1) { + send_ySize--; + } + MPI_Send(&arr[send_yAddr * xSize], (send_ySize + 1) * xSize, MPI_DOUBLE, i, 0, MPI_COMM_WORLD); + send_yAddr += send_ySize; + } + } else { + arr = (double*) malloc((loc_ySize + 1) * xSize * sizeof(double)); + MPI_Recv(arr, (loc_ySize + 1) * xSize, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &status); + } + sum(arr, xSize, loc_ySize + 1); + if (rank == 0) { + uint32_t recv_ySize = loc_ySize; + uint32_t recv_yAddr = loc_ySize; + for (int i = 1; i < size; i++) { + if (i == (int)(ySize % size)) { + recv_ySize--; } + if (i == size - 1) { + recv_ySize--; + } + MPI_Recv(&arr[recv_yAddr * xSize], recv_ySize * xSize, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, &status); + recv_yAddr += recv_ySize; } + } else { + MPI_Send(arr, loc_ySize * xSize, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD); } } From 4690e9621935b7f81bf77ac8c45d6f6e9a231a5f Mon Sep 17 00:00:00 2001 From: Daniil Vorobyev Date: Thu, 5 Nov 2020 23:23:13 +0300 Subject: [PATCH 16/22] Loop3 is done --- Loop3/src/main.cpp | 76 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 69 insertions(+), 7 deletions(-) diff --git a/Loop3/src/main.cpp b/Loop3/src/main.cpp index 43cce1f..76c1366 100644 --- a/Loop3/src/main.cpp +++ b/Loop3/src/main.cpp @@ -5,17 +5,79 @@ #include #include +void sum(double* arr, uint32_t xSize, uint32_t ySize, uint32_t start, int& iter) { + iter = 0; + for (uint32_t y = 4 + start; y < ySize; y += 4) { + iter++; + for (uint32_t x = 0; x < xSize; x++) { + arr[y*xSize + x] = sin(arr[(y - 4)*xSize + x]); + } + } +} + void calc(double* arr, uint32_t ySize, uint32_t xSize, int rank, int size) { - if (rank == 0 && size > 0) - { - for (uint32_t y = 4; y < ySize; y++) - { - for (uint32_t x = 0; x < xSize; x++) - { - arr[y*xSize + x] = sin(arr[(y - 4)*xSize + x]); + if (rank < 4) { + MPI_Status status; + MPI_Bcast(&ySize, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(&xSize, 1, MPI_INT, 0, MPI_COMM_WORLD); + uint32_t loc_ySize = 0, loc_yAddr = 0; + + if (rank ==0) { + loc_yAddr = 0; + loc_ySize = 4 / size; + if (rank < (int)(4 % size)) + loc_ySize++; + uint32_t send_ySize = loc_ySize; + uint32_t send_yAddr = loc_ySize; + if (size >= 4) { + size = 4; } + + for (int i = 1; i < size; i++) { + if (i == (int)(4 % size)) { + send_ySize--; + } + MPI_Send(&send_ySize, 1, MPI_INT, i, 0, MPI_COMM_WORLD); + MPI_Send(&send_yAddr, 1, MPI_INT, i, 0, MPI_COMM_WORLD); + MPI_Send(&arr[send_yAddr * xSize], send_ySize * xSize, MPI_DOUBLE, i, 0, MPI_COMM_WORLD); + send_yAddr += send_ySize; + } + } else { + arr = (double*) malloc(ySize * xSize * sizeof(double)); + MPI_Recv(&loc_ySize, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status); + MPI_Recv(&loc_yAddr, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status); + MPI_Recv(&arr[loc_yAddr * xSize], loc_ySize * xSize, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &status); } + int iter; + + for (uint32_t i = 0; i < loc_ySize; i++) { + sum(arr, xSize, ySize, loc_yAddr + i, iter); + } + + + if (rank == 0) { + uint32_t send_ySize = loc_ySize; + uint32_t send_yAddr = loc_ySize; + for (int i = 1; i < size; i++) { + if (i == (int)(4 % size)) { + send_ySize--; + } + MPI_Recv(&iter, 1, MPI_INT, i, 0, MPI_COMM_WORLD, &status); + MPI_Datatype floattype; + MPI_Type_vector(iter, xSize * send_ySize, xSize * 4, MPI_DOUBLE, &floattype); + MPI_Type_commit(&floattype); + MPI_Recv(&arr[(send_yAddr + 4) * xSize], 1, floattype, i, 0, MPI_COMM_WORLD, &status); + send_yAddr += send_ySize; + } + } else { + MPI_Datatype floattype; + MPI_Type_vector(iter, xSize * loc_ySize, xSize * 4, MPI_DOUBLE, &floattype); + MPI_Type_commit(&floattype); + MPI_Send(&iter, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); + MPI_Send(&arr[(loc_yAddr + 4) * xSize], 1, floattype, 0, 0, MPI_COMM_WORLD); + } + } } From 479ff38695151e695b64ed2255d7c5ae1bc73539 Mon Sep 17 00:00:00 2001 From: Daniil Vorobyev Date: Fri, 6 Nov 2020 18:16:01 +0300 Subject: [PATCH 17/22] Loop4 is done --- Loop4/src/main.cpp | 114 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 109 insertions(+), 5 deletions(-) diff --git a/Loop4/src/main.cpp b/Loop4/src/main.cpp index d958d54..954160e 100644 --- a/Loop4/src/main.cpp +++ b/Loop4/src/main.cpp @@ -7,14 +7,118 @@ void calc(double* arr, uint32_t zSize, uint32_t ySize, uint32_t xSize, int rank, int size) { - if (rank == 0 && size > 0) { - for (uint32_t z = 1; z < zSize; z++) { - for (uint32_t y = 0; y < ySize - 1; y++) { - for (uint32_t x = 0; x < xSize - 1; x++) { - arr[z*ySize*xSize + y*xSize + x] = sin(arr[(z - 1)*ySize*xSize + (y + 1)*xSize + x + 1]); + MPI_Status status; + MPI_Bcast(&xSize, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(&ySize, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(&zSize, 1, MPI_INT, 0, MPI_COMM_WORLD); + uint32_t num_of_tasks, arr_size = 0, arr_addr = 0; + + if (rank == 0) { + double* new_arr = (double *) malloc(zSize * ySize * xSize * sizeof(double)); + bool* added = (bool *) calloc(zSize * ySize * xSize, sizeof(bool)); + int z, y, x; + uint32_t* tasks = (uint32_t*) malloc(zSize * ySize * xSize * sizeof(uint32_t)); + uint32_t counter = 0, task_counter = 0, local_counter = 0, send_num_of_tasks, send_task_addr, send_arr_size[size], send_arr_addr; + for (int i = 0; i < (int)zSize; i++) { + for (int j = 0; j < (int)ySize; j++) { + for (int k = 0; k < (int)xSize; k++) { + if (added[i * ySize * xSize + j * xSize + k] == false) { + z = i; + y = j; + x = k; + local_counter = 0; + while (z < (int)zSize && y >= 0 && x >= 0) { + added[z * ySize * xSize + y * xSize + x] = true; + new_arr[counter] = arr[z * ySize * xSize + y * xSize + x]; + counter++; + local_counter++; + z++; + y--; + x--; + } + tasks[task_counter] = local_counter; + task_counter++; + } + } + } + } + num_of_tasks = task_counter / size; + if (task_counter % size > 0) { + num_of_tasks++; + } + send_arr_addr = 0; + for (int i = 0; i < (int)num_of_tasks; i++) { + arr_size += tasks[i]; + } + send_arr_addr = arr_size; + send_num_of_tasks = num_of_tasks; + send_task_addr = num_of_tasks; + for (int i = 1; i < size; i++) { + send_arr_size[i] = 0; + if (i == (int)task_counter % size) { + send_num_of_tasks--; + } + for (int j = 0; j < (int)send_num_of_tasks; j++) { + send_arr_size[i] += tasks[send_task_addr + j]; + } + MPI_Send(&send_num_of_tasks, 1, MPI_INT, i, 0, MPI_COMM_WORLD); + MPI_Send(&send_arr_size[i], 1, MPI_INT, i, 0, MPI_COMM_WORLD); + MPI_Send(&tasks[send_task_addr], send_num_of_tasks, MPI_INT, i, 0, MPI_COMM_WORLD); + MPI_Send(&new_arr[send_arr_addr], send_arr_size[i], MPI_DOUBLE, i, 0, MPI_COMM_WORLD); + send_arr_addr += send_arr_size[i]; + send_task_addr += send_num_of_tasks; + } + for (int i = 0; i < (int)num_of_tasks; i++) { + for (int j = 0; j < (int)(tasks[i] - 1); j++) { + new_arr[j + arr_addr + 1] = sin(new_arr[j + arr_addr]); + } + arr_addr += tasks[i]; + } + send_arr_addr = arr_size; + for (int i = 1; i < size; i++) { + MPI_Recv(&new_arr[send_arr_addr], send_arr_size[i], MPI_DOUBLE, i, 0, MPI_COMM_WORLD, &status); + send_arr_addr += send_arr_size[i]; + } + counter = 0; + for (int i = 0; i < (int)zSize; i++) { + for (int j = 0; j < (int)ySize; j++) { + for (int k = 0; k < (int)xSize; k++) { + if (added[i * ySize * xSize + j * xSize + k] == true) { + z = i; + y = j; + x = k; + while (z < (int)zSize && y >= 0 && x >= 0) { + added[z * ySize * xSize + y * xSize + x] = false; + arr[z * ySize * xSize + y * xSize + x] = new_arr[counter]; + counter++; + z++; + y--; + x--; + } + } } } } + } else { + MPI_Recv(&num_of_tasks, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status); + MPI_Recv(&arr_size, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status); + uint32_t* tasks = (uint32_t *) malloc(num_of_tasks * sizeof(uint32_t)); + arr = (double *) malloc(arr_size * sizeof(double)); + MPI_Recv(tasks, num_of_tasks, MPI_INT, 0, 0, MPI_COMM_WORLD, &status); + MPI_Recv(arr, arr_size, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &status); + + std::ofstream output("output" + std::to_string(rank) + ".txt"); + for (uint32_t z = 0; z < arr_size; z++) { + output << " " << arr[z]; + } + output.close(); + for (int i = 0; i < (int)num_of_tasks; i++) { + for (int j = 0; j < (int)(tasks[i] - 1); j++) { + arr[j + arr_addr + 1] = sin(arr[j + arr_addr]); + } + arr_addr += tasks[i]; + } + MPI_Send(arr, arr_size, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD); } } From 4e6de9be59b8a608e818dadf3f635b1d31569161 Mon Sep 17 00:00:00 2001 From: Daniil Vorobyev Date: Sat, 7 Nov 2020 18:49:04 +0300 Subject: [PATCH 18/22] dynamic arrays are free'd --- Loop4/src/main.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/Loop4/src/main.cpp b/Loop4/src/main.cpp index 954160e..3185580 100644 --- a/Loop4/src/main.cpp +++ b/Loop4/src/main.cpp @@ -8,9 +8,7 @@ void calc(double* arr, uint32_t zSize, uint32_t ySize, uint32_t xSize, int rank, int size) { MPI_Status status; - MPI_Bcast(&xSize, 1, MPI_INT, 0, MPI_COMM_WORLD); - MPI_Bcast(&ySize, 1, MPI_INT, 0, MPI_COMM_WORLD); - MPI_Bcast(&zSize, 1, MPI_INT, 0, MPI_COMM_WORLD); + uint32_t num_of_tasks, arr_size = 0, arr_addr = 0; if (rank == 0) { @@ -99,6 +97,8 @@ void calc(double* arr, uint32_t zSize, uint32_t ySize, uint32_t xSize, int rank, } } } + free(added); + free(new_arr); } else { MPI_Recv(&num_of_tasks, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status); MPI_Recv(&arr_size, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status); @@ -106,12 +106,6 @@ void calc(double* arr, uint32_t zSize, uint32_t ySize, uint32_t xSize, int rank, arr = (double *) malloc(arr_size * sizeof(double)); MPI_Recv(tasks, num_of_tasks, MPI_INT, 0, 0, MPI_COMM_WORLD, &status); MPI_Recv(arr, arr_size, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &status); - - std::ofstream output("output" + std::to_string(rank) + ".txt"); - for (uint32_t z = 0; z < arr_size; z++) { - output << " " << arr[z]; - } - output.close(); for (int i = 0; i < (int)num_of_tasks; i++) { for (int j = 0; j < (int)(tasks[i] - 1); j++) { arr[j + arr_addr + 1] = sin(arr[j + arr_addr]); @@ -119,6 +113,7 @@ void calc(double* arr, uint32_t zSize, uint32_t ySize, uint32_t xSize, int rank, arr_addr += tasks[i]; } MPI_Send(arr, arr_size, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD); + free(arr); } } From 1b9d5cb5734c6addc87f76ecc9fd75d8831ccdda Mon Sep 17 00:00:00 2001 From: Daniil Vorobyev Date: Sat, 7 Nov 2020 20:14:20 +0300 Subject: [PATCH 19/22] dynamic arrays are free'd --- Loop2/src/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Loop2/src/main.cpp b/Loop2/src/main.cpp index da67f0d..d0a91c0 100644 --- a/Loop2/src/main.cpp +++ b/Loop2/src/main.cpp @@ -59,6 +59,7 @@ void calc(double* arr, uint32_t ySize, uint32_t xSize, int rank, int size) } } else { MPI_Send(arr, loc_ySize * xSize, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD); + free(arr); } } From 3023a7e08e0753fcad77e632924a78af08409bad Mon Sep 17 00:00:00 2001 From: Daniil Vorobyev Date: Tue, 10 Nov 2020 19:30:24 +0300 Subject: [PATCH 20/22] Loop3 is done --- Loop3/src/main.cpp | 121 +++++++++++++++++++-------------------------- 1 file changed, 51 insertions(+), 70 deletions(-) diff --git a/Loop3/src/main.cpp b/Loop3/src/main.cpp index 76c1366..abc7abf 100644 --- a/Loop3/src/main.cpp +++ b/Loop3/src/main.cpp @@ -5,80 +5,61 @@ #include #include -void sum(double* arr, uint32_t xSize, uint32_t ySize, uint32_t start, int& iter) { - iter = 0; - for (uint32_t y = 4 + start; y < ySize; y += 4) { - iter++; - for (uint32_t x = 0; x < xSize; x++) { - arr[y*xSize + x] = sin(arr[(y - 4)*xSize + x]); - } - } +void sum(double* arr, uint32_t xSize, uint32_t ySize) { + for (uint32_t x = 0; x < xSize; x++) { + for (uint32_t y = 4; y < ySize; y++) { + arr[x*ySize + y] = sin(arr[x*ySize + (y-4)]); + } + } } void calc(double* arr, uint32_t ySize, uint32_t xSize, int rank, int size) { - if (rank < 4) { - MPI_Status status; - MPI_Bcast(&ySize, 1, MPI_INT, 0, MPI_COMM_WORLD); - MPI_Bcast(&xSize, 1, MPI_INT, 0, MPI_COMM_WORLD); - uint32_t loc_ySize = 0, loc_yAddr = 0; - - if (rank ==0) { - loc_yAddr = 0; - loc_ySize = 4 / size; - if (rank < (int)(4 % size)) - loc_ySize++; - uint32_t send_ySize = loc_ySize; - uint32_t send_yAddr = loc_ySize; - if (size >= 4) { - size = 4; - } - - for (int i = 1; i < size; i++) { - if (i == (int)(4 % size)) { - send_ySize--; - } - MPI_Send(&send_ySize, 1, MPI_INT, i, 0, MPI_COMM_WORLD); - MPI_Send(&send_yAddr, 1, MPI_INT, i, 0, MPI_COMM_WORLD); - MPI_Send(&arr[send_yAddr * xSize], send_ySize * xSize, MPI_DOUBLE, i, 0, MPI_COMM_WORLD); - send_yAddr += send_ySize; - } - } else { - arr = (double*) malloc(ySize * xSize * sizeof(double)); - MPI_Recv(&loc_ySize, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status); - MPI_Recv(&loc_yAddr, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status); - MPI_Recv(&arr[loc_yAddr * xSize], loc_ySize * xSize, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &status); - } - int iter; - - for (uint32_t i = 0; i < loc_ySize; i++) { - sum(arr, xSize, ySize, loc_yAddr + i, iter); - } - - - if (rank == 0) { - uint32_t send_ySize = loc_ySize; - uint32_t send_yAddr = loc_ySize; - for (int i = 1; i < size; i++) { - if (i == (int)(4 % size)) { - send_ySize--; - } - MPI_Recv(&iter, 1, MPI_INT, i, 0, MPI_COMM_WORLD, &status); - MPI_Datatype floattype; - MPI_Type_vector(iter, xSize * send_ySize, xSize * 4, MPI_DOUBLE, &floattype); - MPI_Type_commit(&floattype); - MPI_Recv(&arr[(send_yAddr + 4) * xSize], 1, floattype, i, 0, MPI_COMM_WORLD, &status); - send_yAddr += send_ySize; - } - } else { - MPI_Datatype floattype; - MPI_Type_vector(iter, xSize * loc_ySize, xSize * 4, MPI_DOUBLE, &floattype); - MPI_Type_commit(&floattype); - MPI_Send(&iter, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); - MPI_Send(&arr[(loc_yAddr + 4) * xSize], 1, floattype, 0, 0, MPI_COMM_WORLD); - } - - } + MPI_Bcast(&ySize, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(&xSize, 1, MPI_INT, 0, MPI_COMM_WORLD); + uint32_t loc_xSize = xSize / size; + if (rank < (int)xSize % size) { + loc_xSize++; + } + double* res = (double*)malloc(loc_xSize * ySize * sizeof(double)); + + if (rank == 0) { + double* arr_T = (double *)malloc(ySize * xSize * sizeof(double)); + for(int i = 0; i < (int)ySize; i++) { + for(int j = 0; j < (int)xSize; j++) { + arr_T[j*ySize + i] = arr[i*xSize + j]; + } + } + + int* displs = (int*)malloc(size * sizeof(int)); + int* sendcounts = (int*)malloc(size * sizeof(int)); + int offset = 0; + for (int i = 0; i < size; i++) { + displs[i] = offset; + sendcounts[i] = xSize / size; + if (i < (int)xSize % size) { + sendcounts[i]++; + } + sendcounts[i] *= ySize; + offset += sendcounts[i]; + } + MPI_Scatterv(arr_T, sendcounts, displs, MPI_DOUBLE, res, loc_xSize * ySize, MPI_DOUBLE, 0, MPI_COMM_WORLD); + sum(res, loc_xSize, ySize); + MPI_Gatherv(res, loc_xSize * ySize, MPI_DOUBLE, arr_T, sendcounts, displs, MPI_DOUBLE, 0, MPI_COMM_WORLD); + for(int i = 0; i < (int)xSize; i++) { + for(int j = 0; j < (int)ySize; j++) { + arr[j*xSize + i] = arr_T[i*ySize + j]; + } + } + free(displs); + free(sendcounts); + free(arr_T); + } else { + MPI_Scatterv(NULL, NULL, NULL, 0, res, loc_xSize * ySize, MPI_DOUBLE, 0, MPI_COMM_WORLD); + sum(res, loc_xSize, ySize); + MPI_Gatherv(res, loc_xSize * ySize, MPI_DOUBLE, NULL, NULL, NULL, 0, 0, MPI_COMM_WORLD); + } + free(res); } int main(int argc, char** argv) From ae2517500ff9e556c232954d7a776f31807897eb Mon Sep 17 00:00:00 2001 From: Daniil Vorobyev Date: Mon, 23 Nov 2020 19:59:14 +0300 Subject: [PATCH 21/22] CompMath1 task is done --- CompMath1/src/main.cpp | 96 ++++++++++++++++++++++++++++++++---------- 1 file changed, 74 insertions(+), 22 deletions(-) diff --git a/CompMath1/src/main.cpp b/CompMath1/src/main.cpp index 7e114bd..e2bf63e 100644 --- a/CompMath1/src/main.cpp +++ b/CompMath1/src/main.cpp @@ -12,32 +12,84 @@ double acceleration(double t) void calc(double* trace, uint32_t traceSize, double t0, double dt, double y0, double y1, int rank, int size) { - // Sighting shot - double v0 = 0; - if (rank == 0 && size > 0) - { - trace[0] = y0; - trace[1] = y0 + dt*v0; - for (uint32_t i = 2; i < traceSize; i++) - { - trace[i] = dt*dt*acceleration(t0 + (i - 1)*dt) + 2*trace[i - 1] - trace[i - 2]; - } - } + MPI_Status status; + MPI_Bcast (&traceSize, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast (&t0, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); + MPI_Bcast (&dt, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); - // The final shot - if (rank == 0 && size > 0) - { - v0 = (y1 - trace[traceSize - 1])/(dt*traceSize); - trace[0] = y0; - trace[1] = y0 + dt*v0; - for (uint32_t i = 2; i < traceSize; i++) - { - trace[i] = dt*dt*acceleration(t0 + (i - 1)*dt) + 2*trace[i - 1] - trace[i - 2]; - } - } + uint32_t mySize = traceSize / size; + if (rank == 0) { + mySize += traceSize % size; + } + double tau = dt * mySize; + + if (rank != 0) { + trace = (double *)malloc(mySize * sizeof(double)); + } + // Sighting shot + double v0 = 0, v1, myY1; + t0 += tau * rank; + if (rank != 0) { + t0 += dt * (traceSize % size); + } + trace[0] = y0; + trace[1] = y0 + dt*v0; + for (uint32_t i = 2; i < mySize; i++) { + trace[i] = dt*dt*acceleration(t0 + (i - 1)*dt) + 2*trace[i - 1] - trace[i - 2]; + } + + v1 = (trace[mySize - 1] - trace[mySize - 2]) / dt; + myY1 = trace[mySize - 1]; + + if (size == 1) { + v0 = (y1 - myY1) / tau; + } else { + double bufY, bufV; + if (rank == 0) { + MPI_Send(&myY1, 1, MPI_DOUBLE, 1, 0, MPI_COMM_WORLD); + MPI_Send(&v1, 1, MPI_DOUBLE, 1, 0, MPI_COMM_WORLD); + MPI_Recv(&bufY, 1, MPI_DOUBLE, size - 1, 0, MPI_COMM_WORLD, &status); + v0 = (y1 - bufY) / (traceSize * dt); + MPI_Bcast(&v0, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); + } else { + MPI_Recv(&bufY, 1, MPI_DOUBLE, rank - 1, 0, MPI_COMM_WORLD, &status); + MPI_Recv(&bufV, 1, MPI_DOUBLE, rank - 1, 0, MPI_COMM_WORLD, &status); + + myY1 += bufY + bufV * (mySize - 1) * dt; + v1 += bufV; + + if (rank != size - 1) { + MPI_Send(&myY1, 1, MPI_DOUBLE, rank + 1, 0, MPI_COMM_WORLD); + MPI_Send(&v1, 1, MPI_DOUBLE, rank + 1, 0, MPI_COMM_WORLD); + } else { + MPI_Send(&myY1, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD); + } + + MPI_Bcast(&v0, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); + y0 = bufY + v0 * tau * rank + v0 * dt * (traceSize % size); + v0 += bufV; + } + +} + // The final shot + trace[0] = y0; + trace[1] = y0 + dt*v0; + for (uint32_t i = 2; i < mySize; i++) { + trace[i] = dt*dt*acceleration(t0 + (i - 1)*dt) + 2*trace[i - 1] - trace[i - 2]; + } + if (rank == 0) { + mySize -= (traceSize % size); + for(int i = 1; i < size; i++) { + MPI_Recv(&trace[i * mySize + (traceSize % size)], mySize, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, &status); + } + } else { + MPI_Send(trace, mySize, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD); + free(trace); + } } + int main(int argc, char** argv) { int rank = 0, size = 0, status = 0; From ae6a4f00277db98bdc497d557b06aacd272005a6 Mon Sep 17 00:00:00 2001 From: Daniil Vorobyev Date: Fri, 27 Nov 2020 14:38:16 +0300 Subject: [PATCH 22/22] CompMath2 task is done --- CompMath2/src/main.cpp | 156 +++++++++++++++++++++++++++-------------- 1 file changed, 102 insertions(+), 54 deletions(-) diff --git a/CompMath2/src/main.cpp b/CompMath2/src/main.cpp index 5c4527a..3eafd87 100644 --- a/CompMath2/src/main.cpp +++ b/CompMath2/src/main.cpp @@ -7,64 +7,112 @@ void calc(double* frame, uint32_t ySize, uint32_t xSize, double delta, int rank, int size) { - if (rank == 0 && size > 0) - { - double diff = 0; - double* tmpFrame = new double[ySize * xSize]; - // Prepare tmpFrame - for (uint32_t y = 0; y < ySize; y++) - { - tmpFrame[y*xSize] = frame[y*xSize]; - tmpFrame[y*xSize + xSize - 1] = frame[y*xSize + xSize - 1]; - } - for (uint32_t x = 1; x < xSize - 1; x++) - { - tmpFrame[x] = frame[x]; - tmpFrame[(ySize - 1)*xSize + x] = frame[(ySize - 1)*xSize + x]; - } - // Calculate first iteration - for (uint32_t y = 1; y < ySize - 1; y++) - { - for (uint32_t x = 1; x < xSize - 1; x++) - { - tmpFrame[y*xSize + x] = (frame[(y + 1)*xSize + x] + frame[(y - 1)*xSize + x] +\ - frame[y*xSize + x + 1] + frame[y*xSize + x - 1])/4.0; - diff += std::abs(tmpFrame[y*xSize + x] - frame[y*xSize + x]); - } - } + MPI_Status status; + MPI_Bcast (&xSize, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast (&ySize, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast (&delta, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); - double* currFrame = tmpFrame; - double* nextFrame = frame; - uint32_t iteration = 1; - // Calculate frames - while (diff > delta) - { - diff = 0; - for (uint32_t y = 1; y < ySize - 1; y++) - { - for (uint32_t x = 1; x < xSize - 1; x++) - { - nextFrame[y*xSize + x] = (currFrame[(y + 1)*xSize + x] + currFrame[(y - 1)*xSize + x] +\ - currFrame[y*xSize + x + 1] + currFrame[y*xSize + x - 1])/4.0; - diff += std::abs(nextFrame[y*xSize + x] - currFrame[y*xSize + x]); - } - } - std::swap(currFrame, nextFrame); - iteration++; - } - // Copy result from tmp - if (iteration % 2 == 1) - { - for (uint32_t i = 0; i < xSize*ySize; i++) - { - frame[i] = tmpFrame[i]; - } - } - delete tmpFrame; - } + uint32_t mySize = ySize / size; + uint32_t yFirst = mySize * rank + ySize % size; + + if (rank == 0) { + yFirst = 1; + mySize += ySize % size - 1; + } + + if (rank == size - 1) { + mySize--; + } + + uint32_t yLast = yFirst + mySize; + + double diff = 0; + + if (mySize == 0) { + diff = 2 * delta; + } + + double* inFrame = (double *)malloc(xSize * ySize * sizeof(double)); + + if (rank > 0) { + frame = (double *)malloc(xSize * ySize * sizeof(double)); + } + + MPI_Bcast (frame, xSize * ySize, MPI_DOUBLE, 0, MPI_COMM_WORLD); + memcpy(inFrame, frame, xSize * ySize * sizeof (double)); + + for (uint32_t y = yFirst; y < yLast; y++) { + for (uint32_t x = 1; x < xSize - 1; x++) { + inFrame[y * xSize + (x)] = (frame[(y + 1) * xSize + x] + frame[(y - 1) * xSize + x] + frame[y * xSize + x + 1] + frame[y * xSize + x - 1]) / 4.0; + diff += std::abs(inFrame[y * xSize + x] - frame[y * xSize + x]); + } + } + + double* p; + + while (diff > delta) + { + p = inFrame; + inFrame = frame; + frame = p; + + diff = 0; + + if (size > 1) { + if (rank == 0) { + MPI_Send (inFrame + (yLast - 1) * xSize, xSize, MPI_DOUBLE, rank + 1, 0, MPI_COMM_WORLD); + } else { + MPI_Recv (inFrame + (yFirst - 1) * xSize, xSize, MPI_DOUBLE, rank - 1, 0, MPI_COMM_WORLD, &status); + if (rank != size - 1) { + MPI_Send (inFrame + (yLast - 1) * xSize, xSize, MPI_DOUBLE, rank + 1, 0, MPI_COMM_WORLD); + } + } + if (rank == size - 1) { + MPI_Send (inFrame + yFirst * xSize, xSize, MPI_DOUBLE, rank - 1, 0, MPI_COMM_WORLD); + } else { + MPI_Recv (inFrame + yLast * xSize, xSize, MPI_DOUBLE, rank + 1, 0, MPI_COMM_WORLD, &status); + if (rank != 0) { + MPI_Send (inFrame + yFirst * xSize, xSize, MPI_DOUBLE, rank - 1, 0, MPI_COMM_WORLD); + } + } + } + + + + for (uint32_t y = yFirst; y < yLast; y++) { + for (uint32_t x = 1; x < xSize - 1; x++) { + frame[y * xSize + x] = (inFrame[(y + 1) * xSize + x] + inFrame[(y - 1) * xSize + x] + inFrame[y * xSize + x + 1] + inFrame[y * xSize + x - 1]) / 4.0; + diff += std::abs(frame[y * xSize + x] - inFrame[y * xSize + x]); + } + } + + MPI_Allreduce(&diff, &diff, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + + } + + if (rank == 0) { + yFirst += mySize; + mySize -= (ySize % size - 1); + for (int i = 1; i < size; i++) { + if (i == size - 1) { + mySize--; + } + MPI_Recv (frame + yFirst * xSize, mySize * xSize, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, &status); + yFirst += mySize; + } + } else { + MPI_Send (frame + yFirst * xSize, mySize * xSize, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD); + } + + free (inFrame); + + if (rank > 0) { + free (frame); + } } + int main(int argc, char** argv) { int rank = 0, size = 0, status = 0;