Skip to content

Commit b2c8dcf

Browse files
committed
Enable hint file, run the benchmark once per line in the hint file
hint file name is "e3sm_io_hints.txt"
1 parent 4759892 commit b2c8dcf

File tree

2 files changed

+130
-41
lines changed

2 files changed

+130
-41
lines changed

e3sm_io_hints.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
start_iodevice=10;striping_unit=1048576;striping_factor=8;lustre_overstriping_ratio=1;cb_nodes=8
2+
start_iodevice=10;striping_unit=1048576;striping_factor=8;lustre_overstriping_ratio=1;cb_nodes=8;nc_num_aggrs_per_node=32

src/e3sm_io.c

Lines changed: 128 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -76,21 +76,88 @@ void check_connector_env(e3sm_io_config *cfg) {
7676
free(env_str);
7777
}
7878

79-
static inline int set_info (e3sm_io_config *cfg, e3sm_io_decom *decom) {
79+
static
80+
int parse_hint_line(e3sm_io_config *cfg,
81+
char *hint_str)
82+
{
83+
char *warn_str="Warning: skip ill-formed hint set in PNETCDF_HINTS";
84+
char *next_hint, *key, *val, *deli;
85+
int err=MPI_SUCCESS;
86+
87+
if (hint_str == NULL) return 1;
88+
89+
/* skip blank lines */
90+
char *hint_saved = strdup(hint_str);
91+
if (strlen(hint_str) == 0 || strtok(hint_saved, " \t") == NULL) {
92+
free(hint_saved);
93+
return 1;
94+
}
95+
96+
next_hint = hint_str;
97+
do {
98+
deli = strchr(hint_str, ';');
99+
if (deli != NULL) {
100+
*deli = '\0'; /* add terminate char */
101+
next_hint = deli + 1;
102+
}
103+
else break; /* done with this line */
104+
105+
/* skip all-blank hint, i.e. blanks in between 2 ';' */
106+
if (strtok(NULL, " \t") == NULL) continue;
107+
108+
deli = strchr(hint_str, '=');
109+
if (deli == NULL) { /* ill-formed hint */
110+
printf("%s: '%s'\n", warn_str, hint_str);
111+
continue;
112+
}
113+
*deli = '\0';
114+
115+
/* hint key */
116+
key = strtok(NULL, "= \t");
117+
if (key == NULL || NULL != strtok(NULL, "= \t")) {
118+
/* expect one token before = */
119+
printf("%s: '%s'\n", warn_str, hint_str);
120+
continue;
121+
}
122+
123+
/* hint value */
124+
val = strtok(deli+1, "= \t");
125+
if (NULL != strtok(NULL, "= \t")) {
126+
/* expect one token before = */
127+
printf("%s: '%s'\n", warn_str, hint_str);
128+
continue;
129+
}
130+
131+
/* override previouse set hint or add a new one */
132+
err = MPI_Info_set(cfg->info, key, val);
133+
CHECK_MPIERR
134+
135+
} while (*next_hint != '\0');
136+
137+
err_out:
138+
return err;
139+
}
140+
141+
static inline int set_info(e3sm_io_config *cfg,
142+
char *hint_str)
143+
{
80144
int err;
81145

82146
/* set MPI-IO hints */
83147

148+
err = MPI_Info_create (&(cfg->info));
149+
CHECK_MPIERR
150+
84151
/* collective write */
85152
err = MPI_Info_set (cfg->info, "romio_cb_write", "enable");
86153
CHECK_MPIERR
87154

88155
/* HDF5 may do independent I/O internally */
89156

90157
if (cfg->api == pnetcdf) {
91-
/* no independent MPI-IO */
92-
err = MPI_Info_set (cfg->info, "romio_no_indep_rw", "true");
93-
CHECK_MPIERR
158+
/* set MPI-IO hints here */
159+
// err = MPI_Info_set (cfg->info, "romio_no_indep_rw", "true");
160+
// CHECK_MPIERR
94161

95162
/* set PnetCDF I/O hints */
96163

@@ -121,6 +188,9 @@ static inline int set_info (e3sm_io_config *cfg, e3sm_io_decom *decom) {
121188
/* in-place byte swap */
122189
err = MPI_Info_set (cfg->info, "nc_in_place_swap", "enable");
123190
CHECK_MPIERR
191+
192+
err = parse_hint_line(cfg, hint_str);
193+
if (err == 0) goto err_out;
124194
}
125195

126196
err_out:
@@ -224,7 +294,7 @@ int main (int argc, char **argv) {
224294
CHECK_ERR;
225295
#endif
226296

227-
timing[0] = MPI_Wtime();
297+
timing[1] = MPI_Wtime();
228298

229299
MPI_Comm_rank (MPI_COMM_WORLD, &(cfg.rank));
230300
MPI_Comm_size (MPI_COMM_WORLD, &(cfg.np));
@@ -562,7 +632,7 @@ int main (int argc, char **argv) {
562632
PRINT_MSG (1, "Input data file/folder name = %s\n", cfg.in_path);
563633
PRINT_MSG (1, "Output data file/folder name = %s\n", cfg.out_path);
564634

565-
timing[1] = MPI_Wtime() - timing[0];
635+
timing[1] = MPI_Wtime() - timing[1];
566636
MPI_Barrier(MPI_COMM_WORLD);
567637
timing[2] = MPI_Wtime();
568638

@@ -584,41 +654,68 @@ int main (int argc, char **argv) {
584654
cfg.run_case = unknown;
585655

586656
timing[2] = MPI_Wtime() - timing[2];
587-
MPI_Barrier(MPI_COMM_WORLD);
588-
timing[3] = MPI_Wtime();
589657

590-
/* set MPI-IO and PnetCDF hints */
591-
err = MPI_Info_create (&(cfg.info));
592-
CHECK_MPIERR
593-
err = set_info (&cfg, &decom);
594-
if (err < 0) goto err_out;
658+
/* read I/O hints from file e3sm_io_hints.txt, run e3sm_io_core() one per
659+
* line in the hint file. Each line contains hints as if it is set in the
660+
* environment variable PNETCDF_HINTS.
661+
*/
662+
FILE *fptr = fopen("e3sm_io_hints.txt", "r");
663+
char hint_str[512];
664+
int next_line;
665+
if (fptr == NULL) /* ignore hint file if not exist */
666+
next_line = EOF;
667+
else /* get the first line of the hint file */
668+
next_line = fscanf(fptr, "%s", hint_str);
595669

596-
/* the core of this benchmark */
597-
err = e3sm_io_core (&cfg, &decom);
598-
CHECK_ERR
670+
do {
599671

600-
timing[3] = MPI_Wtime() - timing[3];
601-
MPI_Barrier(MPI_COMM_WORLD);
602-
timing[4] = MPI_Wtime();
672+
if (cfg.rank == 0) printf("\nHINTS: %s\n\n", (next_line == EOF) ? "" : hint_str);
603673

604-
/* report timing breakdowns */
605-
if (cfg.rd) {
606-
report_timing_RD(&cfg, &decom);
607-
}
608-
else{
609-
report_timing_WR(&cfg, &decom);
610-
}
674+
/* the core of this benchmark */
675+
MPI_Barrier(MPI_COMM_WORLD);
676+
timing[3] = MPI_Wtime();
677+
678+
/* set MPI-IO and PnetCDF hints */
679+
err = set_info(&cfg, (next_line == EOF) ? NULL : hint_str);
680+
if (err < 0) goto err_out;
681+
682+
err = e3sm_io_core(&cfg, &decom);
683+
CHECK_ERR
684+
685+
timing[3] = MPI_Wtime() - timing[3];
686+
687+
/* report timing breakdowns */
688+
if (cfg.rd)
689+
report_timing_RD(&cfg, &decom);
690+
else
691+
report_timing_WR(&cfg, &decom);
611692

612693
#ifdef E3SM_IO_PROFILING
613-
if (cfg.profiling) e3sm_io_print_profile(&cfg);
694+
if (cfg.profiling) e3sm_io_print_profile(&cfg);
614695
#else
615-
if (cfg.profiling && cfg.rank == 0)
616-
printf("\nWarning: E3SM-IO internal time profiling was disabled at configure time\n\n");
696+
if (cfg.profiling && cfg.rank == 0)
697+
printf("\nWarning: E3SM-IO internal time profiling was disabled at configure time\n\n");
617698
#endif
618699

700+
if (cfg.info != MPI_INFO_NULL) MPI_Info_free (&(cfg.info));
701+
702+
timing[0] = timing[1] + timing[2] + timing[3];
703+
MPI_Reduce(timing, max_t, 4, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD);
704+
if (cfg.rank == 0) {
705+
printf("init=%.2f read_decomp=%.2f e3sm_io_core=%.2f end-to-end=%.2f\n",
706+
max_t[1],max_t[2],max_t[3],max_t[0]);
707+
printf("-----------------------------------------------------------\n");
708+
printf("\n\n");
709+
}
710+
711+
if (fptr == NULL) break;
712+
713+
next_line = fscanf(fptr, "%s", hint_str);
714+
} while (next_line != EOF);
715+
716+
if (fptr != NULL) fclose(fptr);
717+
619718
err_out:
620-
if (cfg.info != MPI_INFO_NULL)
621-
MPI_Info_free (&(cfg.info));
622719
if (cfg.io_comm != MPI_COMM_WORLD && cfg.io_comm != MPI_COMM_NULL)
623720
MPI_Comm_free (&(cfg.io_comm));
624721
if (cfg.env_log_info != NULL)
@@ -635,16 +732,6 @@ int main (int argc, char **argv) {
635732
}
636733
}
637734

638-
timing[4] = MPI_Wtime() - timing[4];
639-
timing[0] = MPI_Wtime() - timing[0];
640-
MPI_Reduce(timing, max_t, 5, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD);
641-
if (cfg.rank == 0) {
642-
printf("init=%.2f read_decomp=%.2f e3sm_io_core=%.2f final=%.2f end-to-end=%.2f\n",
643-
max_t[1],max_t[2],max_t[3],max_t[4],max_t[0]);
644-
printf("-----------------------------------------------------------\n");
645-
printf("\n\n");
646-
}
647-
648735
MPI_Finalize ();
649736

650737
return (err < 0) ? 1 : 0;

0 commit comments

Comments
 (0)