Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update ex1 and ex2, fix #12 #13

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
48 changes: 38 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ pdirun mpirun -n 4 ./ex?
Where `?` is the number of the exercise and 4 represents the number of MPI
processes to use.

#### Execution with storage of the log

To store the logs for later comparison, you can use the following command (for
example for ex2.):
```bash
Expand Down Expand Up @@ -109,25 +111,48 @@ read this file.
* Set values in `ex1.yml` to be able to run the code with 4 MPI processes.

```bash
srun -n 4 ./ex1
mpirun -np 4 ./ex1
```


## PDI core & trace plugin

### Ex2. Now with some PDI

Ex2. is the same code as that of ex1. with %PDI calls added in `main` function.
In our YAML file (`ex2.yml`), a new sub-tree has been added under the `pdi` key.
This sub-tree is the %PDI specification tree passed to %PDI at initialization.
Here, the %PDI \ref trace_plugin "Trace plugin" is used to trace %PDI calls.
Ex2. C code is similar to ex1. C code with %PDI calls added in `main` function.
This exercise will be run sequentially.

* Examine the source code, compile it and run it.

* Add the required `::PDI_share` and `::PDI_reclaim` calls to match the output
of `ex2.log` file (only the lines matching `[Trace-plugin]` have been kept).
You only need to change the `ex2.c` file. You can easily check if the files
are the same by running the command:
In our YAML file (`ex2.yml`), the `pdi` key is added. The sub-tree, defined
after this key, is the %PDI specification tree passed to %PDI at initialization.

* To observe %PDI calls on the standard output, add \ref trace_plugin
"Trace plugin" (`trace`) plugin of %PDI in our YAML file (`ex2.yml`).

* In the C file (`ex2.c`), add `::PDI_share` and `::PDI_reclaim` call to share
some data with %PDI.
The shared data are defined in the line that starts with "//***" in `ex2.c`.

Here, the objective is to match the output of `ex2.log` file.
In this file, only the line corresponding to `[Trace-plugin]` have been kept.
Moreover, the time are given for each %PDI calls.
To compare, we need to remove this information from the log.
It is done by adding this line in the sub-tree of the trace plugin.

```yaml
logging: { pattern: '[PDI][%n-plugin] *** %l: %v' }
```
Additionally, we run sequentially to facilitate the comparison between logs
(in parallel each rank send a `trace` message and the order of writing can be
different).

* Add the previous line in the sub-tree of \ref trace_plugin "Trace plugin"
(don't forget to indent this line correctly).
Using the previous section [Execution with storage of the log](#execution-with-storage-of-the-log),
run this exercise and save the output log in the file `ex2.result.log`.
After that you can easily check if the files are the same by running the command:

```bash
diff ex2.log <(grep Trace-plugin ex2.result.log)
```
Expand All @@ -136,8 +161,11 @@ Here, the %PDI \ref trace_plugin "Trace plugin" is used to trace %PDI calls.
Notice that some share/reclaim pairs come one after the other while others are
interlaced.
Is one better than the other?
If you do not know the answer to this question, just wait until Ex5. :)
If you do not know the answer to this question, just wait until ex5. :)

\attention
In this exercise, the shared variable and the reclaimed variable are not defined
in the YAML file (see ex3. and further for this).

## Decl'HDF5 plugin

Expand Down
50 changes: 33 additions & 17 deletions ex1.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <time.h>

#include <paraconf.h>
#include <pdi.h>

/// size of the local data as [HEIGHT, WIDTH] including ghosts & boundary constants
int dsize[2];
Expand All @@ -42,13 +43,32 @@ int pcoord[2];
/// the alpha coefficient used in the computation
double alpha;

double L=1.0;
double source1[4]={0.4, 0.4, 0.2, 100};
Yushan-Wang marked this conversation as resolved.
Show resolved Hide resolved
double source2[4]={0.7, 0.8, 0.1, 200};

/** Initialize the data all to 0 except for the left border (XX==0) initialized to 1 million
* \param[out] dat the local data to initialize
*/
void init(double dat[dsize[0]][dsize[1]])
{
for (int yy=0; yy<dsize[0]; ++yy) for (int xx=0; xx<dsize[1]; ++xx) dat[yy][xx] = 0;
if ( pcoord[1] == 0 ) for (int yy=0; yy<dsize[0]; ++yy) dat[yy][0] = 1000000;
double dy = L / ((dsize[0]-2) *psize[0]) ;
double dx = L / ((dsize[1]-2) *psize[1]) ;

double cpos_x,cpos_y;
for(int yy=0; yy<dsize[0];++yy) {
cpos_y=(yy+pcoord[0]*(dsize[0]-2))*dy-0.5*dy;
for(int xx=0; xx<dsize[1];++xx) {
cpos_x=(xx+pcoord[1]*(dsize[1]-2))*dx-0.5*dx;
if((cpos_y-source1[0])*(cpos_y-source1[0]) + (cpos_x-source1[1])*(cpos_x-source1[1]) <= source1[2]*source1[2]) {
dat[yy][xx] = source1[3];
}
if((cpos_y-source2[0])*(cpos_y-source2[0]) + (cpos_x-source2[1])*(cpos_x-source2[1]) <= source2[2]*source2[2]) {
dat[yy][xx] = source2[3];
}
}
}
}

/** Compute the values at the next time-step based on the values at the current time-step
Expand All @@ -58,21 +78,15 @@ void init(double dat[dsize[0]][dsize[1]])
void iter(double cur[dsize[0]][dsize[1]], double next[dsize[0]][dsize[1]])
{
int xx, yy;
for (xx=0; xx<dsize[1]; ++xx) next[0][xx] = cur[0][xx];
for (yy=1; yy<dsize[0]-1; ++yy) {
next[yy][0] = cur[yy][0];
for (xx=1; xx<dsize[1]-1; ++xx) {
next[yy][xx] =
(1.-4.*alpha) * cur[yy][xx]
+ alpha * ( cur[yy][xx-1]
+ cur[yy][xx+1]
+ cur[yy-1][xx]
+ cur[yy+1][xx]
);
next[yy][xx] = (1.-4.*alpha) * cur[yy][xx]
+alpha * ( cur[yy][xx-1]
+ cur[yy][xx+1]
+ cur[yy-1][xx]
+ cur[yy+1][xx]);
}
next[yy][dsize[1]-1] = cur[yy][dsize[1]-1];
}
for (xx=0; xx<dsize[1]; ++xx) next[dsize[0]-1][xx] = cur[dsize[0]-1][xx];
}

/** Exchanges ghost values with neighbours
Expand Down Expand Up @@ -102,8 +116,8 @@ void exchange(MPI_Comm cart_comm, double cur[dsize[0]][dsize[1]])

// send up
MPI_Cart_shift(cart_comm, 0, -1, &rank_source, &rank_dest);
MPI_Sendrecv(&cur[1][1], 1, row, rank_dest, 100, // send column after ghost
&cur[dsize[0]-1][1], 1, row, rank_source, 100, // receive last column (ghost)
MPI_Sendrecv(&cur[1][1], 1, row, rank_dest, 100, // send row after ghost
&cur[dsize[0]-1][1], 1, row, rank_source, 100, // receive last row (ghost)
cart_comm, &status);

// send to the right
Expand All @@ -114,7 +128,7 @@ void exchange(MPI_Comm cart_comm, double cur[dsize[0]][dsize[1]])

// send to the left
MPI_Cart_shift(cart_comm, 1, -1, &rank_source, &rank_dest);
MPI_Sendrecv(&cur[1][1], 1, column, rank_dest, 100, // send column after ghost
MPI_Sendrecv(&cur[1][1], 1, column, rank_dest, 100, // send column after ghost
&cur[1][dsize[1]-1], 1, column, rank_source, 100, // receive last column (ghost)
cart_comm, &status);
}
Expand All @@ -138,8 +152,9 @@ int main( int argc, char* argv[] )
// load the alpha parameter
PC_double(PC_get(conf, ".alpha"), &alpha);

int global_size[2]={12,12};
// load the global data-size
int global_size[2];
// you can use paraconf to read some parameters from the yml config file
PC_int(PC_get(conf, ".global_size.height"), &longval); global_size[0] = longval;
PC_int(PC_get(conf, ".global_size.width"), &longval); global_size[1] = longval;

Expand All @@ -157,7 +172,7 @@ int main( int argc, char* argv[] )
dsize[1] = global_size[1]/psize[1] + 2;

// create a 2D Cartesian MPI communicator & get our coordinate (rank) in it
int cart_period[2] = { 0, 0 };
int cart_period[2] = { 1, 1 };
MPI_Comm cart_comm; MPI_Cart_create(main_comm, 2, psize, cart_period, 1, &cart_comm);
Yushan-Wang marked this conversation as resolved.
Show resolved Hide resolved
MPI_Cart_coords(cart_comm, pcoord_1d, 2, pcoord);

Expand All @@ -173,6 +188,7 @@ int main( int argc, char* argv[] )

// the main loop
for (; ii<10; ++ii) {

// compute the values for the next iteration
iter(cur, next);

Expand Down
2 changes: 1 addition & 1 deletion ex1.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ alpha: 0.125
# global data-size (excluding spacer for boundary conditions or ghosts)
global_size: { height: 60, width: 12 }
# degree of parallelism (number of blocks in each dimension)
parallelism: { height: 1, width: 1 }
parallelism: { height: 1, width: 1 }
67 changes: 39 additions & 28 deletions ex2.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,32 @@ int pcoord[2];
/// the alpha coefficient used in the computation
double alpha;

double L=1.0;
double source1[4]={0.4, 0.4, 0.2, 100};
double source2[4]={0.7, 0.8, 0.1, 200};

/** Initialize the data all to 0 except for the left border (XX==0) initialized to 1 million
* \param[out] dat the local data to initialize
*/
void init(double dat[dsize[0]][dsize[1]])
{
for (int yy=0; yy<dsize[0]; ++yy) for (int xx=0; xx<dsize[1]; ++xx) dat[yy][xx] = 0;
if ( pcoord[1] == 0 ) for (int yy=0; yy<dsize[0]; ++yy) dat[yy][0] = 1000000;
double dy = L / ((dsize[0]-2) *psize[0]) ;
double dx = L / ((dsize[1]-2) *psize[1]) ;

double cpos_x,cpos_y;
for(int yy=0; yy<dsize[0];++yy) {
cpos_y=(yy+pcoord[0]*(dsize[0]-2))*dy-0.5*dy;
for(int xx=0; xx<dsize[1];++xx) {
cpos_x=(xx+pcoord[1]*(dsize[1]-2))*dx-0.5*dx;
if((cpos_y-source1[0])*(cpos_y-source1[0]) + (cpos_x-source1[1])*(cpos_x-source1[1]) <= source1[2]*source1[2]) {
dat[yy][xx] = source1[3];
}
if((cpos_y-source2[0])*(cpos_y-source2[0]) + (cpos_x-source2[1])*(cpos_x-source2[1]) <= source2[2]*source2[2]) {
dat[yy][xx] = source2[3];
}
}
}
}

/** Compute the values at the next time-step based on the values at the current time-step
Expand All @@ -60,21 +79,15 @@ void init(double dat[dsize[0]][dsize[1]])
void iter(double cur[dsize[0]][dsize[1]], double next[dsize[0]][dsize[1]])
{
int xx, yy;
for (xx=0; xx<dsize[1]; ++xx) next[0][xx] = cur[0][xx];
for (yy=1; yy<dsize[0]-1; ++yy) {
next[yy][0] = cur[yy][0];
for (xx=1; xx<dsize[1]-1; ++xx) {
next[yy][xx] =
(1.-4.*alpha) * cur[yy][xx]
+ alpha * ( cur[yy][xx-1]
+ cur[yy][xx+1]
+ cur[yy-1][xx]
+ cur[yy+1][xx]
);
next[yy][xx] = (1.-4.*alpha) * cur[yy][xx]
+alpha * ( cur[yy][xx-1]
+ cur[yy][xx+1]
+ cur[yy-1][xx]
+ cur[yy+1][xx]);
}
next[yy][dsize[1]-1] = cur[yy][dsize[1]-1];
}
for (xx=0; xx<dsize[1]; ++xx) next[dsize[0]-1][xx] = cur[dsize[0]-1][xx];
}

/** Exchanges ghost values with neighbours
Expand Down Expand Up @@ -104,8 +117,8 @@ void exchange(MPI_Comm cart_comm, double cur[dsize[0]][dsize[1]])

// send up
MPI_Cart_shift(cart_comm, 0, -1, &rank_source, &rank_dest);
MPI_Sendrecv(&cur[1][1], 1, row, rank_dest, 100, // send column after ghost
&cur[dsize[0]-1][1], 1, row, rank_source, 100, // receive last column (ghost)
MPI_Sendrecv(&cur[1][1], 1, row, rank_dest, 100, // send row after ghost
&cur[dsize[0]-1][1], 1, row, rank_source, 100, // receive last row (ghost)
cart_comm, &status);

// send to the right
Expand All @@ -116,7 +129,7 @@ void exchange(MPI_Comm cart_comm, double cur[dsize[0]][dsize[1]])

// send to the left
MPI_Cart_shift(cart_comm, 1, -1, &rank_source, &rank_dest);
MPI_Sendrecv(&cur[1][1], 1, column, rank_dest, 100, // send column after ghost
MPI_Sendrecv(&cur[1][1], 1, column, rank_dest, 100, // send column after ghost
&cur[1][dsize[1]-1], 1, column, rank_source, 100, // receive last column (ghost)
cart_comm, &status);
}
Expand Down Expand Up @@ -162,7 +175,7 @@ int main( int argc, char* argv[] )
dsize[1] = global_size[1]/psize[1] + 2;

// create a 2D Cartesian MPI communicator & get our coordinate (rank) in it
int cart_period[2] = { 0, 0 };
int cart_period[2] = { 1, 1 };
MPI_Comm cart_comm; MPI_Cart_create(main_comm, 2, psize, cart_period, 1, &cart_comm);
MPI_Cart_coords(cart_comm, pcoord_1d, 2, pcoord);

Expand All @@ -176,16 +189,15 @@ int main( int argc, char* argv[] )
// our loop counter so as to be able to use it outside the loop
int ii=0;

// share useful configuration bits with PDI
PDI_share("ii", &ii, PDI_OUT);
PDI_reclaim("ii");
//*** share useful configuration bits with PDI
//*** pcoord, psize, dsize
//...

// the main loop
for (; ii<10; ++ii) {
// share the loop counter at each iteration
PDI_share("ii", &ii, PDI_OUT);
PDI_reclaim("ii");

for (; ii<4; ++ii) {
//*** share the loop counter & main field at each iteration
//...

// compute the values for the next iteration
iter(cur, next);

Expand All @@ -195,9 +207,8 @@ int main( int argc, char* argv[] )
// swap the current and next values
double (*tmp)[dsize[1]] = cur; cur = next; next = tmp;
}
// finally share the main field after the main loop body
PDI_share("main_field", cur, PDI_OUT);
PDI_reclaim("main_field");
//*** finally share the loop counter and main field after the main loop body
//...

// finalize PDI
PDI_finalize();
Expand Down
10 changes: 5 additions & 5 deletions ex2.log
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
[PDI][Trace-plugin] *** info: Welcome!
[PDI][Trace-plugin] *** info: =>> data becoming available in the store: ii
[PDI][Trace-plugin] *** info: <<= data stop being available in the store: ii
[PDI][Trace-plugin] *** info: =>> data becoming available in the store: pcoord
[PDI][Trace-plugin] *** info: <<= data stop being available in the store: pcoord
[PDI][Trace-plugin] *** info: =>> data becoming available in the store: dsize
[PDI][Trace-plugin] *** info: <<= data stop being available in the store: dsize
[PDI][Trace-plugin] *** info: =>> data becoming available in the store: psize
[PDI][Trace-plugin] *** info: <<= data stop being available in the store: psize
[PDI][Trace-plugin] *** info: =>> data becoming available in the store: dsize
[PDI][Trace-plugin] *** info: <<= data stop being available in the store: dsize
[PDI][Trace-plugin] *** info: =>> data becoming available in the store: ii
[PDI][Trace-plugin] *** info: =>> data becoming available in the store: main_field
[PDI][Trace-plugin] *** info: <<= data stop being available in the store: main_field
[PDI][Trace-plugin] *** info: <<= data stop being available in the store: ii
[PDI][Trace-plugin] *** info: =>> data becoming available in the store: ii
[PDI][Trace-plugin] *** info: =>> data becoming available in the store: main_field
[PDI][Trace-plugin] *** info: <<= data stop being available in the store: main_field
Expand All @@ -21,8 +21,8 @@
[PDI][Trace-plugin] *** info: =>> data becoming available in the store: main_field
[PDI][Trace-plugin] *** info: <<= data stop being available in the store: main_field
[PDI][Trace-plugin] *** info: <<= data stop being available in the store: ii
[PDI][Trace-plugin] *** info: =>> data becoming available in the store: main_field
[PDI][Trace-plugin] *** info: =>> data becoming available in the store: ii
[PDI][Trace-plugin] *** info: <<= data stop being available in the store: ii
[PDI][Trace-plugin] *** info: =>> data becoming available in the store: main_field
[PDI][Trace-plugin] *** info: <<= data stop being available in the store: main_field
[PDI][Trace-plugin] *** info: Goodbye!
7 changes: 3 additions & 4 deletions ex2.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ alpha: 0.125
global_size: { height: 60, width: 12 }
# degree of parallelism (number of blocks in each dimension)
parallelism: { height: 1, width: 1 }
# PDI configuration

pdi:
plugins:
trace:
logging: { pattern: '[PDI][%n-plugin] *** %l: %v' }
#*** PDI configuration: use the trace plugin to print all the PDI activities
Yushan-Wang marked this conversation as resolved.
Show resolved Hide resolved
jmorice91 marked this conversation as resolved.
Show resolved Hide resolved
#...
2 changes: 1 addition & 1 deletion solutions/ex1.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ alpha: 0.125
# global data-size (excluding spacer for boundary conditions or ghosts)
global_size: { height: 60, width: 12 }
# degree of parallelism (number of blocks in each dimension)
parallelism: { height: 2, width: 2 }
parallelism: { height: 2, width: 2 }
Loading