diff --git a/benchmarks/C/aggregation.c b/benchmarks/C/aggregation.c index 965db3649..3f29fd4f4 100644 --- a/benchmarks/C/aggregation.c +++ b/benchmarks/C/aggregation.c @@ -172,10 +172,9 @@ int benchmark_write(char *filename, /* set PnetCDF I/O hints */ MPI_Info_create(&info); - /* disable the header extent alignments - MPI_Info_set(info, "nc_header_align_size", "1"); size in bytes - */ - /* disable the fixed-size variable alignments */ + /* disable the fixed-size variable alignments, which also + * disable the header extent alignments + */ MPI_Info_set(info, "nc_var_align_size", "1"); nvars = 0; diff --git a/benchmarks/C/write_block_read_column.c b/benchmarks/C/write_block_read_column.c index cf98b66b2..29cb05a81 100644 --- a/benchmarks/C/write_block_read_column.c +++ b/benchmarks/C/write_block_read_column.c @@ -84,7 +84,6 @@ int benchmark_write(char *filename, /* set PnetCDF I/O hints */ MPI_Info_create(&info); - MPI_Info_set(info, "nc_header_align_size", "1"); /* size in bytes */ MPI_Info_set(info, "nc_var_align_size", "1"); /* size in bytes */ MPI_Info_set(info, "nc_header_read_chunk_size", "512"); /* size in bytes */ /* note that set the above values to 1 to disable the alignment */ diff --git a/examples/C/get_info.c b/examples/C/get_info.c index 92d88ebf4..897470ef8 100644 --- a/examples/C/get_info.c +++ b/examples/C/get_info.c @@ -15,7 +15,7 @@ * * Example standard output: - MPI File Info: nkeys = 35 + MPI File Info: nkeys = 34 MPI File Info: [ 0] key = cb_buffer_size, value = 16777216 MPI File Info: [ 1] key = romio_cb_read, value = automatic MPI File Info: [ 2] key = romio_cb_write, value = automatic @@ -39,18 +39,17 @@ MPI File Info: [20] key = striping_unit, value = 0 MPI File Info: [21] key = striping_factor, value = 0 MPI File Info: [22] key = start_iodevice, value = 0 - MPI File Info: [23] key = nc_header_align_size, value = 512 - MPI File Info: [24] key = nc_var_align_size, value = 4 - MPI File Info: [25] key = nc_record_align_size, value = 4 - MPI File Info: [26] key = nc_header_read_chunk_size, value = 262144 - MPI File Info: [27] key = nc_in_place_swap, value = auto - MPI File Info: [28] key = nc_ibuf_size, value = 16777216 - MPI File Info: [29] key = pnetcdf_subfiling, value = disable - MPI File Info: [30] key = nc_num_subfiles, value = 0 - MPI File Info: [31] key = nc_hash_size_dim, value = 256 - MPI File Info: [32] key = nc_hash_size_var, value = 256 - MPI File Info: [33] key = nc_hash_size_gattr, value = 64 - MPI File Info: [34] key = nc_hash_size_vattr, value = 8 + MPI File Info: [23] key = nc_var_align_size, value = 4 + MPI File Info: [24] key = nc_record_align_size, value = 4 + MPI File Info: [25] key = nc_header_read_chunk_size, value = 262144 + MPI File Info: [26] key = nc_in_place_swap, value = auto + MPI File Info: [27] key = nc_ibuf_size, value = 16777216 + MPI File Info: [28] key = pnetcdf_subfiling, value = disable + MPI File Info: [29] key = nc_num_subfiles, value = 0 + MPI File Info: [30] key = nc_hash_size_dim, value = 256 + MPI File Info: [31] key = nc_hash_size_var, value = 256 + MPI File Info: [32] key = nc_hash_size_gattr, value = 64 + MPI File Info: [33] key = nc_hash_size_vattr, value = 8 */ #include diff --git a/examples/C/hints.c b/examples/C/hints.c index 18bda1ffb..deb88d5c9 100644 --- a/examples/C/hints.c +++ b/examples/C/hints.c @@ -7,8 +7,8 @@ /* $Id$ */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * This example sets two PnetCDF hints: - * nc_header_align_size and nc_var_align_size + * This example sets PnetCDF hint: + * nc_var_align_size * and prints the hint values as well as the header size, header extent, and * two variables' starting file offsets. * @@ -18,7 +18,6 @@ * * % mpiexec -l -n 4 ./hints /pvfs2/wkliao/testfile.nc * - * nc_header_align_size set to = 1024 * nc_var_align_size set to = 512 * nc_header_read_chunk_size set to = 256 * header size = 252 @@ -94,7 +93,7 @@ int print_hints(int ncid, char value[MPI_MAX_INFO_VAL]; int err, len, flag, nerrs=0; MPI_Offset header_size, header_extent, var_zy_start, var_yx_start; - MPI_Offset h_align=-1, v_align=-1, h_chunk=-1; + MPI_Offset v_align=-1, h_chunk=-1; MPI_Info info_used; err = ncmpi_inq_header_size (ncid, &header_size); ERR @@ -103,12 +102,7 @@ int print_hints(int ncid, err = ncmpi_inq_varoffset(ncid, varid1, &var_yx_start); ERR err = ncmpi_inq_file_info(ncid, &info_used); ERR - MPI_Info_get_valuelen(info_used, "nc_header_align_size", &len, &flag); - if (flag) { - MPI_Info_get(info_used, "nc_header_align_size", len+1, value, &flag); - h_align = strtoll(value,NULL,10); - } - MPI_Info_get_valuelen(info_used, "nc_var_align_size", &len, &flag); + MPI_Info_get_valuelen(info_used, "nc_var_align_size", &len, &flag); if (flag) { MPI_Info_get(info_used, "nc_var_align_size", len+1, value, &flag); v_align = strtoll(value,NULL,10); @@ -120,11 +114,6 @@ int print_hints(int ncid, } MPI_Info_free(&info_used); - if (h_align == -1) - printf("nc_header_align_size is NOT set\n"); - else - printf("nc_header_align_size set to = %lld\n", h_align); - if (v_align == -1) printf("nc_var_align_size is NOT set\n"); else @@ -171,7 +160,6 @@ int main(int argc, char** argv) else snprintf(filename, 256, "%s", argv[optind]); MPI_Info_create(&info); - MPI_Info_set(info, "nc_header_align_size", "1024"); /* size in bytes */ MPI_Info_set(info, "nc_var_align_size", "512"); /* size in bytes */ MPI_Info_set(info, "nc_header_read_chunk_size", "256"); /* size in bytes */ /* note that set the above values to 1 to disable the alignment */ diff --git a/examples/CXX/get_info.cpp b/examples/CXX/get_info.cpp index 5b0fc99ee..d101eac4c 100644 --- a/examples/CXX/get_info.cpp +++ b/examples/CXX/get_info.cpp @@ -15,7 +15,7 @@ * * Example standard output: - MPI File Info: nkeys = 18 + MPI File Info: nkeys = 17 MPI File Info: [ 0] key = cb_buffer_size, value = 16777216 MPI File Info: [ 1] key = romio_cb_read, value = automatic MPI File Info: [ 2] key = romio_cb_write, value = automatic @@ -31,9 +31,8 @@ MPI File Info: [12] key = romio_ds_read, value = automatic MPI File Info: [13] key = romio_ds_write, value = automatic MPI File Info: [14] key = cb_config_list, value = *:1 - MPI File Info: [15] key = nc_header_align_size, value = 512 - MPI File Info: [16] key = nc_var_align_size, value = 512 - MPI File Info: [17] key = nc_header_read_chunk_size, value = 0 + MPI File Info: [15] key = nc_var_align_size, value = 512 + MPI File Info: [16] key = nc_header_read_chunk_size, value = 0 */ #include diff --git a/examples/CXX/hints.cpp b/examples/CXX/hints.cpp index 13ff87438..bd9b0bb30 100644 --- a/examples/CXX/hints.cpp +++ b/examples/CXX/hints.cpp @@ -7,8 +7,8 @@ /* $Id$ */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * This example sets two PnetCDF hints: - * nc_header_align_size and nc_var_align_size + * This example sets PnetCDF hint: + * nc_var_align_size * and prints the hint values as well as the header size, header extent, and * two variables' starting file offsets. * @@ -18,7 +18,6 @@ * * % mpiexec -l -n 4 ./hints /pvfs2/wkliao/testfile.nc * - * nc_header_align_size set to = 1024 * nc_var_align_size set to = 512 * nc_header_read_chunk_size set to = 256 * header size = 252 @@ -64,7 +63,7 @@ void print_hints(NcmpiFile &ncFile, char value[MPI_MAX_INFO_VAL]; int len, flag; MPI_Offset header_size, header_extent, var_zy_start, var_yx_start; - MPI_Offset h_align=-1, v_align=-1, h_chunk=-1; + MPI_Offset v_align=-1, h_chunk=-1; MPI_Info info_used; ncFile.Inq_header_size(&header_size); @@ -76,12 +75,7 @@ void print_hints(NcmpiFile &ncFile, /* get all the hints used */ ncFile.Inq_file_info(&info_used); - MPI_Info_get_valuelen(info_used, (char*)"nc_header_align_size", &len, &flag); - if (flag) { - MPI_Info_get(info_used, (char*)"nc_header_align_size", len+1, value, &flag); - h_align = strtoll(value,NULL,10); - } - MPI_Info_get_valuelen(info_used, (char*)"nc_var_align_size", &len, &flag); + MPI_Info_get_valuelen(info_used, (char*)"nc_var_align_size", &len, &flag); if (flag) { MPI_Info_get(info_used, (char*)"nc_var_align_size", len+1, value, &flag); v_align = strtoll(value,NULL,10); @@ -93,11 +87,6 @@ void print_hints(NcmpiFile &ncFile, } MPI_Info_free(&info_used); - if (h_align == -1) - printf("nc_header_align_size is NOT set\n"); - else - printf("nc_header_align_size set to = %lld\n", h_align); - if (v_align == -1) printf("nc_var_align_size is NOT set\n"); else @@ -141,7 +130,6 @@ int main(int argc, char** argv) try { MPI_Info_create(&info); - MPI_Info_set(info, (char*)"nc_header_align_size", (char*)"1024"); MPI_Info_set(info, (char*)"nc_var_align_size", (char*)"512"); MPI_Info_set(info, (char*)"nc_header_read_chunk_size", (char*)"256"); /* note that set the above values to 1 to disable the alignment */ diff --git a/examples/F77/get_info.f b/examples/F77/get_info.f index 784f2a139..0e03dd6b7 100644 --- a/examples/F77/get_info.f +++ b/examples/F77/get_info.f @@ -15,7 +15,7 @@ ! ! Example standard output: ! -! MPI File Info: nkeys = 18 +! MPI File Info: nkeys = 17 ! MPI File Info: [ 0] key = cb_buffer_size, value =16777216 ! MPI File Info: [ 1] key = romio_cb_read, value =automatic ! MPI File Info: [ 2] key = romio_cb_write, value =automatic @@ -31,9 +31,8 @@ ! MPI File Info: [12] key = romio_ds_read, value =automatic ! MPI File Info: [13] key = romio_ds_write, value =automatic ! MPI File Info: [14] key = cb_config_list, value =*:1 -! MPI File Info: [15] key = nc_header_align_size, value =0 -! MPI File Info: [16] key = nc_var_align_size, value =0 -! MPI File Info: [17] key = nc_header_read_chunk_size, value =0 +! MPI File Info: [15] key = nc_var_align_size, value =0 +! MPI File Info: [16] key = nc_header_read_chunk_size, value =0 program main diff --git a/examples/F77/hints.f b/examples/F77/hints.f index 1ab12ab94..7b4a77cff 100644 --- a/examples/F77/hints.f +++ b/examples/F77/hints.f @@ -6,8 +6,8 @@ ! $Id$ ! -! This example sets two PnetCDF hints: -! nc_header_align_size and nc_var_align_size +! This example sets PnetCDF hint: +! nc_var_align_size ! and prints the hint values as well as the header size, header extent, and ! two variables' starting file offsets. ! @@ -17,7 +17,6 @@ ! ! % mpiexec -n 4 ./hints /pvfs2/wkliao/testfile.nc ! -! nc_header_align_size set to = 1024 ! nc_var_align_size set to = 512 ! nc_header_read_chunk_size set to = 256 ! header size = 252 @@ -54,9 +53,8 @@ subroutine print_hints(ncid, varid0, varid1) logical flag integer*8 header_size, header_extent integer*8 var_zy_start, var_yx_start - integer*8 h_align, v_align, h_chunk + integer*8 v_align, h_chunk - h_align=-1 v_align=-1 h_chunk=-1 @@ -72,13 +70,6 @@ subroutine print_hints(ncid, varid0, varid1) err = nfmpi_inq_file_info(ncid, info_used) call check(err, 'In nfmpi_inq_file_info : ') - call MPI_Info_get_valuelen(info_used, "nc_header_align_size", - + len, flag, err) - if (flag) then - call MPI_Info_get(info_used, "nc_header_align_size", - + len+1, value, flag, err) - read(value, '(i16)') h_align - endif call MPI_Info_get_valuelen(info_used, "nc_var_align_size", + len, flag, err) if (flag) then @@ -96,11 +87,6 @@ subroutine print_hints(ncid, varid0, varid1) endif call MPI_Info_free(info_used, err) - if (h_align .EQ. -1) then - print*,"nc_header_align_size is NOT set" - else - print*,"nc_header_align_size set to = ", h_align - endif if (v_align .EQ. -1) then print*,"nc_var_align_size is NOT set" else @@ -178,7 +164,6 @@ program main + MPI_COMM_WORLD, err) call MPI_Info_create(info, err) - call MPI_Info_set(info, "nc_header_align_size", "1024", err) call MPI_Info_set(info, "nc_var_align_size", "512", err) call MPI_Info_set(info, "nc_header_read_chunk_size", "256", err) ! note that set the above values to 1 to disable the alignment diff --git a/examples/F90/get_info.f90 b/examples/F90/get_info.f90 index d7df4845c..6b984ff55 100644 --- a/examples/F90/get_info.f90 +++ b/examples/F90/get_info.f90 @@ -16,7 +16,7 @@ ! ! Example standard output: ! -! MPI File Info: nkeys = 18 +! MPI File Info: nkeys = 17 ! MPI File Info: [ 0] key = cb_buffer_size, value =16777216 ! MPI File Info: [ 1] key = romio_cb_read, value =automatic ! MPI File Info: [ 2] key = romio_cb_write, value =automatic @@ -32,9 +32,8 @@ ! MPI File Info: [12] key = romio_ds_read, value =automatic ! MPI File Info: [13] key = romio_ds_write, value =automatic ! MPI File Info: [14] key = cb_config_list, value =*:1 -! MPI File Info: [15] key = nc_header_align_size, value =0 -! MPI File Info: [16] key = nc_var_align_size, value =0 -! MPI File Info: [17] key = nc_header_read_chunk_size, value =0 +! MPI File Info: [15] key = nc_var_align_size, value =0 +! MPI File Info: [16] key = nc_header_read_chunk_size, value =0 program main diff --git a/examples/F90/hints.f90 b/examples/F90/hints.f90 index f8432c40e..805a3388a 100644 --- a/examples/F90/hints.f90 +++ b/examples/F90/hints.f90 @@ -7,8 +7,8 @@ ! $Id$ ! -! This example sets two PnetCDF hints: -! nc_header_align_size and nc_var_align_size +! This example sets PnetCDF hint: +! nc_var_align_size ! and prints the hint values as well as the header size, header extent, and ! two variables' starting file offsets. ! @@ -18,7 +18,6 @@ ! ! % mpiexec -n 4 ./hints /pvfs2/wkliao/testfile.nc ! -! nc_header_align_size set to = 1024 ! nc_var_align_size set to = 512 ! nc_header_read_chunk_size set to = 256 ! header size = 252 @@ -55,9 +54,8 @@ subroutine print_hints(ncid, varid0, varid1) logical flag integer(kind=MPI_OFFSET_KIND) header_size, header_extent integer(kind=MPI_OFFSET_KIND) var_zy_start, var_yx_start - integer(kind=MPI_OFFSET_KIND) h_align, v_align, h_chunk + integer(kind=MPI_OFFSET_KIND) v_align, h_chunk - h_align=-1 v_align=-1 h_chunk=-1 @@ -73,13 +71,6 @@ subroutine print_hints(ncid, varid0, varid1) err = nf90mpi_inq_file_info(ncid, info_used) call check(err, 'In nf90mpi_inq_file_info : ') - call MPI_Info_get_valuelen(info_used, "nc_header_align_size", & - len, flag, err) - if (flag) then - call MPI_Info_get(info_used, "nc_header_align_size", & - len+1, value, flag, err) - read(value, '(i16)') h_align - endif call MPI_Info_get_valuelen(info_used, "nc_var_align_size", & len, flag, err) if (flag) then @@ -97,11 +88,6 @@ subroutine print_hints(ncid, varid0, varid1) endif call MPI_Info_free(info_used, err) - if (h_align .EQ. -1) then - print*,"nc_header_align_size is NOT set" - else - print*,"nc_header_align_size set to = ", h_align - endif if (v_align .EQ. -1) then print*,"nc_var_align_size is NOT set" else @@ -176,7 +162,6 @@ program main call MPI_Bcast(filename, 256, MPI_CHARACTER, 0, MPI_COMM_WORLD, err) call MPI_Info_create(info, err) - call MPI_Info_set(info, "nc_header_align_size", "1024", err) call MPI_Info_set(info, "nc_var_align_size", "512", err) call MPI_Info_set(info, "nc_header_read_chunk_size", "256", err) ! note that set the above values to 1 to disable the alignment diff --git a/examples/README.md b/examples/README.md index bd1e09c89..f55d8a43d 100644 --- a/examples/README.md +++ b/examples/README.md @@ -92,8 +92,8 @@ with C, C++, F77, and F90 versions. + ./CXX/hints.cpp + ./F77/hints.f + ./F90/hints.f90 - + This example sets two PnetCDF hints: `nc_header_align_size` and - `nc_var_align_size` and prints the hint values, the header size, header + + This example sets PnetCDF hint: `nc_var_align_size` + and prints the hint values, the header size, header extent, and variables' starting file offsets. * ./C/mput.c diff --git a/sneak_peek.md b/sneak_peek.md index fc2ab4a5c..2666cb43d 100644 --- a/sneak_peek.md +++ b/sneak_peek.md @@ -90,6 +90,47 @@ This is essentially a placeholder for the next release note ... * Issues related to Darshan library: + none -* Clarifications - + none +* Clarifications about of PnetCDF hints + + There are three ways in PnetCDF for user to set hints to align the starting + file offset for the data section (header extent) and record variable + section. + 1. through a call to API `nc_header_align_size` by setting arguments of + `h_minfree`, `v_align`, `v_minfree`, and `r_align`. + 2. through an MPI info object passed to calls of `ncmpi_create()` and + `ncmpi_open()`. Hints are `nc_header_align_size`, `nc_var_align_size`, + and `nc_record_align_size`. + 3. through a run-time environment variable `PNETCDF_HINTS`. Hints are + `nc_header_align_size`, `nc_var_align_size`, and `nc_record_align_size`. + + As the same hints may be set by one or more of the above methods, PnetCDF + implements the following hint precedence. + * `PNETCDF_HINTS` > `ncmpi__enddef()` > `MPI info`. + * 1st priority: hints set in the environment variable `PNETCDF_HINTS`, e.g. + `PNETCDF_HINTS="nc_var_align_size=1048576"`. Making this the first + priority is because it allows to run the same application executable + without source code modification using different alignment settings + through a run-time environment variable. + * 2nd priority: hints set in the MPI info object passed to calls of + `ncmpi_create()` and `ncmpi_open()`, e.g. + `MPI_Info_set("nc_var_align_size", "1048576");`. The reasoning is when a + 3rd-party library built on top of PnetCDF implements its codes using + 'ncmpi__enddef'. An application that uses such 3rd-party library can pass + an MPI info object to it, which further passes the info to PnetCDF. This + precedence allows that application to exercise different hints without + changing the 3rd-party library's source codes. + * 3rd priority: hints used in the arguments of `ncmpi__enddef()`, e.g. + `ncmpi__enddef(..., v_align=1048576,...)`. + + PnetCDF I/O hint `nc_header_align_size` is essentially the same as hint + `nc_var_align_size`, but its name appears to be closer to the hint's + intent, i.e. to reserve some space for the header growth in the future when + new data objects are added. Please note when both hints are set, only hint + `nc_var_align_size` will take effect and `nc_header_align_size` ignored. + + When there is no fix-sized variable (i.e. non-record variable) defined, + argument `v_minfree` passed to `ncmpi__enddef()` is ignored. In this + case, users should set `h_minfree`, if an extra header space is desired. + + When there is no fix-sized variables defined and none of hints + `nc_header_align_size`, `nc_var_align_size`, or argument `v_align` is set, + `nc_record_align_size` or `r_align`, if set, will be used to align the + header extent. + + For the above update to the hint precedence, see + PnetCDF See [PR #173](https://github.com/Parallel-NetCDF/PnetCDF/pull/173). diff --git a/src/drivers/ncmpio/ncmpio_NC.h b/src/drivers/ncmpio/ncmpio_NC.h index 6c6546d36..313345baa 100644 --- a/src/drivers/ncmpio/ncmpio_NC.h +++ b/src/drivers/ncmpio/ncmpio_NC.h @@ -17,6 +17,11 @@ #include #include "ncmpio_driver.h" +#define NC_DEFAULT_H_MINFREE 0 +#define NC_DEFAULT_V_ALIGN 512 +#define NC_DEFAULT_V_MINFREE 0 +#define NC_DEFAULT_R_ALIGN 4 + #define FILE_ALIGNMENT_DEFAULT 512 #define FILE_ALIGNMENT_LB 4 @@ -383,12 +388,12 @@ struct NC { #endif int striping_unit; /* stripe size of the file */ int chunk; /* chunk size for reading header, one chunk at a time */ - MPI_Offset h_align; /* file alignment for header size */ MPI_Offset v_align; /* alignment of the beginning of fixed-size variables */ MPI_Offset r_align; /* file alignment for record variable section */ - MPI_Offset env_h_align; /* h_align set in environment variable */ MPI_Offset env_v_align; /* v_align set in environment variable */ MPI_Offset env_r_align; /* r_align set in environment variable */ + MPI_Offset info_v_align;/* v_align set in MPI Info object */ + MPI_Offset info_r_align;/* r_align set in MPI Info object */ MPI_Offset h_minfree; /* pad at the end of the header section */ MPI_Offset v_minfree; /* pad at the end of the data section for fixed-size variables */ MPI_Offset ibuf_size; /* packing buffer size for flushing noncontig diff --git a/src/drivers/ncmpio/ncmpio_enddef.c b/src/drivers/ncmpio/ncmpio_enddef.c index 4eca5f6ab..c0f2c48b6 100644 --- a/src/drivers/ncmpio/ncmpio_enddef.c +++ b/src/drivers/ncmpio/ncmpio_enddef.c @@ -305,28 +305,27 @@ NC_begins(NC *ncp) } /* This function is called in ncmpi_enddef(), which can happen either when - * creating a new file or opening an existing file with metadata modified. - * For the former case, ncp->begin_var == 0 here. - * For the latter case, we set begin_var a new value only if the new header - * grows out of its extent or the start of non-record variables is not - * aligned as requested by ncp->h_align. - * Note ncp->xsz is header size and ncp->begin_var is header extent. - * Add the minimum header free space requested by user. + * creating a new file and first time call to ncmpi_enddef(), or other + * case, e.g. opening an existing file, calling ncmpi_redef(), and then + * ncmpi_enddef(). For the former case, ncp->begin_var == 0. For the latter + * case, ncp->begin_var must be > 0, as it is the orignial header extent. + * We increase begin_var only if the new header size grows out of its + * original extent, or the start of variable section is not aligned as + * requested by ncp->v_align. Note ncp->xsz is header size and + * ncp->begin_var is header extent. Growth of header extent must also + * respect the minimum header free space requested by user. */ + ncp->begin_var = MAX(ncp->begin_var, ncp->xsz + ncp->h_minfree); + + /* align header extent */ if (ncp->vars.ndefined > 0) - ncp->begin_var = D_RNDUP(ncp->xsz + ncp->h_minfree, ncp->h_align); + ncp->begin_var = D_RNDUP(ncp->begin_var, ncp->v_align); else /* no variable defined, ignore alignment and set header extent to * header size */ - ncp->begin_var = ncp->xsz; + ncp->begin_var = MAX(ncp->begin_var, ncp->xsz); - if (ncp->old != NULL) { - /* If this define mode was entered from a redef(), we check whether - * the new begin_var against the old begin_var. We do not shrink - * the header extent. - */ - if (ncp->begin_var < ncp->old->begin_var) - ncp->begin_var = ncp->old->begin_var; - } + if (ncp->old != NULL) + assert(ncp->begin_var >= ncp->old->begin_var); /* ncp->begin_var is the aligned starting file offset of the first * variable (also data section), which is the extent of file header @@ -374,13 +373,21 @@ NC_begins(NC *ncp) * non-record variables or if the start of record variables is not aligned * as requested by ncp->r_align. */ - if (ncp->begin_rec < end_var + ncp->v_minfree) - ncp->begin_rec = end_var + ncp->v_minfree; + if (ncp->vars.ndefined > ncp->vars.num_rec_vars) { + if (ncp->begin_rec < end_var + ncp->v_minfree) + ncp->begin_rec = end_var + ncp->v_minfree; + } + else { /* if there is no fix-sized variable, ignore v_minfree */ + if (ncp->begin_rec < end_var) + ncp->begin_rec = end_var; + } ncp->begin_rec = D_RNDUP(ncp->begin_rec, 4); - /* align the starting offset for record variable section */ - if (ncp->r_align > 1) + /* Align the starting offset for record variable section. + * Ignore ncp->r_align, if there is no fix-sized variable. + */ + if (ncp->r_align > 1 && ncp->vars.ndefined > ncp->vars.num_rec_vars) ncp->begin_rec = D_RNDUP(ncp->begin_rec, ncp->r_align); if (ncp->old != NULL) { @@ -985,12 +992,94 @@ ncmpio_NC_check_voffs(NC *ncp) return NC_NOERR; } +/*----< read_hints() >-------------------------------------------------------*/ +/* check only the following hints set in environment variable PNETCDF_HINTS or + * MPI_Info object passed to ncmpi_create() and ncmpi_open(). + * nc_header_align_size, nc_var_align_size, and nc_record_align_size + */ +static void +read_hints(NC *ncp) +{ + char *warn_str="Warning: skip ill-formed hint set in PNETCDF_HINTS"; + char *env_str, *env_str_cpy, *hint, *next_hint, *key, *val, *deli; + char *hint_saved=NULL; + + /* reset hints from environment variable PNETCDF_HINTS */ + ncp->env_v_align = -1; + ncp->env_r_align = -1; + + /* get hints from the environment variable PNETCDF_HINTS, a string of + * hints separated by ";" and each hint is in the form of hint=value. E.g. + * "cb_nodes=16;cb_config_list=*:6". If this environment variable is set, + * it overrides the same hints that were set by MPI_Info_set() called in + * the application program. + */ + env_str = getenv("PNETCDF_HINTS"); + if (env_str == NULL) return; + + env_str_cpy = strdup(env_str); + next_hint = env_str_cpy; + + do { + hint = next_hint; + deli = strchr(hint, ';'); + if (deli != NULL) { + *deli = '\0'; /* add terminate char */ + next_hint = deli + 1; + } + else next_hint = "\0"; + if (hint_saved != NULL) free(hint_saved); + + /* skip all-blank hint */ + hint_saved = strdup(hint); + if (strtok(hint, " \t") == NULL) continue; + + free(hint_saved); + hint_saved = strdup(hint); /* save hint for error message */ + + deli = strchr(hint, '='); + if (deli == NULL) { /* ill-formed hint */ + printf("%s: '%s'\n", warn_str, hint_saved); + continue; + } + *deli = '\0'; + + /* hint key */ + key = strtok(hint, "= \t"); + if (key == NULL || NULL != strtok(NULL, "= \t")) { + /* expect one token before = */ + printf("%s: '%s'\n", warn_str, hint_saved); + continue; + } + + /* hint value */ + val = strtok(deli+1, "= \t"); + if (NULL != strtok(NULL, "= \t")) { /* expect one token before = */ + printf("%s: '%s'\n", warn_str, hint_saved); + continue; + } + + if (!strcmp(key, "nc_header_align_size") && ncp->env_v_align == -1) + ncp->env_v_align = atoll(val); + else if (!strcmp(key, "nc_var_align_size")) + ncp->env_v_align = atoll(val); + else if (!strcmp(key, "nc_record_align_size")) + ncp->env_r_align = atoll(val); + + } while (*next_hint != '\0'); + + if (hint_saved != NULL) free(hint_saved); + free(env_str_cpy); + + /* return no error as all hints are advisory */ +} + /*----< ncmpio__enddef() >---------------------------------------------------*/ /* This is a collective subroutine. * h_minfree Sets the pad at the end of the "header" section, i.e. at least * this amount of free space includes at the end of header extent. * v_align Controls the alignment of the beginning of the data section for - * fixed size variables. + * fixed size variables. Its value is also the header extent. * v_minfree Sets the pad at the end of the data section for fixed size * variables, i.e. at least this amount of free space between the * fixed-size variable section and record variable section. @@ -1006,99 +1095,113 @@ ncmpio__enddef(void *ncdp, { int i, num_fix_vars, mpireturn, err=NC_NOERR, status=NC_NOERR; char value[MPI_MAX_INFO_VAL]; + MPI_Offset saved_begin_var; NC *ncp = (NC*)ncdp; - /* negative values of h_minfree, v_align, v_minfree, r_align have been - * checked at dispatchers. + /* update the total number of record variables */ + ncp->vars.num_rec_vars = 0; + for (i=0; ivars.ndefined; i++) + ncp->vars.num_rec_vars += IS_RECVAR(ncp->vars.value[i]); + + /* h_minfree, v_align, v_minfree, r_align being -1 means this subroutine is + * called from ncmpio_enddef(). */ + /* check hints from environment variable PNETCDF_HINTS, or MPI info */ + read_hints(ncp); + /* sanity check for NC_ENOTINDEFINE, NC_EINVAL, NC_EMULTIDEFINE_FNC_ARGS * has been done at dispatchers */ - ncp->h_minfree = h_minfree; - ncp->v_minfree = v_minfree; - - /* calculate a good file extent alignment size based on: - * + hints set by users in the environment variable PNETCDF_HINTS - * nc_header_align_size and nc_var_align_size - * + v_align set in the call to ncmpi__enddef() - * Hints set in the environment variable PNETCDF_HINTS have the higher - * precedence than the ones set in the API calls. - * The precedence of hints and arguments: - * 1. hints set in PNETCDF_HINTS environment variable at run time - * 2. hints set in the source codes, for example, a call to - * MPI_Info_set("nc_header_align_size", "1048576"); - * 3. source codes calling ncmpi__enddef(). For example, - * MPI_Offset v_align = 1048576; - * ncmpi__enddef(ncid, 0, v_align, 0, 0); - * 4. defaults - * 0 for h_minfree - * 512 for v_align - * 0 for v_minfree - * 4 for r_align + ncp->h_minfree = (h_minfree < 0) ? NC_DEFAULT_H_MINFREE : h_minfree; + ncp->v_minfree = (v_minfree < 0) ? NC_DEFAULT_V_MINFREE : v_minfree; + + /* calculate a good file extent alignment size based on user hints. + * The precedence of hints: + * + 1st priority: hints set in the environment variable PNETCDF_HINTS, + * i.e. nc_var_align_size and nc_record_align_size + * e.g. PNETCDF_HINTS="nc_var_align_size=1024" + * + 2nd priority: hints set in the MPI info objects passed into calls to + * ncmpi_create() and ncmpi_open() + * e.g. MPI_Info_set("nc_var_align_size", "1024"); + * + 3rd priority: hints passed from arguments of ncmpi__enddef() + * i.e. v_align and r_align + * e.g. ncmpi__enddef(..., v_align=1024,...) + * + * Default values + * NC_DEFAULT_H_MINFREE for h_minfree + * NC_DEFAULT_V_ALIGN for v_align + * NC_DEFAULT_V_MINFREE for v_minfree + * NC_DEFAULT_R_ALIGN for r_align */ - /* ncp->h_align, ncp->v_align, ncp->r_align, and ncp->chunk have been - * set during file create/open */ - num_fix_vars = ncp->vars.ndefined - ncp->vars.num_rec_vars; - /* reset to hints set at file create/open time */ - ncp->h_align = ncp->env_h_align; - ncp->v_align = ncp->env_v_align; - ncp->r_align = ncp->env_r_align; - - if (ncp->h_align == 0) { /* hint nc_header_align_size is not set */ - if (ncp->v_align > 0) /* hint nc_var_align_size is set */ - ncp->h_align = ncp->v_align; - else if (v_align > 0) /* v_align is passed from ncmpi__enddef */ - ncp->h_align = v_align; - - /* if no fixed-size variables is defined, use r_align */ - if (ncp->h_align == 0 && num_fix_vars == 0) { - if (ncp->r_align > 0) /* hint nc_record_align_size is set */ - ncp->h_align = ncp->r_align; - else if (r_align > 0) /* r_align is passed from ncmpi__enddef */ - ncp->h_align = r_align; + /* determine header extent (alignment for the data section) */ + if (ncp->env_v_align == -1) { + /* hint nc_var_align_size is not set in PNETCDF_HINTS */ + ncp->v_align = -1; + + if (num_fix_vars == 0 && ncp->env_r_align != -1) + /* if no fix-sizes variable, try use env_r_align */ + ncp->v_align = ncp->env_r_align; + + if (ncp->v_align < 0) { /* ncp->v_align is still not set */ + if (ncp->info_v_align >= 0) + /* use hint set in MPI info passed to ncmpi_create/ncmpi_open */ + ncp->v_align = ncp->info_v_align; + else if (v_align >= 0) + /* valid v_align is passed from ncmpi__enddef */ + ncp->v_align = v_align; } - if (ncp->h_align == 0 && ncp->old == NULL) - /* h_align is still not set. Set h_align only when creating a new - * file. When opening an existing file file, setting h_align here - * may unexpectedly grow the file extent. - */ - ncp->h_align = FILE_ALIGNMENT_DEFAULT; + if (ncp->v_align < 0) { /* ncp->v_align is still not set */ + if (ncp->old != NULL) + /* if enter from redefine mode, reuse one set in old header */ + ncp->v_align = ncp->old->v_align; + else /* default */ + ncp->v_align = NC_DEFAULT_V_ALIGN; + } } - /* else respect user hint */ + else /* hint nc_var_align_size is set in PNETCDF_HINTS, use it and + * ignore v_align passed from ncmpi__enddef(). + */ + ncp->v_align = ncp->env_v_align; + + /* determine alignment for record variable section */ + if (ncp->env_r_align == -1) { + /* hint nc_record_align_size is not set in PNETCDF_HINTS */ + ncp->r_align = -1; + + if (ncp->info_r_align >= 0) + /* use hint set in MPI info passed to ncmpi_create/ncmpi_open */ + ncp->r_align = ncp->info_r_align; + else if (r_align >= 0) + /* valid r_align is passed from ncmpi__enddef */ + ncp->r_align = r_align; - if (ncp->v_align == 0) { /* user info does not set nc_var_align_size */ - if (v_align > 0) /* v_align is passed from ncmpi__enddef */ - ncp->v_align = v_align; - /* else ncp->v_align is already set by user/env, ignore the one passed - * by the argument v_align of this subroutine. - */ + if (ncp->r_align == -1) { /* ncp->r_align is still not set */ + if (ncp->old != NULL) + /* reuse one set in old header */ + ncp->r_align = ncp->old->r_align; + else + ncp->r_align = NC_DEFAULT_R_ALIGN; + } } - - if (ncp->r_align == 0) { /* user info does not set nc_record_align_size */ - if (r_align > 0) /* r_align is passed from ncmpi__enddef */ - ncp->r_align = r_align; - /* else ncp->r_align is already set by user/env, ignore the one passed - * by the argument r_align of this subroutine. + else + /* hint nc_record_align_size is set in PNETCDF_HINTS, use it and + * ignore r_align passed from ncmpi__enddef(). */ - } + ncp->r_align = ncp->env_r_align; /* all CDF formats require 4-bytes alignment */ - if (ncp->h_align == 0) ncp->h_align = 4; - else ncp->h_align = D_RNDUP(ncp->h_align, 4); - if (ncp->v_align == 0) ncp->v_align = 4; - else ncp->v_align = D_RNDUP(ncp->v_align, 4); - if (ncp->r_align == 0) ncp->r_align = 4; - else ncp->r_align = D_RNDUP(ncp->r_align, 4); + if (ncp->v_align == 0) ncp->v_align = 4; + else ncp->v_align = D_RNDUP(ncp->v_align, 4); + if (ncp->r_align == 0) ncp->r_align = 4; + else ncp->r_align = D_RNDUP(ncp->r_align, 4); /* reflect the hint changes to the MPI info object, so the user can inquire * what the true hint values are being used */ - sprintf(value, "%lld", ncp->h_align); - MPI_Info_set(ncp->mpiinfo, "nc_header_align_size", value); sprintf(value, "%lld", ncp->v_align); MPI_Info_set(ncp->mpiinfo, "nc_var_align_size", value); sprintf(value, "%lld", ncp->r_align); @@ -1130,14 +1233,12 @@ ncmpio__enddef(void *ncdp, * Note in NC_begins, root broadcasts ncp->xsz, the file header size, to * all processes. */ + saved_begin_var = ncp->begin_var; err = NC_begins(ncp); + if (err != NC_NOERR) /* restore the original begin_var when failed */ + ncp->begin_var = saved_begin_var; CHECK_ERROR(err) - /* update the total number of record variables */ - ncp->vars.num_rec_vars = 0; - for (i=0; ivars.ndefined; i++) - ncp->vars.num_rec_vars += IS_RECVAR(ncp->vars.value[i]); - if (ncp->safe_mode) { /* check whether variable begins are in an increasing order. * This check is for debugging purpose. */ @@ -1239,6 +1340,6 @@ ncmpio__enddef(void *ncdp, int ncmpio_enddef(void *ncdp) { - return ncmpio__enddef(ncdp, 0, 0, 0, 0); + return ncmpio__enddef(ncdp, -1, -1, -1, -1); } diff --git a/src/drivers/ncmpio/ncmpio_file_misc.c b/src/drivers/ncmpio/ncmpio_file_misc.c index 25671c9d6..75559c112 100644 --- a/src/drivers/ncmpio/ncmpio_file_misc.c +++ b/src/drivers/ncmpio/ncmpio_file_misc.c @@ -362,9 +362,6 @@ ncmpio_inq_misc(void *ncdp, * user. */ - sprintf(value, "%lld", ncp->h_align); - MPI_Info_set(*info_used, "nc_header_align_size", value); - sprintf(value, "%lld", ncp->v_align); MPI_Info_set(*info_used, "nc_var_align_size", value); diff --git a/src/drivers/ncmpio/ncmpio_subfile.c b/src/drivers/ncmpio/ncmpio_subfile.c index 2a0a93f71..3ea09bb7a 100644 --- a/src/drivers/ncmpio/ncmpio_subfile.c +++ b/src/drivers/ncmpio/ncmpio_subfile.c @@ -262,7 +262,6 @@ int ncmpio_subfile_partition(NC *ncp) /* NOTE: the following "for loop" should be before NC_begins() */ /* adjust the hints to be used by PnetCDF; use the same value in master */ - ncp->ncp_sf->h_align = ncp->h_align; ncp->ncp_sf->v_align = ncp->v_align; ncp->ncp_sf->r_align = ncp->r_align; diff --git a/src/drivers/ncmpio/ncmpio_util.c b/src/drivers/ncmpio/ncmpio_util.c index e7d631b2c..fb522f0e1 100644 --- a/src/drivers/ncmpio/ncmpio_util.c +++ b/src/drivers/ncmpio/ncmpio_util.c @@ -38,62 +38,67 @@ void ncmpio_set_pnetcdf_hints(NC *ncp, */ assert(info_used != MPI_INFO_NULL); - /* nc_header_align_size, nc_var_align_size, and r_align take effect when - * a file is created, or opened and later adding more metadata or variable - * data */ + /* nc_var_align_size, and r_align take effect when a file is created, or + * opened and later adding more metadata or variable data + */ - ncp->env_h_align = 0; + ncp->info_v_align = -1; /* -1 indicates not set */ if (user_info != MPI_INFO_NULL) { - /* aligns the size of header extent of a newly created file */ - MPI_Info_get(user_info, "nc_header_align_size", MPI_MAX_INFO_VAL-1, + /* aligns starting file offsets of entire data section */ + MPI_Info_get(user_info, "nc_var_align_size", MPI_MAX_INFO_VAL-1, value, &flag); if (flag) { errno = 0; /* errno must set to zero before calling strtoll */ - ncp->env_h_align = strtoll(value, NULL, 10); - if (errno != 0) ncp->env_h_align = 0; - else if (ncp->env_h_align < 0) ncp->env_h_align = 0; + ncp->info_v_align = strtoll(value, NULL, 10); + if (errno != 0) ncp->info_v_align = -1; + else if (ncp->info_v_align < 0) ncp->info_v_align = -1; } } - if (ncp->env_h_align == 0) + if (ncp->info_v_align == -1) sprintf(value, "%d", FILE_ALIGNMENT_DEFAULT); else - sprintf(value, "%lld", ncp->env_h_align); - MPI_Info_set(info_used, "nc_header_align_size", value); + sprintf(value, "%lld", ncp->info_v_align); + MPI_Info_set(info_used, "nc_var_align_size", value); - ncp->env_v_align = 0; if (user_info != MPI_INFO_NULL) { - /* aligns starting file offsets of individual fixed-size variables */ - MPI_Info_get(user_info, "nc_var_align_size", MPI_MAX_INFO_VAL-1, + /* Hint nc_header_align_size is now deprecated. But for backward + * compatibility, let's still check. + */ + int info_h_align = -1; + MPI_Info_get(user_info, "nc_header_align_size", MPI_MAX_INFO_VAL-1, value, &flag); if (flag) { errno = 0; /* errno must set to zero before calling strtoll */ - ncp->env_v_align = strtoll(value, NULL, 10); - if (errno != 0) ncp->env_v_align = 0; - else if (ncp->env_v_align < 0) ncp->env_v_align = 0; + info_h_align = strtoll(value, NULL, 10); + if (errno != 0) info_h_align = -1; + else if (info_h_align < 0) info_h_align = -1; + } + /* if nc_header_align_size is set and nc_var_align_size is not set, + * replace hint nc_var_align_size with the value of info_h_align. + */ + if (info_h_align >= 0 && ncp->info_v_align == -1) { + ncp->info_v_align = info_h_align; + sprintf(value, "%lld", ncp->info_v_align); + MPI_Info_set(info_used, "nc_var_align_size", value); } } - if (ncp->env_v_align == 0) - sprintf(value, "%d", FILE_ALIGNMENT_DEFAULT); - else - sprintf(value, "%lld", ncp->env_v_align); - MPI_Info_set(info_used, "nc_var_align_size", value); - ncp->env_r_align = 0; + ncp->info_r_align = -1; if (user_info != MPI_INFO_NULL) { /* aligns starting file offset of the record variable section */ MPI_Info_get(user_info, "nc_record_align_size", MPI_MAX_INFO_VAL-1, value, &flag); if (flag) { errno = 0; /* errno must set to zero before calling strtoll */ - ncp->env_r_align = strtoll(value, NULL, 10); - if (errno != 0) ncp->env_r_align = 0; - else if (ncp->env_r_align < 0) ncp->env_r_align = 0; + ncp->info_r_align = strtoll(value, NULL, 10); + if (errno != 0) ncp->info_r_align = -1; + else if (ncp->info_r_align < 0) ncp->info_r_align = -1; } } - if (ncp->env_r_align == 0) + if (ncp->info_r_align == -1) sprintf(value, "%d", FILE_ALIGNMENT_DEFAULT); else - sprintf(value, "%lld", ncp->env_r_align); + sprintf(value, "%lld", ncp->info_r_align); MPI_Info_set(info_used, "nc_record_align_size", value); ncp->chunk = PNC_DEFAULT_CHUNKSIZE; diff --git a/test/F90/f90tst_vars.f90 b/test/F90/f90tst_vars.f90 index a1f98952e..7f43a6908 100644 --- a/test/F90/f90tst_vars.f90 +++ b/test/F90/f90tst_vars.f90 @@ -60,8 +60,7 @@ program f90tst_vars end do call MPI_Info_create(info, ierr) - call MPI_Info_set(info, "nc_header_align_size", "1024", ierr) - call MPI_Info_set(info, "nc_var_align_size", "512", ierr) + call MPI_Info_set(info, "nc_var_align_size", "1024", ierr) call MPI_Info_set(info, "nc_header_read_chunk_size", "256", ierr) ! Create the netCDF file. diff --git a/test/cdf_format/dim_cdf12.c b/test/cdf_format/dim_cdf12.c index 082b944a9..837a419e5 100644 --- a/test/cdf_format/dim_cdf12.c +++ b/test/cdf_format/dim_cdf12.c @@ -72,9 +72,9 @@ int main(int argc, char** argv) /* Note this test program must use the 512-byte alignment setting */ MPI_Info_create(&info); - /* use the 512-byte header align size */ - MPI_Info_set(info, "nc_header_align_size", "512"); - /* use the 512-byte fixed-size variable starting file offset alignment */ + /* use the 512-byte fixed-size variable starting file offset alignment, + * which is also the header extent align size + */ MPI_Info_set(info, "nc_var_align_size", "512"); /* get command-line arguments */ diff --git a/test/testcases/alignment_test.c b/test/testcases/alignment_test.c index affa5c38a..0ce81ca9b 100644 --- a/test/testcases/alignment_test.c +++ b/test/testcases/alignment_test.c @@ -134,8 +134,7 @@ int main(int argc, char** argv) { /* mimic netCDF that does not do alignments */ MPI_Info_create(&info); - MPI_Info_set(info, "nc_header_align_size", "1"); /* size in bytes */ - MPI_Info_set(info, "nc_var_align_size", "197"); /* size in bytes */ + MPI_Info_set(info, "nc_var_align_size", "197"); /* size in bytes */ /* open the file for adding more metadata */ err = ncmpi_open(MPI_COMM_WORLD, filename, NC_WRITE, info, &ncid); diff --git a/test/testcases/tst_info.c b/test/testcases/tst_info.c index 64a295518..3a4fe3caa 100644 --- a/test/testcases/tst_info.c +++ b/test/testcases/tst_info.c @@ -53,7 +53,6 @@ int check_pnetcdf_hints(int ncid) err = ncmpi_inq_file_info(ncid, &info_used); CHECK_ERR; - CHECK_HINT("nc_header_align_size"); CHECK_HINT("nc_var_align_size"); CHECK_HINT("nc_header_read_chunk_size"); CHECK_HINT("nc_record_align_size"); @@ -108,7 +107,6 @@ int main(int argc, char** argv) { /* create some PnetCDF-level I/O hints */ MPI_Info_create(&info); - MPI_Info_set(info, "nc_header_align_size", "1"); /* size in bytes */ MPI_Info_set(info, "nc_var_align_size", "197"); /* size in bytes */ /* create another new file using a non-NULL MPI info --------------------*/ @@ -153,20 +151,6 @@ int main(int argc, char** argv) { } #endif - MPI_Info_get_valuelen(info_used, "nc_header_align_size", &len, &flag); - if (flag) { - MPI_Info_get(info_used, "nc_header_align_size", len+1, value, &flag); - expect = PNETCDF_RNDUP(1, 4); - if (expect != strtoll(value,NULL,10)) { - printf("Error: nc_header_align_size expect %lld but got %lld\n", - expect, strtoll(value,NULL,10)); - nerrs++; - } - } else { - printf("Error: hint \"nc_header_align_size\" is missing\n"); - nerrs++; - } - MPI_Info_get_valuelen(info_used, "nc_var_align_size", &len, &flag); if (flag) { MPI_Info_get(info_used, "nc_var_align_size", len+1, value, &flag); diff --git a/test/testcases/tst_redefine.c b/test/testcases/tst_redefine.c index ecb482adc..9d0379007 100644 --- a/test/testcases/tst_redefine.c +++ b/test/testcases/tst_redefine.c @@ -6,7 +6,14 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * This program tests header extent alignment if entering the redefine mode. + * This program tests all alignment features available from PnetCDF: + * 1. v_align: header extent alignment (starting file offset of data section) + * 2. h_minfree: header free space + * 3. r_align: record variable section alignment + * 4. v_minfree: free space between record variable section and the end of last + * fix-sized variable. + * + * Tests are done by reentering the define mode multiple times. * * The compile and run commands are given below. * @@ -25,11 +32,11 @@ #include -static int verbose; +#define LEN 16 -#define NUM_RNDUP(x, unit) ((((x) + (unit) - 1) / (unit)) * (unit)) +#define RNDUP(x, unit) ((((x) + (unit) - 1) / (unit)) * (unit)) -#define LEN 16 +static int verbose; #define CHECK_VAL(ncid, varid, ii, val, expect) { \ if (val != expect) { \ @@ -43,443 +50,465 @@ static int verbose; } \ } +/*----< check_vars() >-------------------------------------------------------*/ +/* read back variables from file and check their contents */ static int -check_fix_vars(MPI_Comm comm, int ncid, int *varid) +check_vars(MPI_Comm comm, int ncid, int *varid) { - int i, nerrs=0, err, rank, *buf; + int i, nerrs=0, err, rank, *buf, nvars; MPI_Offset start[2], count[2]; MPI_Comm_rank(comm, &rank); - start[0] = 0; start[1] = rank * LEN; - count[0] = 1; count[1] = LEN; + err = ncmpi_inq_nvars(ncid, &nvars); CHECK_ERROUT - buf = (int*) malloc(sizeof(int) * count[0] * count[1]); + /* check fix-sized variables */ + start[0] = 0; + start[1] = rank * LEN; + count[1] = LEN; + + buf = (int*) malloc(sizeof(int) * 2 * LEN); + + /* check record variables */ + count[0] = 2; for (i=0; i 0) goto err_out; \ +} - for (i=0; i ncmpi__enddef() > MPI info. + */ static int -tst_fmt(char *filename, int cmode) +tst_fmt(char *filename, + int cmode, + int has_fix_vars, + MPI_Offset *env_align, /* [3] 0 means unset in PNETCDF_HINTS */ + MPI_Offset *info_align) /* [3] 0 means unset in MPI info */ { int i, rank, nprocs, ncid, err, nerrs=0; - int *buf, dimid[3], varid[4], minfree=100; - MPI_Offset start[2], count[2]; - MPI_Offset old_hsize, hsize; - MPI_Offset old_extent, extent; - MPI_Offset old_var_off, var_off; - MPI_Offset v_align, r_align, exp_var_off; + int *buf, dimid[3], varid[4]; + MPI_Info info=MPI_INFO_NULL; + MPI_Offset start[2], count[2], increment, fix_v_size; + + MPI_Offset hsize=0, old_hsize, exp_hsize; + MPI_Offset extent=0, old_extent, exp_extent; + MPI_Offset h_free=0, old_h_free, exp_h_free; + MPI_Offset v_free=0, old_v_free, exp_v_free; + MPI_Offset r_begin=0, old_r_begin, exp_r_begin; + MPI_Offset h_minfree, v_align, v_minfree, r_align; + MPI_Offset env_h_align=0, env_v_align=0, env_r_align=0; + MPI_Offset info_h_align=0, info_v_align=0, info_r_align=0; + MPI_Comm comm = MPI_COMM_WORLD; MPI_Comm_rank(comm, &rank); MPI_Comm_size(comm, &nprocs); - unsetenv("PNETCDF_HINTS"); + if (verbose && rank == 0) + printf("---- cmode=%d has_fix_vars=%d env_align=%s info_align=%s\n", + cmode,has_fix_vars,(env_align==NULL)?"NULL":"SET", + (info_align==NULL)?"NULL":"SET"); + + if (env_align != NULL) { + env_h_align = env_align[0]; /* 0 means unset in PNETCDF_HINTS */ + env_v_align = env_align[1]; /* 0 means unset in PNETCDF_HINTS */ + env_r_align = env_align[2]; /* 0 means unset in PNETCDF_HINTS */ + if (env_v_align == 0) env_v_align = env_h_align; + } + if (info_align != NULL) { + char str[16]; + info_h_align = info_align[0]; /* 0 means unset in MPI info */ + info_v_align = info_align[1]; /* 0 means unset in MPI info */ + info_r_align = info_align[2]; /* 0 means unset in MPI info */ + MPI_Info_create(&info); + if (info_h_align) { + sprintf(str, "%lld", info_h_align); + MPI_Info_set(info, "nc_header_align_size", str); + } + if (info_v_align) { + sprintf(str, "%lld", info_v_align); + MPI_Info_set(info, "nc_var_align_size", str); + } + if (info_r_align) { + sprintf(str, "%lld", info_r_align); + MPI_Info_set(info, "nc_record_align_size", str); + } + if (info_v_align == 0) info_v_align = info_h_align; + } + if (verbose && rank == 0) + printf("---- cmode=%d has_fix_vars=%d env_align=%lld %lld %lld info_align=%lld %lld %lld\n", + cmode,has_fix_vars,env_h_align,env_v_align,env_r_align, + info_h_align,info_v_align,info_r_align); + /* create a new file */ cmode |= NC_CLOBBER; - err = ncmpi_create(comm, filename, cmode, MPI_INFO_NULL, &ncid); CHECK_ERR + err = ncmpi_create(comm, filename, cmode, info, &ncid); CHECK_ERR err = ncmpi_def_dim(ncid, "time", NC_UNLIMITED, &dimid[0]); CHECK_ERR err = ncmpi_def_dim(ncid, "dim", LEN*nprocs, &dimid[1]); CHECK_ERR - err = ncmpi_def_var(ncid, "fa", NC_INT, 1, dimid+1, &varid[0]); CHECK_ERR - err = ncmpi_def_var(ncid, "fb", NC_INT, 1, dimid+1, &varid[1]); CHECK_ERR - err = ncmpi_def_var(ncid, "ta", NC_INT, 2, dimid, &varid[2]); CHECK_ERR - err = ncmpi_def_var(ncid, "tb", NC_INT, 2, dimid, &varid[3]); CHECK_ERR + err = ncmpi_def_var(ncid, "ta", NC_INT, 2, dimid, &varid[0]); CHECK_ERR + err = ncmpi_def_var(ncid, "tb", NC_INT, 2, dimid, &varid[1]); CHECK_ERR + if (has_fix_vars) { + err = ncmpi_def_var(ncid, "fa", NC_INT, 1, dimid+1, &varid[2]); + CHECK_ERR + err = ncmpi_def_var(ncid, "fb", NC_INT, 1, dimid+1, &varid[3]); + CHECK_ERR + } + err = ncmpi_put_att_text(ncid, NC_GLOBAL, "attr", 0, NULL); CHECK_ERR - /* disable header alignment */ - err = ncmpi__enddef(ncid, 0, 4, 0, 4); CHECK_ERR + err = ncmpi_enddef(ncid); CHECK_ERR + /* write to all variables, 2 records */ start[0] = 0; start[1] = rank * LEN; count[0] = 2; count[1] = LEN; buf = (int*) malloc(sizeof(int) * count[0] * count[1]); - for (i=0; i 0) goto err_out; - nerrs += check_rec_vars(comm, ncid, varid+2); - if (nerrs > 0) goto err_out; - - err = ncmpi_close(ncid); CHECK_ERR - - /* reopen the file and check file header size and extent */ - err = ncmpi_open(comm, filename, NC_WRITE, MPI_INFO_NULL, &ncid); CHECK_ERR - - err = ncmpi_inq_varid(ncid, "fa", &varid[0]); CHECK_ERR - err = ncmpi_inq_varid(ncid, "fb", &varid[1]); CHECK_ERR - err = ncmpi_inq_varid(ncid, "ta", &varid[2]); CHECK_ERR - err = ncmpi_inq_varid(ncid, "tb", &varid[3]); CHECK_ERR - - err = ncmpi_inq_header_size(ncid, &hsize); CHECK_ERR - err = ncmpi_inq_header_extent(ncid, &extent); CHECK_ERR - if (verbose) - printf("File header size = %lld extent = %lld\n", hsize, extent); - - /* make sure header size == extent */ - if (hsize != extent) { - nerrs++; - printf("Error at line %d in %s: File header size %lld != extent %lld\n", - __LINE__,__FILE__, hsize, extent); + for (i=0; i 0) goto err_out; - nerrs += check_rec_vars(comm, ncid, varid+2); - if (nerrs > 0) goto err_out; + /* expect nothing changed */ + exp_hsize = old_hsize; + exp_extent = old_extent; + exp_h_free = old_h_free; + exp_v_free = old_v_free; + exp_r_begin = old_r_begin; + CHECK_HEADER_SIZE - /* enter redefine mode and add nothing */ - err = ncmpi_redef(ncid); CHECK_ERR + err = ncmpi_close(ncid); CHECK_ERR - /* add free space into header extent */ - err = ncmpi__enddef(ncid, minfree, 0, 0, 0); CHECK_ERR + /* reopen the file and check file header size and extent */ + err = ncmpi_open(comm, filename, NC_WRITE, info, &ncid); CHECK_ERR - old_hsize = hsize; - old_extent = extent; - err = ncmpi_inq_header_size(ncid, &hsize); CHECK_ERR - err = ncmpi_inq_header_extent(ncid, &extent); CHECK_ERR - if (verbose) { - printf("File old header size = %6lld old extent = %6lld\n", old_hsize, old_extent); - printf("File new header size = %6lld new extent = %6lld\n", hsize, extent); + err = ncmpi_inq_varid(ncid, "ta", &varid[0]); CHECK_ERR + err = ncmpi_inq_varid(ncid, "tb", &varid[1]); CHECK_ERR + if (has_fix_vars) { + err = ncmpi_inq_varid(ncid, "fa", &varid[2]); CHECK_ERR + err = ncmpi_inq_varid(ncid, "fb", &varid[3]); CHECK_ERR } - /* make sure header size does not change */ - if (hsize != old_hsize) { - nerrs++; - printf("Error at line %d in %s: File header size %lld changed from %lld\n", - __LINE__,__FILE__, hsize, old_hsize); - } - /* make sure header extent grows minfree bytes */ - if (extent != old_extent + minfree) { - nerrs++; - printf("Error at line %d in %s: File header extent %lld fails to grow into %lld\n", - __LINE__,__FILE__, extent, old_extent + minfree); - } + GET_HEADER_SIZE - nerrs += check_fix_vars(comm, ncid, varid); - if (nerrs > 0) goto err_out; - nerrs += check_rec_vars(comm, ncid, varid+2); - if (nerrs > 0) goto err_out; + /* expect nothing changed */ + exp_hsize = old_hsize; + exp_extent = old_extent; + exp_h_free = old_h_free; + exp_v_free = old_v_free; + exp_r_begin = old_r_begin; + CHECK_HEADER_SIZE - /* enter redefine mode and add nothing */ + /* enter redefine mode -------------------------------------------*/ err = ncmpi_redef(ncid); CHECK_ERR - /* align header extent to 512 bytes */ - err = ncmpi__enddef(ncid, 0, 512, 0, 0); CHECK_ERR + /* grow header size */ + increment = extent - hsize + 8; + GROW_METADATA(increment) - old_hsize = hsize; - old_extent = extent; - err = ncmpi_inq_header_size(ncid, &hsize); CHECK_ERR - err = ncmpi_inq_header_extent(ncid, &extent); CHECK_ERR - if (verbose) { - printf("File old header size = %6lld old extent = %6lld\n", old_hsize, old_extent); - printf("File new header size = %6lld new extent = %6lld\n", hsize, extent); - } + /* exit define mode */ + h_minfree = 0; + v_minfree = 0; + v_align = 4; + r_align = 4; + err = ncmpi_enddef(ncid); CHECK_ERR - /* make sure header size does not change */ - if (hsize != old_hsize) { - nerrs++; - printf("Error at line %d in %s: File header size %lld changed from %lld\n", - __LINE__,__FILE__, hsize, old_hsize); - } - /* make sure header extent grows to 512 bytes */ - if (extent != 512) { - nerrs++; - printf("Error at line %d in %s: File header extent %lld fails to grow into 512\n", - __LINE__,__FILE__, extent); - } + GET_HEADER_SIZE + CHECK_ALIGNMENTS - nerrs += check_fix_vars(comm, ncid, varid); - if (nerrs > 0) goto err_out; - nerrs += check_rec_vars(comm, ncid, varid+2); - if (nerrs > 0) goto err_out; - - err = ncmpi_close(ncid); CHECK_ERR - - - setenv("PNETCDF_HINTS", "nc_header_align_size=700", 1); - - /* reopen the file and check file header size and extent */ - err = ncmpi_open(comm, filename, NC_WRITE, MPI_INFO_NULL, &ncid); CHECK_ERR - - err = ncmpi_inq_varid(ncid, "fa", &varid[0]); CHECK_ERR - err = ncmpi_inq_varid(ncid, "fb", &varid[1]); CHECK_ERR - err = ncmpi_inq_varid(ncid, "ta", &varid[2]); CHECK_ERR - err = ncmpi_inq_varid(ncid, "tb", &varid[3]); CHECK_ERR - - /* enter redefine mode and add nothing */ + /* enter redefine mode -------------------------------------------*/ err = ncmpi_redef(ncid); CHECK_ERR - /* align header extent to 800 bytes, this should take no effect, as - * run-time hints precedes function calls. */ - err = ncmpi__enddef(ncid, 0, 800, 0, 0); CHECK_ERR - - old_hsize = hsize; - old_extent = extent; - err = ncmpi_inq_header_size(ncid, &hsize); CHECK_ERR - err = ncmpi_inq_header_extent(ncid, &extent); CHECK_ERR - if (verbose) { - printf("File old header size = %6lld old extent = %6lld\n", old_hsize, old_extent); - printf("File new header size = %6lld new extent = %6lld\n", hsize, extent); - } - - /* make sure header size does not change */ - if (hsize != old_hsize) { - nerrs++; - printf("Error at line %d in %s: File header size %lld changed from %lld\n", - __LINE__,__FILE__, hsize, old_hsize); - } - /* make sure header extent grows to 700 bytes */ - if (extent != 700) { - nerrs++; - printf("Error at line %d in %s: File header extent %lld fails to grow into 700\n", - __LINE__,__FILE__, extent); - } - - unsetenv("PNETCDF_HINTS"); + /* add a header free space, disable header alignment */ + increment = 0; + h_minfree = 76; + v_minfree = 44; + v_align = 4; + r_align = 4; + err = ncmpi__enddef(ncid, h_minfree, v_align, v_minfree, r_align); + CHECK_ERR - nerrs += check_fix_vars(comm, ncid, varid); - if (nerrs > 0) goto err_out; - nerrs += check_rec_vars(comm, ncid, varid+2); - if (nerrs > 0) goto err_out; + GET_HEADER_SIZE + CHECK_ALIGNMENTS - /* enter redefine mode and add nothing */ + /* enter redefine mode -------------------------------------------*/ err = ncmpi_redef(ncid); CHECK_ERR - /* set minfree to the free space, this should not grow the extent */ - err = ncmpi__enddef(ncid, extent-hsize, 0, 0, 0); CHECK_ERR + /* grow header size */ + increment = extent - hsize - 16; + GROW_METADATA(increment); - old_hsize = hsize; - old_extent = extent; - err = ncmpi_inq_header_size(ncid, &hsize); CHECK_ERR - err = ncmpi_inq_header_extent(ncid, &extent); CHECK_ERR - if (verbose) { - printf("File old header size = %6lld old extent = %6lld\n", old_hsize, old_extent); - printf("File new header size = %6lld new extent = %6lld\n", hsize, extent); - } - - /* make sure header size does not change */ - if (hsize != old_hsize) { - nerrs++; - printf("Error at line %d in %s: File header size %lld changed from %lld\n", - __LINE__,__FILE__, hsize, old_hsize); - } - /* make sure header extent remain the same */ - if (extent != old_extent) { - nerrs++; - printf("Error at line %d in %s: File header extent %lld changed from %lld\n", - __LINE__,__FILE__, extent, old_extent); - } - - /* obtain 1st record variable's file offset */ - err = ncmpi_inq_varoffset(ncid, varid[2], &old_var_off); CHECK_ERR + /* disable header alignment */ + h_minfree = 0; + v_minfree = 31; + v_align = 4; + r_align = 4; + err = ncmpi__enddef(ncid, h_minfree, v_align, v_minfree, r_align); + CHECK_ERR - nerrs += check_fix_vars(comm, ncid, varid); - if (nerrs > 0) goto err_out; - nerrs += check_rec_vars(comm, ncid, varid+2); - if (nerrs > 0) goto err_out; + GET_HEADER_SIZE + CHECK_ALIGNMENTS - /* enter redefine mode and add nothing */ + /* enter redefine mode -------------------------------------------*/ err = ncmpi_redef(ncid); CHECK_ERR - /* set v_minfree of size 400 */ - err = ncmpi__enddef(ncid, 0, 0, 400, 0); CHECK_ERR + /* grow header size */ + increment = extent - hsize - 4; + GROW_METADATA(increment); - /* obtain 1st record variable's file offset */ - err = ncmpi_inq_varoffset(ncid, varid[2], &var_off); CHECK_ERR + /* exit define mode */ + h_minfree = 0; + v_minfree = 0; + v_align = 4; + r_align = 4; + err = ncmpi_enddef(ncid); CHECK_ERR - /* var_off should grows 400 bytes */ - if (var_off != old_var_off + 400) { - nerrs++; - printf("Error at line %d in %s: 1st record variable offset %lld (expecting %lld)\n", - __LINE__,__FILE__, var_off, old_var_off+400); - } + GET_HEADER_SIZE + CHECK_ALIGNMENTS - nerrs += check_fix_vars(comm, ncid, varid); - if (nerrs > 0) goto err_out; - nerrs += check_rec_vars(comm, ncid, varid+2); - if (nerrs > 0) goto err_out; - -#if 0 - err = ncmpi_close(ncid); CHECK_ERR - - /* reopen the file and set r_align */ - err = ncmpi_open(comm, filename, NC_WRITE, MPI_INFO_NULL, &ncid); CHECK_ERR -#endif - - /* obtained the old offset of 1st record variable */ - err = ncmpi_inq_varoffset(ncid, varid[2], &old_var_off); CHECK_ERR - - /* enter redefine mode and add nothing */ + /* enter redefine mode -------------------------------------------*/ err = ncmpi_redef(ncid); CHECK_ERR - /* set r_align to 1500 */ - r_align = 1500; - err = ncmpi__enddef(ncid, 0, 0, 0, r_align); CHECK_ERR + increment = 0; + h_minfree = 0; + v_minfree = 31; + r_align = 4; - /* obtain 1st record variable's file offset */ - err = ncmpi_inq_varoffset(ncid, varid[2], &var_off); CHECK_ERR + /* increase v_align */ + v_align = extent + 4; + err = ncmpi__enddef(ncid, h_minfree, v_align, v_minfree, r_align); + CHECK_ERR - /* round up to r_align */ - exp_var_off = NUM_RNDUP(old_var_off, r_align); + GET_HEADER_SIZE - /* var_off should grows into 1500 bytes */ - if (var_off != exp_var_off) { - nerrs++; - printf("Error at line %d in %s: 1st record variable offset %lld (expecting %lld)\n", - __LINE__,__FILE__, var_off, exp_var_off); - } + CHECK_ALIGNMENTS - nerrs += check_fix_vars(comm, ncid, varid); - if (nerrs > 0) goto err_out; - nerrs += check_rec_vars(comm, ncid, varid+2); - if (nerrs > 0) goto err_out; + /* enter redefine mode -------------------------------------------*/ + err = ncmpi_redef(ncid); CHECK_ERR - err = ncmpi_close(ncid); CHECK_ERR + increment = 0; + h_minfree = 0; + v_minfree = 31; + v_align = 4; - unsetenv("PNETCDF_HINTS"); + /* increase r_align */ + r_align = r_begin + 4; + err = ncmpi__enddef(ncid, h_minfree, v_align, v_minfree, r_align); + CHECK_ERR - /* re-create a new file */ - cmode |= NC_CLOBBER; - err = ncmpi_create(comm, filename, cmode, MPI_INFO_NULL, &ncid); CHECK_ERR + GET_HEADER_SIZE - /* define only record variables */ - err = ncmpi_def_dim(ncid, "time", NC_UNLIMITED, &dimid[0]); CHECK_ERR - err = ncmpi_def_dim(ncid, "dim", LEN*nprocs, &dimid[1]); CHECK_ERR - err = ncmpi_def_var(ncid, "ta", NC_INT, 2, dimid, &varid[2]); CHECK_ERR - err = ncmpi_def_var(ncid, "tb", NC_INT, 2, dimid, &varid[3]); CHECK_ERR + CHECK_ALIGNMENTS - /* set v_align and r_align. Without record variables, r_align will take - * effect over v_align - */ - v_align = 100; - r_align = 512; - err = ncmpi__enddef(ncid, 0, v_align, 0, r_align); CHECK_ERR + /* enter redefine mode -------------------------------------------*/ + err = ncmpi_redef(ncid); CHECK_ERR - start[0] = 0; start[1] = rank * LEN; - count[0] = 2; count[1] = LEN; + increment = 0; + h_minfree = 0; + v_minfree = 0; + v_align = 4; + r_align = 4; - for (i=0; i<2*LEN; i++) buf[i] = rank + i + 1000; - err = ncmpi_put_vara_int_all(ncid, varid[2], start, count, buf); CHECK_ERR - for (i=0; i<2*LEN; i++) buf[i] = rank + i + 10000; - err = ncmpi_put_vara_int_all(ncid, varid[3], start, count, buf); CHECK_ERR - - err = ncmpi_inq_header_size(ncid, &hsize); CHECK_ERR - err = ncmpi_inq_header_extent(ncid, &extent); CHECK_ERR - if (verbose) - printf("File header size = %lld extent = %lld\n", hsize, extent); - - /* obtain 1st record variable's file offset */ - err = ncmpi_inq_varoffset(ncid, varid[2], &var_off); CHECK_ERR - if (var_off != extent) { - nerrs++; - printf("Error at line %d in %s: 1st record variable offset %lld (expecting %lld)\n", - __LINE__,__FILE__, var_off, extent); - } + /* add nothing */ + err = ncmpi_enddef(ncid); CHECK_ERR - /* extent should be r_align */ - if (extent != r_align) { - nerrs++; - printf("Error at line %d in %s: file extent %lld (expecting %lld)\n", - __LINE__,__FILE__, extent, r_align); - } + GET_HEADER_SIZE - nerrs += check_rec_vars(comm, ncid, varid+2); - if (nerrs > 0) goto err_out; + CHECK_ALIGNMENTS err_out: err = ncmpi_close(ncid); CHECK_ERR free(buf); + if (info != MPI_INFO_NULL) MPI_Info_free(&info); return nerrs; } int main(int argc, char** argv) { - char filename[256]; - int commsize, rank, err, nerrs=0; + char filename[256], str[256]; + int i, rank, err, nerrs=0, cmode[3], has_fix_vars; MPI_Comm comm = MPI_COMM_WORLD; + MPI_Offset env_align[3], info_align[3]; MPI_Init(&argc, &argv); - MPI_Comm_size(comm, &commsize); MPI_Comm_rank(comm, &rank); verbose = 0; @@ -497,11 +526,121 @@ int main(int argc, char** argv) sprintf(cmd_str, "*** TESTING C %s for header alignment ", basename(argv[0])); printf("%-66s ------ ", cmd_str); fflush(stdout); free(cmd_str); + if (verbose) printf("\n"); + } + cmode[0] = 0; + cmode[1] = NC_64BIT_OFFSET; + cmode[2] = NC_64BIT_DATA; + + for (has_fix_vars=1; has_fix_vars>=0; has_fix_vars--) { + /* No hints set in environment variable PNETCDF_HINTS. + * No hints set in MPI Info object. + */ + unsetenv("PNETCDF_HINTS"); + for (i=0; i<3; i++) { + nerrs += tst_fmt(filename, cmode[i], has_fix_vars, NULL, NULL); + if (nerrs > 0) goto main_exit; + } + + info_align[0] = 28; /* 7 x 4 */ + info_align[1] = 44; /* 11 x 4 */ + info_align[2] = 52; /* 13 x 4 */ + + /* No hints set in environment variable PNETCDF_HINTS. + * Hints set in MPI Info object. + */ + for (i=0; i<3; i++) { + nerrs += tst_fmt(filename, cmode[i], has_fix_vars, NULL, + info_align); + if (nerrs > 0) goto main_exit; + } + + env_align[0] = 68; /* 17 x 4 */ + env_align[1] = 76; /* 19 x 4 */ + env_align[2] = 92; /* 23 x 4 */ + sprintf(str, "nc_header_align_size=%lld;nc_var_align_size=%lld;nc_record_align_size=%lld\n", + env_align[0], env_align[1], env_align[2]); + setenv("PNETCDF_HINTS", str, 1); + + /* Set hints in environment variable PNETCDF_HINTS. + * No hints set in MPI Info object. + */ + for (i=0; i<3; i++) { + nerrs += tst_fmt(filename, cmode[i], has_fix_vars, env_align, NULL); + if (nerrs > 0) goto main_exit; + } + + /* Set hints in environment variable PNETCDF_HINTS. + * Set hints in MPI Info object. + */ + for (i=0; i<3; i++) { + nerrs += tst_fmt(filename, cmode[i], has_fix_vars, env_align, + info_align); + if (nerrs > 0) goto main_exit; + } + + env_align[0] = 68; /* 17 x 4 */ + env_align[1] = 0; + env_align[2] = 92; /* 23 x 4 */ + sprintf(str, "nc_header_align_size=%lld;nc_record_align_size=%lld\n", + env_align[0], env_align[2]); + setenv("PNETCDF_HINTS", str, 1); + + /* Set hints in environment variable PNETCDF_HINTS. + * No hints set in MPI Info object. + */ + for (i=0; i<3; i++) { + nerrs += tst_fmt(filename, cmode[i], has_fix_vars, env_align, + info_align); + if (nerrs > 0) goto main_exit; + } + + env_align[0] = 0; + env_align[1] = 76; /* 19 x 4 */ + env_align[2] = 92; /* 23 x 4 */ + sprintf(str, "nc_var_align_size=%lld;nc_record_align_size=%lld\n", + env_align[1], env_align[2]); + setenv("PNETCDF_HINTS", str, 1); + + /* Set hints in environment variable PNETCDF_HINTS. + * No hints set in MPI Info object. + */ + for (i=0; i<3; i++) { + nerrs += tst_fmt(filename, cmode[i], has_fix_vars, env_align, + info_align); + if (nerrs > 0) goto main_exit; + } + + env_align[0] = 0; + env_align[1] = 76; /* 19 x 4 */ + env_align[2] = 0; + sprintf(str, "nc_var_align_size=%lld\n", env_align[1]); + setenv("PNETCDF_HINTS", str, 1); + + /* Set hints in environment variable PNETCDF_HINTS. + * No hints set in MPI Info object. + */ + for (i=0; i<3; i++) { + nerrs += tst_fmt(filename, cmode[i], has_fix_vars, env_align, + info_align); + if (nerrs > 0) goto main_exit; + } + + env_align[0] = 0; /* 17 x 4 */ + env_align[1] = 0; + env_align[2] = 92; /* 23 x 4 */ + sprintf(str, "nc_record_align_size=%lld\n", env_align[2]); + setenv("PNETCDF_HINTS", str, 1); + + /* Set hints in environment variable PNETCDF_HINTS. + * No hints set in MPI Info object. + */ + for (i=0; i<3; i++) { + nerrs += tst_fmt(filename, cmode[i], has_fix_vars, env_align, + info_align); + if (nerrs > 0) goto main_exit; + } } - - nerrs += tst_fmt(filename, 0); - nerrs += tst_fmt(filename, NC_64BIT_OFFSET); - nerrs += tst_fmt(filename, NC_64BIT_DATA); /* check if PnetCDF freed all internal malloc */ MPI_Offset malloc_size, sum_size; @@ -514,6 +653,7 @@ int main(int argc, char** argv) if (malloc_size > 0) ncmpi_inq_malloc_list(); } +main_exit: MPI_Allreduce(MPI_IN_PLACE, &nerrs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD); if (rank == 0) { if (nerrs) printf(FAIL_STR,nerrs); @@ -523,3 +663,4 @@ int main(int argc, char** argv) MPI_Finalize(); return (nerrs > 0); } +