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

fix #25, update ex6 #29

Merged
merged 7 commits into from
Jan 31, 2025
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,18 +253,19 @@ You have to use events for that, you will modify both the C and YAML file.
```bash
diff ex5.h5dump <(h5dump ex5*.h5)
```


### Ex6. Simplifying the code

As you can notice, the %PDI code is quite redundant.
In this exercise, you will use `::PDI_expose` and `::PDI_multi_expose` to
simplify the code while keeping the exact same behaviour.
For once, there is no need to modify the YAML file here, you only need to modify
the C file in this exercise.
the C file. Moreover, this exercise will be launched sequentially to facilitate
the comparison between logs.

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

\remark At the end of the iteration loop, a new event `finalization` is added.

There are lots of matched `::PDI_share`/`::PDI_reclaim` in the code.

* Replace these by `::PDI_expose` that is the exact equivalent of a
Expand All @@ -277,12 +278,21 @@ then triggers an event and finally does all the reclaim in reverse order.

* Replace the remaining `::PDI_share`/`::PDI_reclaim` by `::PDI_expose`s and
`::PDI_multi_expose`s and ensure that your code keeps the exact same behaviour
by comparing its trace to `ex6.log` (only the lines matching `[Trace-plugin]`
have been kept). You can easily check if the files are the same by running:
as in previous exercise by comparing its trace to `ex6.log` (only the lines matching
`[Trace-plugin]` have been kept). Using the previous section
[Execution with storage of the log](#execution-with-storage-of-the-log),
run this exercise in saving the output log in the `ex6.result.log`.
After that you can easily check if the files are the same by running:
```bash
diff ex6.log <(grep Trace-plugin ex6.result.log)
```

In summary:

1. `::PDI_expose` is equivalent to `::PDI_share` + `::PDI_reclaim`.

2. `::PDI_multi_expose` is equivalent to `::PDI_share` + `::PDI_event` + `::PDI_reclaim`.


### Ex7. Writing a selection

Expand Down
89 changes: 59 additions & 30 deletions ex6.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,25 +32,57 @@
// load the PDI header
#include <pdi.h>

/// size of the local data as [HEIGHT, WIDTH] including ghosts & boundary constants
// size of the local data as [HEIGHT, WIDTH] including the number of ghost layers
// for communications or boundary conditions
int dsize[2];

/// 2D size of the process grid as [HEIGHT, WIDTH]
// 2D size of the process grid as [HEIGHT, WIDTH]
int psize[2];

/// 2D rank of the local process in the process grid as [YY, XX]
// 2D rank of the local process in the process grid as [YY, XX]
int pcoord[2];

/// the alpha coefficient used in the computation
// the alpha coefficient used in the computation
double alpha;

/** Initialize the data all to 0 except for the left border (XX==0) initialized to 1 million
double L=1.0;
// definition of the source
// the source corresponds to a disk of an uniform value
// source1: center=(0.4,0.4), radius=0.2 and value=100
double source1[4]={0.4, 0.4, 0.2, 100};
// source2: center=(0.8,0.7), radius=0.1 and value=200
double source2[4]={0.7, 0.8, 0.1, 200};
// the order of the coordinates of the center (XX,YY) is inverted in the vector

/** Initialize all the data to 0, with the exception of a given cell
* whose center (cpos_x,cpos_y) is inside of the disks
* defined by source1 or source2
* \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;
double square_dist1, square_dist2;
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;
square_dist1 = ( cpos_y-source1[0] ) * ( cpos_y-source1[0] )
+ ( cpos_x-source1[1] ) * ( cpos_x-source1[1] );
if (square_dist1 <= source1[2] * source1[2]) {
dat[yy][xx] = source1[3];
}
square_dist2 = ( cpos_y-source2[0] ) * ( cpos_y-source2[0] )
+ ( cpos_x-source2[1] ) * ( cpos_x-source2[1] );
if (square_dist2 <= 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,24 +92,18 @@ 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
/** Exchange ghost values with neighbours
* \param[in] cart_comm the MPI communicator with all processes organized in a 2D Cartesian grid
* \param[in] cur the local data at the current time-step whose ghosts need exchanging
*/
Expand All @@ -104,8 +130,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 +142,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 @@ -157,12 +183,12 @@ int main( int argc, char* argv[] )
assert(global_size[1]%psize[1]==0);
assert(psize[1]*psize[0] == psize_1d);

// compute the local data-size with space for ghosts and boundary constants
// compute the local data-size (the number of ghost layers is 2 for each coordinate)
dsize[0] = global_size[0]/psize[0] + 2;
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 @@ -178,20 +204,20 @@ int main( int argc, char* argv[] )
int ii=0;

// share useful configuration bits with PDI
PDI_share("ii", &ii, PDI_OUT);
PDI_reclaim("ii");
//*** use PDI_expose to replace PDI_share + reclaim
//...
PDI_share("pcoord", pcoord, PDI_OUT);
PDI_reclaim("pcoord");
PDI_share("dsize", dsize, PDI_OUT);
PDI_reclaim("dsize");
PDI_share("psize", psize, PDI_OUT);
PDI_reclaim("psize");
PDI_share("main_field", cur, PDI_OUT);
PDI_reclaim("main_field");

// the main loop
for (; ii<10; ++ii) {
for (; ii<4; ++ii) {
// share the loop counter & main field at each iteration
//*** use PDI_multi_expose to replace PDI_share + event + reclaim
//...
PDI_share("ii", &ii, PDI_OUT);
PDI_share("main_field", cur, PDI_OUT);
PDI_event("loop");
Expand All @@ -208,11 +234,13 @@ int main( int argc, char* argv[] )
double (*tmp)[dsize[1]] = cur; cur = next; next = tmp;
}
// finally share the main field as well as the loop counter after the loop
PDI_share("main_field", cur, PDI_OUT);
//*** use PDI_multi_expose to replace PDI_share + event + reclaim
//...
PDI_share("ii", &ii, PDI_OUT);
PDI_share("main_field", cur, PDI_OUT);
PDI_event("finalization");
PDI_reclaim("ii");
PDI_reclaim("main_field");
PDI_reclaim("ii");

// finalize PDI
PDI_finalize();
Expand All @@ -230,3 +258,4 @@ int main( int argc, char* argv[] )
fprintf(stderr, "[%d] SUCCESS\n", pcoord_1d);
return EXIT_SUCCESS;
}

5 changes: 3 additions & 2 deletions ex6.log
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
[PDI][Trace-plugin] *** info: Welcome!
[PDI][Trace-plugin] *** info: !!! named event: initialization
[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: ii
[PDI][Trace-plugin] *** info: =>> data becoming available in the store: main_field
[PDI][Trace-plugin] *** info: !!! named event: loop
[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: !!! named event: loop
Expand Down
13 changes: 12 additions & 1 deletion ex6.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# the alpha parameter
alpha: 0.125
# global data-size (excluding spacer for boundary conditions or ghosts)
# global data-size (excluding the number of ghost layers for boundary conditions)
global_size: { height: 60, width: 12 }
# degree of parallelism (number of blocks in each dimension)
parallelism: { height: 1, width: 1 }
Expand All @@ -16,3 +16,14 @@ pdi:
plugins:
trace:
logging: { pattern: '[PDI][%n-plugin] *** %l: %v' }
decl_hdf5:
- file: ex6-meta-${pcoord[0]}x${pcoord[1]}.h5
write: [ dsize, psize ]
- file: ex6-data-${pcoord[0]}x${pcoord[1]}.h5
on_event: loop
when: '$ii>0 & $ii<3'
write:
ii:
dataset: 'iter${ii}/ii'
main_field:
dataset: 'iter${ii}/main_field'
52 changes: 33 additions & 19 deletions solutions/ex6.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 @@ -178,15 +191,15 @@ int main( int argc, char* argv[] )
int ii=0;

// share useful configuration bits with PDI
PDI_expose("ii", &ii, PDI_OUT);
//*** use PDI_expose to replace PDI_share + reclaim
PDI_expose("pcoord", pcoord, PDI_OUT);
PDI_expose("dsize", dsize, PDI_OUT);
PDI_expose("psize", psize, PDI_OUT);
PDI_expose("main_field", cur, PDI_OUT);

// the main loop
for (; ii<3; ++ii) {
for (; ii<4; ++ii) {
// share the loop counter & main field at each iteration
//*** use PDI_multi_expose to replace PDI_share + event + reclaim
PDI_multi_expose("loop",
"ii", &ii, PDI_OUT,
"main_field", cur, PDI_OUT,
Expand All @@ -202,6 +215,7 @@ int main( int argc, char* argv[] )
double (*tmp)[dsize[1]] = cur; cur = next; next = tmp;
}
// finally share the main field as well as the loop counter after the loop
//*** use PDI_multi_expose to replace PDI_share + event + reclaim
PDI_multi_expose("finalization",
"main_field", cur, PDI_OUT,
"ii", &ii, PDI_OUT,
Expand Down