1/*
2Copyright 2009, UCAR/Unidata
3See COPYRIGHT file for copying and redistribution conditions.
4
5This program tests netcdf-4 parallel I/O. These tests are based on the
6needs of the NASA GMAO model, and are based on some test code from
7Dennis Nadeau.
8
9$Id: tst_nc4perf.c,v 1.4 2009/08/19 15:58:57 ed Exp $
10*/
11
12#include "nc_tests.h"
13#include "err_macros.h"
14
15#define FILENAME "tst_nc4perf.nc"
16#define NDIMS1 2
17#define NDIMS2 4
18#define DIMSIZE1 40
19#define DIMSIZE2 61
20#define DIMSIZE3 3
21/*#define DIMSIZE1 540
22#define DIMSIZE2 361
23#define DIMSIZE3 72*/
24#define TIMELEN 4
25#define NUMVARS 10
26#define NUM_TRIES 2
27#define MEGABYTE 1048576
28
29/* This function creates a file with 10 2D variables, no unlimited
30 * dimension. */
31int test_pio_2d(size_t cache_size, int facc_type, int access_flagMPI_Comm comm,
32 MPI_Info info, int mpi_size, int mpi_rank,
33 size_t *chunk_size)
34{
35   double starttimeendtimewrite_time = 0, bandwidth = 0;
36   int ncid;
37   int dimids[NDIMS1];
38   size_t start[NDIMS1], count[NDIMS1];
39   float *data;
40   char file_name[NC_MAX_NAME + 1];
41   char var_name1[NUMVARS][NC_MAX_NAME + 1] = {"GWa", "JAd", "TJe", "JMa", "JMo",
42        "JQA", "AJa", "MVB", "WHH", "JTy"};
43   int varid1[NUMVARS];
44   size_t nelems_in;
45   float preemption_in;
46   int jit;
47
48   /* Create some data. */
49   if (!(data = malloc(sizeof(float) * DIMSIZE2 * DIMSIZE1 / mpi_size)))
50      return -2;
51   for (j = 0; j < DIMSIZE2j++)
52      for (i = 0; i < DIMSIZE1 / mpi_sizei++)
53  data[j * DIMSIZE1 / mpi_size + i] = (float)mpi_rank * (j + 1);
54
55   /* Get the file name. */
56   sprintf(file_name, "%s/%s", TEMP_LARGEFILENAME);
57
58   /* Set the cache size. */
59   if (nc_get_chunk_cache(NULL, &nelems_in, &preemption_in)) ERR;
60   if (nc_set_chunk_cache(cache_sizenelems_inpreemption_in)) ERR;
61
62   for (t = 0; t < NUM_TRIESt++)
63   {
64      /* Create a netcdf-4 file, opened for parallel I/O. */
65      if (nc_create_par(file_namefacc_type|NC_NETCDF4comm,
66 info, &ncid)) ERR;
67
68      /* Create two dimensions. */
69      if (nc_def_dim(ncid, "d1", DIMSIZE2, &dimids[0])) ERR;
70      if (nc_def_dim(ncid, "d2", DIMSIZE1, &dimids[1])) ERR;
71
72      /* Create our variables. */
73      for (i = 0; i < NUMVARSi++)
74      {
75  if (nc_def_var(ncidvar_name1[i], NC_INTNDIMS1,
76 dimids, &varid1[i])) ERR;
77  if (chunk_size[0])
78     if (nc_def_var_chunking(ncidvarid1[i], 0, chunk_size)) ERR;
79      }
80
81      if (nc_enddef(ncid)) ERR;
82
83      /* Set up slab for this process. */
84      start[0] = 0;
85      start[1] = mpi_rank * DIMSIZE1/mpi_size;
86      count[0] = DIMSIZE2;
87      count[1] = DIMSIZE1 / mpi_size;
88
89      /* start parallel netcdf4 */
90      for (i = 0; i < NUMVARSi++)
91  if (nc_var_par_access(ncidvarid1[i], access_flag)) ERR;
92
93      starttime = MPI_Wtime();
94
95      /* Write two dimensional float data */
96      for (i = 0; i < NUMVARSi++)
97  if (nc_put_vara_float(ncidvarid1[i], startcountdata)) ERR;
98
99      /* Close the netcdf file. */
100      if (nc_close(ncid)) ERR;
101
102      endtime = MPI_Wtime();
103      if (!mpi_rank)
104      {
105  bandwidth += ((sizeof(float) * DIMSIZE1 * DIMSIZE2 * NUMVARS) /
106        ((endtime - starttime) * 1024 * 1024)) / NUM_TRIES;
107  write_time += (endtime - starttime) / NUM_TRIES;
108      }
109   }
110   free(data);
111   if (!mpi_rank)
112   {
113      char chunk_string[NC_MAX_NAME + 1] = "";
114
115      /* What was our chunking? */
116      if (chunk_size[0])
117  sprintf(chunk_string, "%dx%d    ", (int)chunk_size[0], (int)chunk_size[1]);
118      else
119  strcat(chunk_string, "contiguous");
120
121      /* Print the results. */
122      printf("%d\t\t%s\t%s\t%d\t\t%dx%d\t\t%s\t%f\t\t%f\t\t\t%d\n", mpi_size,
123      (facc_type == NC_MPIIO ? "MPI-IO   " : "MPI-POSIX"),
124      (access_flag == NC_INDEPENDENT ? "independent" : "collective"),
125      (int)cache_size/MEGABYTEDIMSIZE1DIMSIZE2chunk_string,
126      write_timebandwidthNUM_TRIES);
127   }
128
129   /* Delete this file. */
130   remove(file_name);
131
132   return 0;
133}
134
135/* Both read and write will be tested */
136/* Case 2: create four dimensional integer data,
137   one dimension is unlimited. */
138int test_pio_4d(size_t cache_size, int facc_type, int access_flagMPI_Comm comm,
139 MPI_Info info, int mpi_size, int mpi_rank, size_t *chunk_size)
140{
141   int nciddimuids[NDIMS2], varid2[NUMVARS];
142   size_t ustart[NDIMS2], ucount[NDIMS2];
143   float *udata, *tempudata;
144   char file_name[NC_MAX_NAME + 1];
145   char var_name2[NUMVARS][NC_MAX_NAME + 1] = {"JKP", "ZTa", "MFi", "FPi", "JBu",
146        "ALi", "AJo", "USG", "RBH", "JAG"};
147   double starttimeendtimewrite_time = 0, bandwidth = 0;
148   size_t nelems_in;
149   float preemption_in;
150   int kjit;
151
152   udata = malloc(DIMSIZE3 * DIMSIZE2 * DIMSIZE1 / mpi_size * sizeof(int));
153
154   /* Create phony data. */
155   tempudata = udata;
156   for(k = 0; k < DIMSIZE3k++)
157      for(j = 0; j < DIMSIZE2j++)
158  for(i = 0; i < DIMSIZE1 / mpi_sizei++)
159  {
160     *tempudata = (float)(1 + mpi_rank) * 2 * (j + 1) * (k + 1);
161     tempudata++;
162  }
163
164   /* Get the file name. */
165   sprintf(file_name, "%s/%s", TEMP_LARGEFILENAME);
166
167   /* Set the cache size. */
168   if (nc_get_chunk_cache(NULL, &nelems_in, &preemption_in)) ERR;
169   if (nc_set_chunk_cache(cache_sizenelems_inpreemption_in)) ERR;
170
171   for (t = 0; t < NUM_TRIESt++)
172   {
173      /* Create a netcdf-4 file. */
174      if (nc_create_par(file_namefacc_type|NC_NETCDF4comminfo,
175 &ncid)) ERR;
176
177      /* Create four dimensions. */
178      if (nc_def_dim(ncid, "ud1", TIMELENdimuids)) ERR;
179      if (nc_def_dim(ncid, "ud2", DIMSIZE3, &dimuids[1])) ERR;
180      if (nc_def_dim(ncid, "ud3", DIMSIZE2, &dimuids[2])) ERR;
181      if (nc_def_dim(ncid, "ud4", DIMSIZE1, &dimuids[3])) ERR;
182
183      /* Create 10 variables. */
184      for (i = 0; i < NUMVARSi++)
185  if (nc_def_var(ncidvar_name2[i], NC_INTNDIMS2,
186 dimuids, &varid2[i])) ERR;
187
188      if (nc_enddef(ncid)) ERR;
189
190      /* Set up selection parameters */
191      ustart[0] = 0;
192      ustart[1] = 0;
193      ustart[2] = 0;
194      ustart[3] = DIMSIZE1 * mpi_rank / mpi_size;
195      ucount[0] = 1;
196      ucount[1] = DIMSIZE3;
197      ucount[2] = DIMSIZE2;
198      ucount[3] = DIMSIZE1 / mpi_size;
199
200      /* Access parallel */
201      for (i = 0; i < NUMVARSi++)
202  if (nc_var_par_access(ncidvarid2[i], access_flag)) ERR;
203
204      starttime = MPI_Wtime();
205
206      /* Write slabs of phony data. */
207      for(ustart[0] = 0; ustart[0] < TIMELENustart[0]++)
208  for (i = 0; i < NUMVARSi++)
209     if (nc_put_vara_float(ncidvarid2[i], ustartucountudata)) ERR;
210
211      /* Close the netcdf file. */
212      if (nc_close(ncid)) ERR;
213
214      endtime = MPI_Wtime();
215      if (!mpi_rank)
216      {
217  write_time += (endtime - starttime) / NUM_TRIES;
218  bandwidth += (sizeof(float) * TIMELEN * DIMSIZE1 * DIMSIZE2 * DIMSIZE3 * NUMVARS) /
219     ((endtime - starttime) * 1024 * 1024 * NUM_TRIES);
220      }
221   }
222   free(udata);
223   if (!mpi_rank)
224   {
225      char chunk_string[NC_MAX_NAME + 1] = "";
226
227      /* What was our chunking? */
228      if (chunk_size[0])
229  sprintf(chunk_string, "%dx%dx%dx%d", (int)chunk_size[0], (int)chunk_size[1],
230  (int)chunk_size[2], (int)chunk_size[3]);
231      else
232  strcat(chunk_string, "contiguous");
233
234      /* Print our results. */
235      printf("%d\t\t%s\t%s\t%d\t\t%dx%dx%dx%d\t%s\t%f\t\t%f\t\t\t%d\n", mpi_size,
236      (facc_type == NC_MPIIO ? "MPI-IO   " : "MPI-POSIX"),
237      (access_flag == NC_INDEPENDENT ? "independent" : "collective"),
238      (int)cache_size / MEGABYTETIMELENDIMSIZE3DIMSIZE2DIMSIZE1chunk_stringwrite_time,
239      bandwidthNUM_TRIES);
240   }
241
242   /* Delete this file. */
243   remove(file_name);
244
245   return 0;
246}
247
248/* Note: When the MPI-POSIX VFD is not compiled in to HDF5, the NC_MPIPOSIX
249 *      flag will be aliased to the NC_MPIIO flag within the library, and
250 *      therefore this test will exercise the aliasing, with the MPI-IO VFD,
251 *      under that configuration. -QAK
252 */
253#define NUM_MODES 2
254#define NUM_FACC 2
255#define NUM_CHUNK_COMBOS_2D 3
256#define NUM_CHUNK_COMBOS_4D 4
257#define NUM_CACHE_SIZES 3
258
259int main(int argc, char **argv)
260{
261   MPI_Comm comm = MPI_COMM_WORLD;
262   MPI_Info info = MPI_INFO_NULL;
263   int mpi_sizempi_rank;
264   int mpi_mode[NUM_MODES] = {NC_MPIIONC_MPIPOSIX};
265   int facc_type[NUM_FACC] = {NC_INDEPENDENTNC_COLLECTIVE};
266   size_t chunk_size_2d[NUM_CHUNK_COMBOS_2D][NDIMS1] = {{0, 0},
267 {DIMSIZE2DIMSIZE1},
268 {DIMSIZE2/2 + 1, DIMSIZE1 / 2}};
269   size_t chunk_size_4d[NUM_CHUNK_COMBOS_4D][NDIMS2] = {{0, 0, 0, 0},
270 {1, DIMSIZE3DIMSIZE2DIMSIZE1},
271 {TIMELEN / 2, DIMSIZE3 / 2 + 1, DIMSIZE2 / 2 + 1, DIMSIZE1 / 2},
272 {TIMELENDIMSIZE3DIMSIZE2DIMSIZE1}};
273   size_t cache_size[NUM_CACHE_SIZES] = {MEGABYTE, 32 * MEGABYTE, 64 * MEGABYTE};
274   int mfci;
275
276   /* Initialize MPI. */
277   MPI_Init(&argc, &argv);
278   MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
279   MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
280
281   /* Check for invalid number of processors. */
282   if ((float)DIMSIZE1 / mpi_size != (int)(DIMSIZE1 / mpi_size))
283   {
284      printf("%d divided by number of processors must be a whole number!\n",
285      DIMSIZE1);
286      return -1;
287   }
288
289   if (!mpi_rank)
290   {
291      printf("*** Testing parallel IO for NASA...\n");
292      printf("num_proc\tMPI mode\taccess\t\tcache (MB)\tgrid size\tchunks\tavg. write time(s)\t"
293      "avg. write bandwidth(MB/s)\tnum_tries\n");
294   }
295
296   for (i = 0; i < NUM_CACHE_SIZESi++)
297      for (m = 0; m < NUM_MODESm++)
298  for (f = 0; f < NUM_FACCf++)
299     for (c = 0; c < NUM_CHUNK_COMBOS_2Dc++)
300        if (test_pio_2d(cache_size[i], mpi_mode[m], facc_type[f], comm,
301        infompi_sizempi_rankchunk_size_2d[c])) ERR;
302
303   for (i = 0; i < NUM_CACHE_SIZESi++)
304      for (m = 0; m < NUM_MODESm++)
305  for (f = 0; f < NUM_FACCf++)
306     for (c = 0; c < NUM_CHUNK_COMBOS_4Dc++)
307        if (test_pio_4d(cache_size[i], mpi_mode[m], facc_type[f], comm,
308        infompi_sizempi_rankchunk_size_4d[c])) ERR;
309
310   if (!mpi_rank)
311      SUMMARIZE_ERR;
312   MPI_Finalize();
313
314   if (!mpi_rank)
315      FINAL_RESULTS;
316
317   return 0;
318}


HyperKWIC - Version 7.20DA executed at 11:37 on 27 Oct 2017 | Polyhedron Solutions - INTERNAL USE | COMMERCIAL (Any O/S) SN 4AKIed