/* Copyright 2018, UCAR/Unidata See COPYRIGHT file for copying and redistribution conditions. This program tests netcdf-4 performance with some AR-4 3D data. Ed Hartnett */ #include #include "err_macros.h" #include #include #include /* Prototype from tst_utils.c. */ int nc4_timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y); /* From the data file we are using: netcdf pr_A1.20C3M_8.CCSM.atmm.1870-01_cat_1999-12 { dimensions: lon = 256 ; lat = 128 ; bnds = 2 ; time = UNLIMITED ; // (1560 currently) variables: double lon_bnds(lon, bnds) ; double lat_bnds(lat, bnds) ; double time_bnds(time, bnds) ; double time(time) ; time:calendar = "noleap" ; time:standard_name = "time" ; time:axis = "T" ; time:units = "days since 0000-1-1" ; time:bounds = "time_bnds" ; time:long_name = "time" ; double lat(lat) ; lat:axis = "Y" ; lat:standard_name = "latitude" ; lat:bounds = "lat_bnds" ; lat:long_name = "latitude" ; lat:units = "degrees_north" ; double lon(lon) ; lon:axis = "X" ; lon:standard_name = "longitude" ; lon:bounds = "lon_bnds" ; lon:long_name = "longitude" ; lon:units = "degrees_east" ; float pr(time, lat, lon) ; pr:comment = "Created using NCL code CCSM_atmm_2cf.ncl on\n", " machine mineral" ; pr:missing_value = 1.e+20f ; pr:_FillValue = 1.e+20f ; pr:cell_methods = "time: mean (interval: 1 month)" ; pr:history = "(PRECC+PRECL)*r[h2o]" ; pr:original_units = "m-1 s-1" ; pr:original_name = "PRECC, PRECL" ; pr:standard_name = "precipitation_flux" ; pr:units = "kg m-2 s-1" ; pr:long_name = "precipitation_flux" ; pr:cell_method = "time: mean" ; */ #define USAGE "\ [-v] Verbose\n\ [-h] Print output header\n\ [-t] Do a time-series read\n\ [-c CACHE_SIZE] Set the HDF5 chunk cache to this size before read\n\ file Name of netCDF file\n" static void usage(void) { fprintf(stderr, "tst_ar4 -v -h -t -c CACHE_SIZE file\n%s", USAGE); } #define NDIMS3 3 #define DATA_VAR_NAME "pr" #define NUM_CACHE_TRIES 1 #define LON_DIMID 0 #define LAT_DIMID 1 #define BNDS_DIMID 2 #define TIME_DIMID 3 #define LON_LEN 256 #define LAT_LEN 128 #define BNDS_LEN 2 #define TIME_LEN 1560 #define NUM_TS 1 int main(int argc, char **argv) { extern int optind; extern int opterr; extern char *optarg; int c, header = 0, verbose = 0, timeseries = 0; int ncid, varid, storage; char name_in[NC_MAX_NAME + 1]; size_t len; size_t cs[NDIMS3] = {0, 0, 0}; int cache = MEGABYTE; int ndims, dimid[NDIMS3]; float hor_data[LAT_LEN * LON_LEN]; int read_1_us, avg_read_us; float ts_data[TIME_LEN]; size_t start[NDIMS3], count[NDIMS3]; int deflate, shuffle, deflate_level; struct timeval start_time, end_time, diff_time; while ((c = getopt(argc, argv, "vhtc:")) != EOF) switch(c) { case 'v': verbose++; break; case 'h': header++; break; case 't': timeseries++; break; case 'c': sscanf(optarg, "%d", &cache); break; case '?': usage(); return 1; } argc -= optind; argv += optind; /* If no file arguments left, report and exit */ if (argc < 1) { printf("no file specified\n"); return 0; } /* Print the header if desired. */ if (header) { printf("cs[0]\tcs[1]\tcs[2]\tcache(MB)\tdeflate\tshuffle"); if (timeseries) printf("\t1st_read_ser(us)\tavg_read_ser(us)\n"); else printf("\t1st_read_hor(us)\tavg_read_hor(us)\n"); } #define PREEMPTION .75 /* Also tried NELEMS of 2500009*/ #define NELEMS 7919 if (nc_set_chunk_cache(cache, NELEMS, PREEMPTION)) ERR; if (nc_open(argv[0], 0, &ncid)) ERR; /* Check to make sure that all the dimension information is * correct. */ if (nc_inq_varid(ncid, DATA_VAR_NAME, &varid)) ERR; if (nc_inq_dim(ncid, LON_DIMID, name_in, &len)) ERR; if (strcmp(name_in, "lon") || len != LON_LEN) ERR; if (nc_inq_dim(ncid, LAT_DIMID, name_in, &len)) ERR; if (strcmp(name_in, "lat") || len != LAT_LEN) ERR; if (nc_inq_dim(ncid, BNDS_DIMID, name_in, &len)) ERR; if (strcmp(name_in, "bnds") || len != BNDS_LEN) ERR; if (nc_inq_dim(ncid, TIME_DIMID, name_in, &len)) ERR; if (strcmp(name_in, "time") || len != TIME_LEN) ERR; if (nc_inq_var(ncid, varid, NULL, NULL, &ndims, dimid, NULL)) ERR; if (ndims != NDIMS3 || dimid[0] != TIME_DIMID || dimid[1] != LAT_DIMID || dimid[2] != LON_DIMID) ERR; /* Get info about the main data var. */ if (nc_inq_var_chunking(ncid, varid, &storage, cs)) ERR; if (nc_inq_var_deflate(ncid, varid, &shuffle, &deflate, &deflate_level)) ERR; if (timeseries) { /* Read the var as a time series. */ start[0] = 0; start[1] = 0; start[2] = 0; count[0] = TIME_LEN; count[1] = 1; count[2] = 1; /* Read the first timeseries. */ if (gettimeofday(&start_time, NULL)) ERR; if (nc_get_vara_float(ncid, varid, start, count, ts_data)) ERR_RET; if (gettimeofday(&end_time, NULL)) ERR; if (nc4_timeval_subtract(&diff_time, &end_time, &start_time)) ERR; read_1_us = (int)diff_time.tv_sec * MILLION + (int)diff_time.tv_usec; /* Read all the rest. */ if (gettimeofday(&start_time, NULL)) ERR; for (start[1] = 0; start[1] < LAT_LEN; start[1]++) for (start[2] = 1; start[2] < LON_LEN; start[2]++) if (nc_get_vara_float(ncid, varid, start, count, ts_data)) ERR_RET; if (gettimeofday(&end_time, NULL)) ERR; if (nc4_timeval_subtract(&diff_time, &end_time, &start_time)) ERR; avg_read_us = ((int)diff_time.tv_sec * MILLION + (int)diff_time.tv_usec + read_1_us) / (LAT_LEN * LON_LEN); } else { /* Read the data variable in horizontal slices. */ start[0] = 0; start[1] = 0; start[2] = 0; count[0] = 1; count[1] = LAT_LEN; count[2] = LON_LEN; /* Read (and time) the first one. */ if (gettimeofday(&start_time, NULL)) ERR; if (nc_get_vara_float(ncid, varid, start, count, hor_data)) ERR_RET; if (gettimeofday(&end_time, NULL)) ERR; if (nc4_timeval_subtract(&diff_time, &end_time, &start_time)) ERR; read_1_us = (int)diff_time.tv_sec * MILLION + (int)diff_time.tv_usec; /* Read (and time) all the rest. */ if (gettimeofday(&start_time, NULL)) ERR; for (start[0] = 1; start[0] < TIME_LEN; start[0]++) if (nc_get_vara_float(ncid, varid, start, count, hor_data)) ERR_RET; if (gettimeofday(&end_time, NULL)) ERR; if (nc4_timeval_subtract(&diff_time, &end_time, &start_time)) ERR; avg_read_us = ((int)diff_time.tv_sec * MILLION + (int)diff_time.tv_usec + read_1_us) / TIME_LEN; } /* Close file. */ if (nc_close(ncid)) ERR; /* Print results. */ printf("%d\t%d\t%d\t%.1f\t\t%d\t%d\t\t", (int)cs[0], (int)cs[1], (int)cs[2], (storage == NC_CHUNKED) ? (cache/(float)MEGABYTE) : 0, deflate, shuffle); if (timeseries) printf("%d\t\t%d\n", (int)read_1_us, (int)avg_read_us); else printf("%d\t\t%d\n", (int)read_1_us, (int)avg_read_us); FINAL_RESULTS; }