diff --git a/README.md b/README.md index fba05c2..062b217 100644 --- a/README.md +++ b/README.md @@ -136,123 +136,180 @@ 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. :) ## Decl'HDF5 plugin +From exercise 3 to exercise 9 included, we present the \ref Decl_HDF5_plugin +"Decl'HDF5 plugin" (`decl_hdf5`). We will introduce some keywords (`when`, +`datasets`, ...) in the sub-tree of `decl_hdf5` in configuration YAML file. + +All keywords are defined in the last section **full configuration example** of +\ref Decl_HDF5_plugin "Decl'HDF5 plugin". + ### Ex3. HDF5 through PDI -In this exercise, the code is the same as in ex2. -No need to touch the C code here, modification of the YAML file (`ex3.yml`) -should be enough. +In this exercise, the C code is the same as in ex2. You only need to modify the +YAML file (`ex3.yml`). * Examine the YAML file, compile the code and run it. -The \ref trace_plugin "Trace plugin" (`trace`) was replaced by the -\ref Decl_HDF5_plugin "Decl'HDF5 plugin" (`decl_hdf5`) in the specification -tree. -In its configuration, the `dsize` variable is written. +The \ref Decl_HDF5_plugin "Decl'HDF5 plugin" (`decl_hdf5`) is added in the +specification tree. +In its configuration, the `dsize` variable is defined as a metadata for %PDI. -* Write the `psize` and `pcoord` variables in addition to `dsize` to match the - content expected as described in the `ex3.h5dump` text file (use the `h5dump` - command to see the content of your HDF5 output file in the same format as the - `.h5dump` file). You can easily check if the files are the same by running the - command: -```bash - diff ex3.h5dump <(h5dump ex3*.h5) -``` +* Write the `psize` and `pcoord` variables in addition to `dsize` in a file `ex3.h5` +with one MPI process. +To achieve this result, you will need to fill 2 sections in the YAML file: -To achieve this result, you will need to fill 2 sections in the YAML file. + 1. The `data` section to indicate to %PDI the \ref datatype_node "type" of the + fields that are exposed. -1. The `data` section to indicate to %PDI the \ref datatype_node type of the - fields that are exposed. + 2. The `decl_hdf5` section for the configuration of the \ref Decl_HDF5_plugin + "Decl'HDF5 plugin". -2. The `decl_hdf5` section for the configuration of the - \ref Decl_HDF5_plugin "Decl'HDF5 plugin". +* Use the `h5dump` command to see the content of your HDF5 output file in the +same format as the h5dump file `ex3.h5dump`. You can easily check if the files +are the same by running: +```bash + diff ex3.h5dump <(h5dump ex3*.h5) +``` +To see your `h5` file in readable file format, you can check the section +[Comparison with the `h5dump` command](#h5comparison). \warning -If you relaunch the executable, remember to delete your old `ex3.h5` file -before, otherwise the data will not be changed. +If you relaunch the executable, remember to delete your old `ex3.h5` file before, +otherwise the data will not be changed. \warning -Since we write to the same location independently of the MPI rank, this exercise -will fail if more than one MPI rank is used. - +When more than one MPI rank is used, we write to the same location in the file +independently of the MPI rank. For this reason, this exercise will fail. The next +exercise solves this issue. ### Ex4. Writing some real data In this exercise each MPI process will write its local 2D array block contained in the `main_field` variable to a separate HDF5 file. -Once again, this can be done by modifying the YAML file only, no nee to touch +Once again, this can be done by modifying the YAML file only, no need to touch the C file. * Examine the YAML file, compile the code and run it. -Look at the number of blocks, you will have to use the correct number of MPI -ranks to run the example. - -Notice that in the YAML file, a list was used in the `decl_hdf5` section with -multiple write blocks instead of a single one as before in order to write to -multiple files. +\note Notice that in the YAML file `ex4.yml`, a list was used in the `decl_hdf5` +section with multiple write blocks instead of a single one as before in order +to write to multiple files. + +\note Notice that we have moved fields (`dsize`, `psize` and `pcoord`) in the +`metadata` section. +```yaml +pdi: + metadata: # small values for which PDI keeps a copy + #*** add ii as metadata + #... + dsize: { type: array, subtype: int, size: 2 } +``` +You can reference them from dynamic "$-expressions" in the configuration file. -Also notice that this example now runs in parallel with two processes. -Therefore it uses "$-expressions" to specify the file names and ensure we -do not write to the same file from distinct ranks. +\remark Also notice that this example now runs in parallel with 4 processes. +To ensure we do not write to the same file, we need to specify the file name +using "$-expressions" for the different process rank. Unlike the other fields manipulated until now, the type of `main_field` is not -fully known, its size is dynamic. -By moving other fields in the `metadata` section, you can reference them from -"$-expressions" in the configuration file. +fully known, its size is dynamic. Therefore, we need to define the size in YAML +file for %PDI using "$-expressions". -* Use a $-expression to specify the size of `main_field`. +* Describe the temperature data on the current iteration by using a $-expression +to specify the size of `main_field` in `data` section. -Unlike the other fields manipulated until now, `main_field` is exposed multiple +Unlike the other fields manipulated until now, `main_field` is exposed multiple times along execution. -In order not to overwrite it every time it is exposed, you need to add a `when` -condition to restrict its output. +In order not to overwrite it every time it is exposed, you propose to write one +file per rank only at the first iteration (`ii=1`) with the directive `when`. + +* Add the iteration loop `ii` as a metadata. +* Write the curent temperature field in one file per process at first iteration. -* Only write `main_field` at the second iteration (when `ii=1`) and match the - expected content as described in `ex4.h5dump`. +You should be able to match the expected output described in `ex4.h5dump`. +You can easily check if the files are the same by running: ```bash - diff ex4.h5dump <(h5dump ex4*.h5) + diff ex4.h5dump <(h5dump ex4-data-*.h5) ``` +To see your `h5` file in readable file format, you can check the section +[Comparison with the `h5dump` command](#h5comparison). -### Ex5. Introducing events +\note A definition of `metadata` and `data` can be: -In ex4., two variables were written to `ex4-data*.h5`, but the file was opened +- `metadata`: small values for which PDI keeps a copy. These value can be referenced +by using "$-expressions" in the configuration YAML file. + +- `data` : values for which PDI does not keep a copy. + +### Ex5. Introducing events and group of dataset + +This exercise is done sequentially to facilitate the comparison between logs. + +#### Ex 5.1 PDI event and on_event + +In ex4, two variables were written to `ex4-data-*.h5`, but the files were opened and closed for each and every write. + Since Decl'HDF5 only sees the data appear one after the other, it does not keep -the file open. -Since `ii` and `main_field` are shared in an interlaced way, they are both -available to %PDI at the same time and could be written without opening the file -twice. -You have to use events for that, you will modify both the C and YAML file. +the file open. Since `ii` and `main_field` are shared in an interlaced way, they +are both available to %PDI at the same time and could be written without opening +the file twice. +You have to use events for that, you will modify both the C and YAML file in this +exercise. * Examine the YAML file and source code. - -* In the C file, trigger a %PDI event named `loop` when both `ii` and +* In the C file, add a %PDI event named `loop` when both `ii` and `main_field` are shared. - With the \ref trace_plugin "Trace plugin", check that the event is indeed - triggered at the expected time as described in `ex5.log` (only the lines - matching `[Trace-plugin]` have been kept). You can check if the files are the - same by running: + + With the \ref trace_plugin "Trace plugin", check that the event is indeed + triggered at the expected time as described in `ex5.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 `ex5.result.log`. + After that you can easily check if the files are the same by running: ```bash diff ex5.log <(grep Trace-plugin ex5.result.log) ``` +* In the YAML file, use the `on_event` mechanism to trigger the write of `ii` and + `main_field` for event `loop` only. This mechanism can be combined with a `when` + directive, in that case the write is only executed when both mechanisms agree. +* Add the `when` directive to write only at iteration 1 and 2. Use the symbol `&` + which corresponds to the logical operation `and`. + +#### Ex 5.2 group of dataset +In ex4, the name of the datasets of `.h5` file are `ii` and `main_field`(see ex4.h5dump). +Using the keyword `dataset`, it is possible to have a different name from the +%PDI variable name. + +The name of the dataset is given after the definition of the data +```yaml + write: + ii: # name of the PDI data to write + dataset: 'new_name' +``` +Using this mechanism, it is possible to define a group object of hdf5 see +https://support.hdfgroup.org/documentation/hdf5/latest/_h5_g__u_g.html. +If you want to add a dataset `my_data` in the sub-group `groupA` of the group +`my_group`, the name of the dataset will be: +```yaml +dataset: 'my_group/groupA/my_data'. +``` +where the symbol "/" is used to separate groups in path. -* Use the `on_event` mechanism to trigger the write of `ii` and `main_field`. - This mechanism can be combined with a `when` directive, in that case the - write is only executed when both mechanisms agree. +* Change the YAML file to write `main_field` and `ii` at iterations 1 and 2, +in two distinct groups `iter1` and `iter2`. -* Also notice the extended syntax that make it possible to write data to a - dataset whose name differs from the %PDI variable name. - Use this mechanism to write `main_field` at iterations 1 and 2, in two - distinct groups `iter1` and `iter2`. - Your output should match the content described in `ex5.h5dump`. + To match the expected output described in `ex5.h5dump`. You can easily check + if the files are the same by running: ```bash - diff ex5.h5dump <(h5dump ex5*.h5) + diff ex5.h5dump <(h5dump ex5-data-*.h5) ``` + To see your `h5` file in readable file format, you can check the section + [Comparison with the `h5dump` command](#h5comparison). ### Ex6. Simplifying the code diff --git a/ex3.c b/ex3.c index a2d3a90..aad7ba6 100644 --- a/ex3.c +++ b/ex3.c @@ -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> 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 +[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 [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 +[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 +[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 +[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 +[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 diff --git a/ex5.yml b/ex5.yml index d9d28b5..ae516aa 100644 --- a/ex5.yml +++ b/ex5.yml @@ -17,13 +17,19 @@ pdi: trace: logging: { pattern: '[PDI][%n-plugin] *** %l: %v' } decl_hdf5: - - file: ex5-meta${pcoord[0]}x${pcoord[1]}.h5 + - file: ex5-meta-${pcoord[0]}x${pcoord[1]}.h5 write: [ dsize, psize ] - - file: ex5-data${pcoord[0]}x${pcoord[1]}.h5 - on_event: "" - when: '$ii>0 & ' # `&' is a local `and' operation + - file: ex5-data-${pcoord[0]}x${pcoord[1]}.h5 + #*** enable the output upon the event + #... + #*** enable the output when ii>0 and ii<3 (`&` is a logical `and` operation ) + #... write: ii: # name of the PDI data to write - dataset: 'iter${}/ii' # dataset name in file, $-expressions can be used here, "/" separate groups in path + #*** give the dataset that you want to write into for ii + # $-expressions can be used to define dataset name in file, , "/" separate groups in path + #... main_field: - dataset: 'iter${}/main_field' + #*** give the dataset that you want to write into for main_field + # $-expressions can be used to define dataset name in file, , "/" separate groups in path + #... diff --git a/solutions/ex3.yml b/solutions/ex3.yml index e80547e..e5d3fe8 100644 --- a/solutions/ex3.yml +++ b/solutions/ex3.yml @@ -6,12 +6,15 @@ global_size: { height: 60, width: 12 } parallelism: { height: 1, width: 1 } # PDI configuration pdi: + #*** describe the data dsize, psize, pcoord data: - ii: int dsize: { type: array, subtype: int, size: 2 } psize: { type: array, subtype: int, size: 2 } pcoord: { type: array, subtype: int, size: 2 } + plugins: + trace: decl_hdf5: + #*** use the decl_hdf5 plugin to write in the file ex3.h5 the data above (dsize, psize, pcoord) file: ex3.h5 write: [ dsize, psize, pcoord ] diff --git a/solutions/ex4.yml b/solutions/ex4.yml index 5536b7a..3d3704b 100644 --- a/solutions/ex4.yml +++ b/solutions/ex4.yml @@ -3,20 +3,24 @@ 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: 1 } +parallelism: { height: 2 , width: 2 } # PDI configuration pdi: metadata: # small values for which PDI keeps a copy + #*** add ii as metadata ii: int dsize: { type: array, subtype: int, size: 2 } psize: { type: array, subtype: int, size: 2 } pcoord: { type: array, subtype: int, size: 2 } data: # values for which PDI does not keep a copy - main_field: { type: array, subtype: double, size: [ '$dsize[0]', '$dsize[1]' ] } # we can use $ expressions in type definitions + #*** add main_field to the data section, use $-expression to define its size + main_field: { type: array, subtype: double, size: [ '$dsize[0]', '$dsize[1]' ] } plugins: decl_hdf5: - - file: ex4-meta${pcoord[0]}x${pcoord[1]}.h5 # we can use $ expressions in file names + #*** write dsize and psize into hdf5, one file per rank + - file: ex4-metadata-${pcoord[0]}x${pcoord[1]}.h5 # we can use $ expressions in file names write: [ dsize, psize ] - - file: ex4-data${pcoord[0]}x${pcoord[1]}.h5 - when: '$ii=1' # we can use $ expressions in conditions - write: [ ii, main_field ] + #*** write main_field and iteration counter into hdf5, one file per rank at first iteration (ii=1) + - file: ex4-data-${pcoord[0]}x${pcoord[1]}_iter_${ii}.h5 + when: '$ii=1' + write: [ii, main_field ] diff --git a/solutions/ex5.c b/solutions/ex5.c index fc95d84..df43264 100644 --- a/solutions/ex5.c +++ b/solutions/ex5.c @@ -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; yy0 & $ii<3' # `&' is a logical `and' operation + #*** enable the output when ii>0 and ii<3 (`&` is a logical `and` operation ) + when: '$ii>0 & $ii<3' write: ii: # name of the PDI data to write - dataset: 'iter${ii}/ii' # dataset name in file, $-expressions can be used here, "/" separate groups in path + #*** give the dataset that you want to write into for ii + # $-expressions can be used to define dataset name in file, , "/" separate groups in path + dataset: 'iter${ii}/ii' main_field: + #*** give the dataset that you want to write into for main_field + # $-expressions can be used to define dataset name in file, , "/" separate groups in path dataset: 'iter${ii}/main_field'