-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Philipp Gschwandtner
committed
May 20, 2024
1 parent
176a787
commit 8b4841b
Showing
3 changed files
with
204 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# Assignment 10 | ||
|
||
The goal of this task is to practice using OpenMP tasks and take a first look at the heat stencil application. | ||
|
||
## Exercise 1 (1 Point) | ||
|
||
### Description | ||
|
||
This exercise consists of implementing a program that calculates Delannoy numbers with OpenMP tasks. | ||
|
||
A Delannoy number specifies the number of paths from the south-west corner of a 2D grid to the north-east corner, using only the per-step directions north, north-east, and east. See https://en.wikipedia.org/wiki/Delannoy_number for more information and a visualization. | ||
|
||
### Tasks | ||
|
||
- Implement a sequential program that computes the Delannoy number for a square 2D grid of size NxN where N is an input parameter for your program. If in doubt, base your implementation on the formula given in the Wikipedia article under "basic recurrence relation". Make sure your program is semantically correct by comparing the result against the Delannoy numbers given in the article. | ||
- Parallelize your program using OpenMP tasks and benchmark both the sequential and parallel implementation for several N between 3 and ~15. What can you observe? | ||
- What is the main bottleneck of your parallel implementation and how can it be improved without changing the underlying algorithm? | ||
- Enter the wall clock time of the sequential version and the parallel version for 1 and 12 threads for N=12 on LCC3 to the comparison spreadsheet linked on Discord. | ||
|
||
## Exercise 2 (2 Points) | ||
|
||
### Description | ||
|
||
This exercise consists of implementing a 2-dimensional heat stencil application. | ||
|
||
A large class of scientific applications are so-called stencil or structured grid applications. These simulate time-dependent physical processes such as the propagation of heat or pressure in a given medium. The core of the simulation operates on a grid and updates each cell with information from its neighbor cells. | ||
|
||
<img alt="heat_stencil" src="https://upload.wikimedia.org/wikipedia/commons/e/ec/2D_von_Neumann_Stencil.svg" width="40%"> | ||
|
||
### Tasks | ||
|
||
- Given the code in [heat_stencil_2D.c](heat_stencil_2D.c), finish the implementation: | ||
- implement the heat propagation by updating each cell with information from its neighbors. If in doubt, you can start with the formula given in https://en.wikipedia.org/wiki/Finite_difference_method#Example:_The_Laplace_operator | ||
- make sure the heat source stays the same through all iterations | ||
- if computing the value at the boundary, use temperature at the center position as the next value (e.g if you want to calculate A[0,1], use A[0,1] as the left neighbor cell instead of the non-existent A[-1,1]) | ||
- The simple verification at the end should pass | ||
- Parallelize the implementation using OpenMP. Investigate the use of the `collapse` clause and explain its purpose and effects. | ||
- Measure the time, speedup and efficiency of the stencil codes for varying problem sizes and numbers of threads. | ||
- Enter the wall clock time of the sequential version and the parallel version for 1 and 12 threads for 500x500 on LCC3 to the comparison spreadsheet linked on Discord. | ||
|
||
## General Notes | ||
|
||
All the material required by the tasks above (e.g., code, figures, text, etc...) must be part of the solution that is handed in. Your experiments should be reproducible and comparable to your measurements using the solution materials that you hand in. | ||
|
||
**Every** member of your group must be able to explain the given problem, your solution, and possible findings. You may also need to answer detailed questions about any of these aspects. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <errno.h> | ||
#include <omp.h> | ||
#include <string.h> | ||
|
||
#define RESOLUTION_WIDTH 50 | ||
#define RESOLUTION_HEIGHT 50 | ||
|
||
#define PERROR fprintf(stderr, "%s:%d: error: %s\n", __FILE__, __LINE__, strerror(errno)) | ||
#define PERROR_GOTO(label) \ | ||
do { \ | ||
PERROR; \ | ||
goto label; \ | ||
} while (0) | ||
|
||
|
||
// -- vector utilities -- | ||
|
||
#define IND(y, x) ((y) * (N) + (x)) | ||
|
||
void printTemperature(double *m, int N, int M); | ||
|
||
// -- simulation code --- | ||
|
||
int main(int argc, char **argv) { | ||
// 'parsing' optional input parameter = problem size | ||
int N = 200; | ||
if (argc > 1) { | ||
N = atoi(argv[1]); | ||
} | ||
int T = N * 10; | ||
printf("Computing heat-distribution for room size %dX%d for T=%d timesteps\n", N, N, T); | ||
|
||
// ---------- setup ---------- | ||
|
||
// create a buffer for storing temperature fields | ||
double *A = malloc(sizeof(double) * N * N); | ||
|
||
if(!A) PERROR_GOTO(error_a); | ||
|
||
// set up initial conditions in A | ||
for (int i = 0; i < N; i++) { | ||
for (int j = 0; j < N; j++) { | ||
A[IND(i,j)] = 273; // temperature is 0° C everywhere (273 K) | ||
} | ||
} | ||
|
||
// and there is a heat source | ||
int source_x = N / 4; | ||
int source_y = N / 4; | ||
A[IND(source_x,source_y)] = 273 + 60; | ||
|
||
printf("Initial:"); | ||
printTemperature(A, N, N); | ||
printf("\n"); | ||
|
||
// ---------- compute ---------- | ||
|
||
// create a second buffer for the computation | ||
double *B = malloc(sizeof(double) * N * N); | ||
if(!B) PERROR_GOTO(error_b); | ||
// for each time step .. | ||
for (int t = 0; t < T; t++) { | ||
// todo implement heat propagation | ||
// todo make sure the heat source stays the same | ||
|
||
// every 1000 steps show intermediate step | ||
if (!(t % 1000)) { | ||
printf("Step t=%d\n", t); | ||
printTemperature(A, N, N); | ||
printf("\n"); | ||
} | ||
} | ||
|
||
|
||
// ---------- check ---------- | ||
|
||
printf("Final:"); | ||
printTemperature(A, N, N); | ||
printf("\n"); | ||
|
||
// simple verification if nowhere the heat is more then the heat source | ||
int success = 1; | ||
for (long long i = 0; i < N; i++) { | ||
for (long long j = 0; j < N; j++) { | ||
double temp = A[IND(i,j)]; | ||
if (273 <= temp && temp <= 273 + 60) | ||
continue; | ||
success = 0; | ||
break; | ||
} | ||
} | ||
|
||
printf("Verification: %s\n", (success) ? "OK" : "FAILED"); | ||
|
||
// todo ---------- cleanup ---------- | ||
error_b: | ||
free(B); | ||
error_a: | ||
free(A); | ||
return (success) ? EXIT_SUCCESS : EXIT_FAILURE; | ||
} | ||
|
||
void printTemperature(double *m, int N, int M) { | ||
const char *colors = " .-:=+*^X#%@"; | ||
const int numColors = 12; | ||
|
||
// boundaries for temperature (for simplicity hard-coded) | ||
const double max = 273 + 30; | ||
const double min = 273 + 0; | ||
|
||
// set the 'render' resolution | ||
int W = RESOLUTION_WIDTH; | ||
int H = RESOLUTION_HEIGHT; | ||
|
||
// step size in each dimension | ||
int sW = N / W; | ||
int sH = M / H; | ||
|
||
// upper wall | ||
printf("\t"); | ||
for (int u = 0; u < W + 2; u++) { | ||
printf("X"); | ||
} | ||
printf("\n"); | ||
// room | ||
for (int i = 0; i < H; i++) { | ||
// left wall | ||
printf("\tX"); | ||
// actual room | ||
for (int j = 0; j < W; j++) { | ||
// get max temperature in this tile | ||
double max_t = 0; | ||
for (int x = sH * i; x < sH * i + sH; x++) { | ||
for (int y = sW * j; y < sW * j + sW; y++) { | ||
max_t = (max_t < m[IND(x,y)]) ? m[IND(x,y)] : max_t; | ||
} | ||
} | ||
double temp = max_t; | ||
|
||
// pick the 'color' | ||
int c = ((temp - min) / (max - min)) * numColors; | ||
c = (c >= numColors) ? numColors - 1 : ((c < 0) ? 0 : c); | ||
|
||
// print the average temperature | ||
printf("%c", colors[c]); | ||
} | ||
// right wall | ||
printf("X\n"); | ||
} | ||
// lower wall | ||
printf("\t"); | ||
for (int l = 0; l < W + 2; l++) { | ||
printf("X"); | ||
} | ||
printf("\n"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters