/** * @ingroup PIO_def_var * * Set chunk cache netCDF files to be opened/created. * * This function only applies to netCDF-4 files. When used with netCDF * classic files, the error PIO_ENOTNC4 will be returned. * * The file chunk cache for HDF5 can be set, and will apply for any * files opened or created until the program ends, or the settings are * changed again. The cache settings apply only to the open file. They * do not persist with the file, and must be set each time the file is * opened, before it is opened, if they are to have effect. * * See the <a * href="http://www.unidata.ucar.edu/software/netcdf/docs/group__variables.html">netCDF * variable documentation</a> for details about the operation of this * function. * * @param iotype the iotype of files to be created or opened. * @param size size of file cache. * @param nelems number of elements in file cache. * @param preemption preemption setting for file cache. * * @return PIO_NOERR for success, otherwise an error code. */ int PIOc_set_chunk_cache(int iosysid, int iotype, PIO_Offset size, PIO_Offset nelems, float preemption) { int ierr; int msg; int mpierr; iosystem_desc_t *ios; file_desc_t *file; char *errstr; errstr = NULL; ierr = PIO_NOERR; msg = PIO_MSG_SET_CHUNK_CACHE; ios = pio_get_iosystem_from_id(iosysid); if(ios == NULL) return PIO_EBADID; /* if (ios->async_interface && ! ios->ioproc){ */ /* if (ios->compmaster) */ /* mpierr = MPI_Send(&msg, 1,MPI_INT, ios->ioroot, 1, ios->union_comm); */ /* mpierr = MPI_Bcast(&(file->fh),1, MPI_INT, 0, ios->intercomm); */ /* } */ switch (iotype) { #ifdef _NETCDF #ifdef _NETCDF4 case PIO_IOTYPE_NETCDF4P: ierr = nc_set_chunk_cache(size, nelems, preemption); break; case PIO_IOTYPE_NETCDF4C: if (!ios->io_rank) ierr = nc_set_chunk_cache(size, nelems, preemption); break; #endif case PIO_IOTYPE_NETCDF: ierr = PIO_ENOTNC4; break; #endif #ifdef _PNETCDF case PIO_IOTYPE_PNETCDF: ierr = PIO_ENOTNC4; break; #endif default: ierr = iotype_error(file->iotype,__FILE__,__LINE__); } /* Propogate error code to all processes. */ MPI_Bcast(&ierr, 1, MPI_INTEGER, ios->ioroot, ios->my_comm); return ierr; }
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); return 0; }
/* This function creates a file with 10 2D variables, no unlimited * dimension. */ int test_pio_2d(size_t cache_size, int facc_type, int access_flag, MPI_Comm comm, MPI_Info info, int mpi_size, int mpi_rank, size_t *chunk_size) { double starttime, endtime, write_time = 0, bandwidth = 0; int ncid; int dimids[NDIMS1]; size_t start[NDIMS1], count[NDIMS1]; float *data; char file_name[NC_MAX_NAME + 1]; char var_name1[NUMVARS][NC_MAX_NAME + 1] = {"GWa", "JAd", "TJe", "JMa", "JMo", "JQA", "AJa", "MVB", "WHH", "JTy"}; int varid1[NUMVARS]; size_t nelems_in; float preemption_in; int j, i, t; /* Create some data. */ if (!(data = malloc(sizeof(float) * DIMSIZE2 * DIMSIZE1 / mpi_size))) return -2; for (j = 0; j < DIMSIZE2; j++) for (i = 0; i < DIMSIZE1 / mpi_size; i++) data[j * DIMSIZE1 / mpi_size + i] = (float)mpi_rank * (j + 1); /* Get the file name. */ sprintf(file_name, "%s/%s", TEMP_LARGE, FILENAME); /* Set the cache size. */ if (nc_get_chunk_cache(NULL, &nelems_in, &preemption_in)) ERR; if (nc_set_chunk_cache(cache_size, nelems_in, preemption_in)) ERR; for (t = 0; t < NUM_TRIES; t++) { /* Create a netcdf-4 file, opened for parallel I/O. */ if (nc_create_par(file_name, facc_type|NC_NETCDF4, comm, info, &ncid)) ERR; /* Create two dimensions. */ if (nc_def_dim(ncid, "d1", DIMSIZE2, &dimids[0])) ERR; if (nc_def_dim(ncid, "d2", DIMSIZE1, &dimids[1])) ERR; /* Create our variables. */ for (i = 0; i < NUMVARS; i++) { if (nc_def_var(ncid, var_name1[i], NC_INT, NDIMS1, dimids, &varid1[i])) ERR; if (chunk_size[0]) if (nc_def_var_chunking(ncid, varid1[i], 0, chunk_size)) ERR; } if (nc_enddef(ncid)) ERR; /* Set up slab for this process. */ start[0] = 0; start[1] = mpi_rank * DIMSIZE1/mpi_size; count[0] = DIMSIZE2; count[1] = DIMSIZE1 / mpi_size; /* start parallel netcdf4 */ for (i = 0; i < NUMVARS; i++) if (nc_var_par_access(ncid, varid1[i], access_flag)) ERR; starttime = MPI_Wtime(); /* Write two dimensional float data */ for (i = 0; i < NUMVARS; i++) if (nc_put_vara_float(ncid, varid1[i], start, count, data)) ERR; /* Close the netcdf file. */ if (nc_close(ncid)) ERR; endtime = MPI_Wtime(); if (!mpi_rank) { bandwidth += ((sizeof(float) * DIMSIZE1 * DIMSIZE2 * NUMVARS) / ((endtime - starttime) * 1024 * 1024)) / NUM_TRIES; write_time += (endtime - starttime) / NUM_TRIES; } } free(data); if (!mpi_rank) { char chunk_string[NC_MAX_NAME + 1] = ""; /* What was our chunking? */ if (chunk_size[0]) sprintf(chunk_string, "%dx%d ", (int)chunk_size[0], (int)chunk_size[1]); else strcat(chunk_string, "contiguous"); /* Print the results. */ 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, (facc_type == NC_MPIIO ? "MPI-IO " : "MPI-POSIX"), (access_flag == NC_INDEPENDENT ? "independent" : "collective"), (int)cache_size/MEGABYTE, DIMSIZE1, DIMSIZE2, chunk_string, write_time, bandwidth, NUM_TRIES); } /* Delete this file. */ remove(file_name); return 0; }
/* Case 2: create four dimensional integer data, one dimension is unlimited. */ int test_pio_4d(size_t cache_size, int facc_type, int access_flag, MPI_Comm comm, MPI_Info info, int mpi_size, int mpi_rank, size_t *chunk_size) { int ncid, dimuids[NDIMS2], varid2[NUMVARS]; size_t ustart[NDIMS2], ucount[NDIMS2]; float *udata, *tempudata; char file_name[NC_MAX_NAME + 1]; char var_name2[NUMVARS][NC_MAX_NAME + 1] = {"JKP", "ZTa", "MFi", "FPi", "JBu", "ALi", "AJo", "USG", "RBH", "JAG"}; double starttime, endtime, write_time = 0, bandwidth = 0; size_t nelems_in; float preemption_in; int k, j, i, t; udata = malloc(DIMSIZE3 * DIMSIZE2 * DIMSIZE1 / mpi_size * sizeof(int)); /* Create phony data. */ tempudata = udata; for(k = 0; k < DIMSIZE3; k++) for(j = 0; j < DIMSIZE2; j++) for(i = 0; i < DIMSIZE1 / mpi_size; i++) { *tempudata = (float)(1 + mpi_rank) * 2 * (j + 1) * (k + 1); tempudata++; } /* Get the file name. */ sprintf(file_name, "%s/%s", TEMP_LARGE, FILENAME); /* Set the cache size. */ if (nc_get_chunk_cache(NULL, &nelems_in, &preemption_in)) ERR; if (nc_set_chunk_cache(cache_size, nelems_in, preemption_in)) ERR; for (t = 0; t < NUM_TRIES; t++) { /* Create a netcdf-4 file. */ if (nc_create_par(file_name, facc_type|NC_NETCDF4, comm, info, &ncid)) ERR; /* Create four dimensions. */ if (nc_def_dim(ncid, "ud1", TIMELEN, dimuids)) ERR; if (nc_def_dim(ncid, "ud2", DIMSIZE3, &dimuids[1])) ERR; if (nc_def_dim(ncid, "ud3", DIMSIZE2, &dimuids[2])) ERR; if (nc_def_dim(ncid, "ud4", DIMSIZE1, &dimuids[3])) ERR; /* Create 10 variables. */ for (i = 0; i < NUMVARS; i++) if (nc_def_var(ncid, var_name2[i], NC_INT, NDIMS2, dimuids, &varid2[i])) ERR; if (nc_enddef(ncid)) ERR; /* Set up selection parameters */ ustart[0] = 0; ustart[1] = 0; ustart[2] = 0; ustart[3] = DIMSIZE1 * mpi_rank / mpi_size; ucount[0] = 1; ucount[1] = DIMSIZE3; ucount[2] = DIMSIZE2; ucount[3] = DIMSIZE1 / mpi_size; /* Access parallel */ for (i = 0; i < NUMVARS; i++) if (nc_var_par_access(ncid, varid2[i], access_flag)) ERR; starttime = MPI_Wtime(); /* Write slabs of phony data. */ for(ustart[0] = 0; ustart[0] < TIMELEN; ustart[0]++) for (i = 0; i < NUMVARS; i++) if (nc_put_vara_float(ncid, varid2[i], ustart, ucount, udata)) ERR; /* Close the netcdf file. */ if (nc_close(ncid)) ERR; endtime = MPI_Wtime(); if (!mpi_rank) { write_time += (endtime - starttime) / NUM_TRIES; bandwidth += (sizeof(float) * TIMELEN * DIMSIZE1 * DIMSIZE2 * DIMSIZE3 * NUMVARS) / ((endtime - starttime) * 1024 * 1024 * NUM_TRIES); } } free(udata); if (!mpi_rank) { char chunk_string[NC_MAX_NAME + 1] = ""; /* What was our chunking? */ if (chunk_size[0]) sprintf(chunk_string, "%dx%dx%dx%d", (int)chunk_size[0], (int)chunk_size[1], (int)chunk_size[2], (int)chunk_size[3]); else strcat(chunk_string, "contiguous"); /* Print our results. */ 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, (facc_type == NC_MPIIO ? "MPI-IO " : "MPI-POSIX"), (access_flag == NC_INDEPENDENT ? "independent" : "collective"), (int)cache_size / MEGABYTE, TIMELEN, DIMSIZE3, DIMSIZE2, DIMSIZE1, chunk_string, write_time, bandwidth, NUM_TRIES); } /* Delete this file. */ remove(file_name); return 0; }
/* compare contiguous, chunked, and compressed performance */ int main(int argc, char *argv[]) { int stat; /* return status */ int ncid; /* netCDF id */ int i, j, k; int dim1id, dim2id, dim3id; int varid_g; /* varid for contiguous */ int varid_k; /* varid for chunked */ int varid_x; /* varid for compressed */ float *varxy, *varxz, *varyz; /* 2D memory slabs used for I/O */ int mm; size_t dims[] = {256, 256, 256}; /* default dim lengths */ size_t chunks[] = {32, 32, 32}; /* default chunk sizes */ size_t start[3], count[3]; float contig_time, chunked_time, compressed_time, ratio; int deflate_level = 1; /* default compression level, 9 is * better and slower. If negative, * turn on shuffle filter also. */ int shuffle = NC_NOSHUFFLE; size_t cache_size_def; size_t cache_hash_def; float cache_pre_def; size_t cache_size = 0; /* use library default */ size_t cache_hash = 0; /* use library default */ float cache_pre = -1.0f; /* use library default */ /* rank (number of dimensions) for each variable */ # define RANK_var1 3 /* variable shapes */ int var_dims[RANK_var1]; TIMING_DECLS(TMsec) ; /* From args, get parameters for timing, including variable and chunk sizes. Negative deflate level means also use shuffle filter. */ parse_args(argc, argv, &deflate_level, &shuffle, dims, chunks, &cache_size, &cache_hash, &cache_pre); /* get cache defaults, then set cache parameters that are not default */ if((stat = nc_get_chunk_cache(&cache_size_def, &cache_hash_def, &cache_pre_def))) ERR1(stat); if(cache_size == 0) cache_size = cache_size_def; if(cache_hash == 0) cache_hash = cache_hash_def; if(cache_pre == -1.0f) cache_pre = cache_pre_def; if((stat = nc_set_chunk_cache(cache_size, cache_hash, cache_pre))) ERR1(stat); printf("cache: %3.2f MBytes %ld objs %3.2f preempt, ", cache_size/1.e6, cache_hash, cache_pre); if(deflate_level == 0) { printf("uncompressed "); } else { printf("compression level %d", deflate_level); } if(shuffle == 1) { printf(", shuffled"); } printf("\n\n"); /* initialize 2D slabs for writing along each axis with phony data */ varyz = (float *) emalloc(sizeof(float) * 1 * dims[1] * dims[2]); varxz = (float *) emalloc(sizeof(float) * dims[0] * 1 * dims[2]); varxy = (float *) emalloc(sizeof(float) * dims[0] * dims[1] * 1); mm = 0; for(j = 0; j < dims[1]; j++) { for(k = 0; k < dims[2]; k++) { varyz[mm++] = k + dims[2]*j; } } mm = 0; for(i = 0; i < dims[0]; i++) { for(k = 0; k < dims[2]; k++) { varxz[mm++] = k + dims[2]*i; } } mm = 0; for(i = 0; i < dims[0]; i++) { for(j = 0; j < dims[1]; j++) { varxy[mm++] = j + dims[1]*i; } } if((stat = nc_create(FILENAME, NC_NETCDF4 | NC_CLASSIC_MODEL, &ncid))) ERR1(stat); /* define dimensions */ if((stat = nc_def_dim(ncid, "dim1", dims[0], &dim1id))) ERR1(stat); if((stat = nc_def_dim(ncid, "dim2", dims[1], &dim2id))) ERR1(stat); if((stat = nc_def_dim(ncid, "dim3", dims[2], &dim3id))) ERR1(stat); /* define variables */ var_dims[0] = dim1id; var_dims[1] = dim2id; var_dims[2] = dim3id; if((stat = nc_def_var(ncid, "var_contiguous", NC_FLOAT, RANK_var1, var_dims, &varid_g))) ERR1(stat); if((stat = nc_def_var(ncid, "var_chunked", NC_FLOAT, RANK_var1, var_dims, &varid_k))) ERR1(stat); if((stat = nc_def_var(ncid, "var_compressed", NC_FLOAT, RANK_var1, var_dims, &varid_x))) ERR1(stat); if((stat = nc_def_var_chunking(ncid, varid_g, NC_CONTIGUOUS, 0))) ERR1(stat); if((stat = nc_def_var_chunking(ncid, varid_k, NC_CHUNKED, chunks))) ERR1(stat); if((stat = nc_def_var_chunking(ncid, varid_x, NC_CHUNKED, chunks))) ERR1(stat); if (deflate_level != 0) { if((stat = nc_def_var_deflate(ncid, varid_x, shuffle, NC_COMPRESSED, deflate_level))) ERR1(stat); } /* leave define mode */ if((stat = nc_enddef (ncid))) ERR1(stat); /* write each variable one yz slab at a time */ start[0] = 0; start[1] = 0; start[2] = 0; count[0] = 1; count[1] = dims[1]; count[2] = dims[2]; sprintf(time_mess," contiguous write %3ld %3ld %3ld", 1, dims[1], dims[2]); TIMING_START ; for(i = 0; i < dims[0]; i++) { start[0] = i; if((stat = nc_put_vara(ncid, varid_g, start, count, &varyz[0]))) ERR1(stat); } TIMING_END(TMsec) ; printf("\n"); contig_time = TMsec; sprintf(time_mess," chunked write %3ld %3ld %3ld %3ld %3ld %3ld", 1, dims[1], dims[2], chunks[0], chunks[1], chunks[2]); TIMING_START ; for(i = 0; i < dims[0]; i++) { start[0] = i; if((stat = nc_put_vara(ncid, varid_k, start, count, &varyz[0]))) ERR1(stat); } TIMING_END(TMsec) ; chunked_time = TMsec; ratio = contig_time/chunked_time; if(ratio >= 1.0) printf(" %5.2g x faster\n", ratio); else printf(" %5.2g x slower\n", 1.0/ratio); sprintf(time_mess," compressed write %3ld %3ld %3ld %3ld %3ld %3ld", 1, dims[1], dims[2], chunks[0], chunks[1], chunks[2]); TIMING_START ; for(i = 0; i < dims[0]; i++) { start[0] = i; if((stat = nc_put_vara(ncid, varid_x, start, count, &varyz[0]))) ERR1(stat); } TIMING_END(TMsec) ; compressed_time = TMsec; ratio = contig_time/compressed_time; if(ratio >= 1.0) printf(" %5.2g x faster\n", ratio); else printf(" %5.2g x slower\n", 1.0/ratio); printf("\n"); /* write each variable one xz slab at a time */ start[0] = 0; start[1] = 0; start[2] = 0; count[0] = dims[0]; count[1] = 1; count[2] = dims[2]; sprintf(time_mess," contiguous write %3ld %3ld %3ld", dims[0], 1, dims[2]); TIMING_START ; for(i = 0; i < dims[1]; i++) { start[1] = i; if((stat = nc_put_vara(ncid, varid_g, start, count, &varxz[0]))) ERR1(stat); } TIMING_END(TMsec) ; printf("\n"); contig_time = TMsec; sprintf(time_mess," chunked write %3ld %3ld %3ld %3ld %3ld %3ld", dims[0], 1, dims[2], chunks[0], chunks[1], chunks[2]); TIMING_START ; for(i = 0; i < dims[1]; i++) { start[1] = i; if((stat = nc_put_vara(ncid, varid_k, start, count, &varxz[0]))) ERR1(stat); } TIMING_END(TMsec) ; chunked_time = TMsec; ratio = contig_time/chunked_time; if(ratio >= 1.0) printf(" %5.2g x faster\n", ratio); else printf(" %5.2g x slower\n", 1.0/ratio); sprintf(time_mess," compressed write %3ld %3ld %3ld %3ld %3ld %3ld", dims[0], 1, dims[2], chunks[0], chunks[1], chunks[2]); TIMING_START ; for(i = 0; i < dims[1]; i++) { start[1] = i; if((stat = nc_put_vara(ncid, varid_x, start, count, &varxz[0]))) ERR1(stat); } TIMING_END(TMsec) ; compressed_time = TMsec; ratio = contig_time/compressed_time; if(ratio >= 1.0) printf(" %5.2g x faster\n", ratio); else printf(" %5.2g x slower\n", 1.0/ratio); printf("\n"); /* write each variable one xy slab at a time */ start[0] = 0; start[1] = 0; start[2] = 0; count[0] = dims[0]; count[1] = dims[1]; count[2] = 1; sprintf(time_mess," contiguous write %3ld %3ld %3ld", dims[0], dims[1], 1); TIMING_START ; for(i = 0; i < dims[2]; i++) { start[2] = i; if((stat = nc_put_vara(ncid, varid_g, start, count, &varxy[0]))) ERR1(stat); } TIMING_END(TMsec) ; printf("\n"); contig_time = TMsec; sprintf(time_mess," chunked write %3ld %3ld %3ld %3ld %3ld %3ld", dims[0], dims[1], 1, chunks[0], chunks[1], chunks[2]); TIMING_START ; for(i = 0; i < dims[2]; i++) { start[2] = i; if((stat = nc_put_vara(ncid, varid_k, start, count, &varxy[0]))) ERR1(stat); } TIMING_END(TMsec) ; chunked_time = TMsec; ratio = contig_time/chunked_time; if(ratio >= 1.0) printf(" %5.2g x faster\n", ratio); else printf(" %5.2g x slower\n", 1.0/ratio); sprintf(time_mess," compressed write %3ld %3ld %3ld %3ld %3ld %3ld", dims[0], dims[1], 1, chunks[0], chunks[1], chunks[2]); TIMING_START ; for(i = 0; i < dims[2]; i++) { start[2] = i; if((stat = nc_put_vara(ncid, varid_x, start, count, &varxy[0]))) ERR1(stat); } TIMING_END(TMsec) ; compressed_time = TMsec; ratio = contig_time/compressed_time; if(ratio >= 1.0) printf(" %5.2g x faster\n", ratio); else printf(" %5.2g x slower\n", 1.0/ratio); printf("\n"); /* read each variable one yz slab at a time */ start[0] = 0; start[1] = 0; start[2] = 0; count[0] = 1; count[1] = dims[1]; count[2] = dims[2]; sprintf(time_mess," contiguous read %3ld %3ld %3ld", 1, dims[1], dims[2]); TIMING_START ; for(i = 0; i < dims[0]; i++) { start[0] = i; if((stat = nc_get_vara(ncid, varid_g, start, count, &varyz[0]))) ERR1(stat); } TIMING_END(TMsec) ; printf("\n"); contig_time = TMsec; sprintf(time_mess," chunked read %3ld %3ld %3ld %3ld %3ld %3ld", 1, dims[1], dims[2] , chunks[0], chunks[1], chunks[2]); TIMING_START ; for(i = 0; i < dims[0]; i++) { start[0] = i; if((stat = nc_get_vara(ncid, varid_k, start, count, &varyz[0]))) ERR1(stat); } TIMING_END(TMsec) ; chunked_time = TMsec; ratio = contig_time/chunked_time; if(ratio >= 1.0) printf(" %5.2g x faster\n", ratio); else printf(" %5.2g x slower\n", 1.0/ratio); sprintf(time_mess," compressed read %3ld %3ld %3ld %3ld %3ld %3ld", 1, dims[1], dims[2] , chunks[0], chunks[1], chunks[2]); TIMING_START ; for(i = 0; i < dims[0]; i++) { start[0] = i; if((stat = nc_get_vara(ncid, varid_x, start, count, &varyz[0]))) ERR1(stat); } TIMING_END(TMsec) ; compressed_time = TMsec; ratio = contig_time/compressed_time; if(ratio >= 1.0) printf(" %5.2g x faster\n", ratio); else printf(" %5.2g x slower\n", 1.0/ratio); printf("\n"); /* read each variable one xz slab at a time */ start[0] = 0; start[1] = 0; start[2] = 0; count[0] = dims[0]; count[1] = 1; count[2] = dims[2]; sprintf(time_mess," contiguous read %3ld %3ld %3ld", dims[0], 1, dims[2]); TIMING_START ; for(i = 0; i < dims[1]; i++) { start[1] = i; if((stat = nc_get_vara(ncid, varid_g, start, count, &varxz[0]))) ERR1(stat); } TIMING_END(TMsec) ; printf("\n"); contig_time = TMsec; sprintf(time_mess," chunked read %3ld %3ld %3ld %3ld %3ld %3ld", dims[0], 1, dims[2], chunks[0], chunks[1], chunks[2]); TIMING_START ; for(i = 0; i < dims[1]; i++) { start[1] = i; if((stat = nc_get_vara(ncid, varid_k, start, count, &varxz[0]))) ERR1(stat); } TIMING_END(TMsec) ; chunked_time = TMsec; ratio = contig_time/chunked_time; if(ratio >= 1.0) printf(" %5.2g x faster\n", ratio); else printf(" %5.2g x slower\n", 1.0/ratio); sprintf(time_mess," compressed read %3ld %3ld %3ld %3ld %3ld %3ld", dims[0], 1, dims[2], chunks[0], chunks[1], chunks[2]); TIMING_START ; for(i = 0; i < dims[1]; i++) { start[1] = i; if((stat = nc_get_vara(ncid, varid_x, start, count, &varxz[0]))) ERR1(stat); } TIMING_END(TMsec) ; compressed_time = TMsec; ratio = contig_time/compressed_time; if(ratio >= 1.0) printf(" %5.2g x faster\n", ratio); else printf(" %5.2g x slower\n", 1.0/ratio); printf("\n"); /* read variable one xy slab at a time */ start[0] = 0; start[1] = 0; start[2] = 0; count[0] = dims[0]; count[1] = dims[1]; count[2] = 1; sprintf(time_mess," contiguous read %3ld %3ld %3ld", dims[0], dims[1], 1); TIMING_START ; for(i = 0; i < dims[2]; i++) { start[2] = i; if((stat = nc_get_vara(ncid, varid_g, start, count, &varxy[0]))) ERR1(stat); } TIMING_END(TMsec) ; printf("\n"); contig_time = TMsec; sprintf(time_mess," chunked read %3ld %3ld %3ld %3ld %3ld %3ld", dims[0], dims[1], 1, chunks[0], chunks[1], chunks[2]); TIMING_START ; for(i = 0; i < dims[2]; i++) { start[2] = i; if((stat = nc_get_vara(ncid, varid_k, start, count, &varxy[0]))) ERR1(stat); } TIMING_END(TMsec) ; chunked_time = TMsec; ratio = contig_time/chunked_time; if(ratio >= 1.0) printf(" %5.2g x faster\n", ratio); else printf(" %5.2g x slower\n", 1.0/ratio); sprintf(time_mess," compressed read %3ld %3ld %3ld %3ld %3ld %3ld", dims[0], dims[1], 1, chunks[0], chunks[1], chunks[2]); TIMING_START ; for(i = 0; i < dims[2]; i++) { start[2] = i; if((stat = nc_get_vara(ncid, varid_x, start, count, &varxy[0]))) ERR1(stat); } TIMING_END(TMsec) ; compressed_time = TMsec; ratio = contig_time/compressed_time; if(ratio >= 1.0) printf(" %5.2g x faster\n", ratio); else printf(" %5.2g x slower\n", 1.0/ratio); if((stat = nc_close(ncid))) ERR1(stat); return 0; }
int test_redef(int format) { int ncid, varid, dimids[REDEF_NDIMS], dimids_in[REDEF_NDIMS]; int ndims, nvars, natts, unlimdimid; int dimids_var[REDEF_NDIMS], var_type; int cflags = 0; size_t dim_len; char dim_name[NC_MAX_NAME+1], var_name[NC_MAX_NAME+1]; float float_in; double double_out = 99E99; int int_in; unsigned char uchar_in, uchar_out = 255; short short_out = -999; nc_type xtype_in; size_t cache_size_in, cache_nelems_in; float cache_preemption_in; int ret; if (format == NC_FORMAT_64BIT) cflags |= NC_64BIT_OFFSET; else if (format == NC_FORMAT_NETCDF4_CLASSIC) cflags |= (NC_NETCDF4|NC_CLASSIC_MODEL); else if (format == NC_FORMAT_NETCDF4) cflags |= NC_NETCDF4; /* Change chunk cache. */ if (nc_set_chunk_cache(NEW_CACHE_SIZE, NEW_CACHE_NELEMS, NEW_CACHE_PREEMPTION)) ERR; /* Create a file with two dims, two vars, and two atts. */ if (nc_create(FILE_NAME, cflags|NC_CLOBBER, &ncid)) ERR; /* Retrieve the chunk cache settings, just for fun. */ if (nc_get_chunk_cache(&cache_size_in, &cache_nelems_in, &cache_preemption_in)) ERR; if (cache_size_in != NEW_CACHE_SIZE || cache_nelems_in != NEW_CACHE_NELEMS || cache_preemption_in != NEW_CACHE_PREEMPTION) ERR; /* This will fail, except for netcdf-4/hdf5, which permits any * name. */ if (format != NC_FORMAT_NETCDF4) if ((ret = nc_def_dim(ncid, REDEF_NAME_ILLEGAL, REDEF_DIM2_LEN, &dimids[1])) != NC_EBADNAME) ERR; if (nc_def_dim(ncid, REDEF_DIM1_NAME, REDEF_DIM1_LEN, &dimids[0])) ERR; if (nc_def_dim(ncid, REDEF_DIM2_NAME, REDEF_DIM2_LEN, &dimids[1])) ERR; if (nc_def_var(ncid, REDEF_VAR1_NAME, NC_INT, REDEF_NDIMS, dimids, &varid)) ERR; if (nc_def_var(ncid, REDEF_VAR2_NAME, NC_BYTE, REDEF_NDIMS, dimids, &varid)) ERR; if (nc_put_att_double(ncid, NC_GLOBAL, REDEF_ATT1_NAME, NC_DOUBLE, 1, &double_out)) ERR; if (nc_put_att_short(ncid, NC_GLOBAL, REDEF_ATT2_NAME, NC_SHORT, 1, &short_out)) ERR; /* Check it out. */ if (nc_inq(ncid, &ndims, &nvars, &natts, &unlimdimid)) ERR; if (ndims != REDEF_NDIMS || nvars != 2 || natts != 2 || unlimdimid != -1) ERR; if (nc_inq_var(ncid, 0, var_name, &xtype_in, &ndims, dimids_in, &natts)) ERR; if (strcmp(var_name, REDEF_VAR1_NAME) || xtype_in != NC_INT || ndims != REDEF_NDIMS || dimids_in[0] != dimids[0] || dimids_in[1] != dimids[1]) ERR; if (nc_inq_var(ncid, 1, var_name, &xtype_in, &ndims, dimids_in, &natts)) ERR; if (strcmp(var_name, REDEF_VAR2_NAME) || xtype_in != NC_BYTE || ndims != REDEF_NDIMS || dimids_in[0] != dimids[0] || dimids_in[1] != dimids[1]) ERR; /* Close it up. */ if (format != NC_FORMAT_NETCDF4) if (nc_enddef(ncid)) ERR; if (nc_close(ncid)) ERR; /* Reopen as read only - make sure it doesn't let us change file. */ if (nc_open(FILE_NAME, 0, &ncid)) ERR; if (nc_inq(ncid, &ndims, &nvars, &natts, &unlimdimid)) ERR; if (ndims != REDEF_NDIMS || nvars != 2 || natts != 2 || unlimdimid != -1) ERR; if (nc_inq_var(ncid, 0, var_name, &xtype_in, &ndims, dimids_in, &natts)) ERR; if (strcmp(var_name, REDEF_VAR1_NAME) || xtype_in != NC_INT || ndims != REDEF_NDIMS || dimids_in[0] != dimids[0] || dimids_in[1] != dimids[1]) ERR; if (nc_inq_var(ncid, 1, var_name, &xtype_in, &ndims, dimids_in, &natts)) ERR; if (strcmp(var_name, REDEF_VAR2_NAME) || xtype_in != NC_BYTE || ndims != REDEF_NDIMS || dimids_in[0] != dimids[0] || dimids_in[1] != dimids[1]) ERR; /* This will fail. */ ret = nc_def_var(ncid, REDEF_VAR3_NAME, NC_UBYTE, REDEF_NDIMS, dimids, &varid); if(format == NC_FORMAT_NETCDF4) { if(ret != NC_EPERM) { ERR; } } else { if(ret != NC_ENOTINDEFINE) { ERR; } } /* This will fail. */ if (!nc_put_att_uchar(ncid, NC_GLOBAL, REDEF_ATT3_NAME, NC_CHAR, 1, &uchar_out)) ERR; if (nc_close(ncid)) ERR; /* Make sure we can't redef a file opened for NOWRITE. */ if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR; if (nc_redef(ncid) != NC_EPERM) ERR; /* Check it out again. */ if (nc_inq(ncid, &ndims, &nvars, &natts, &unlimdimid)) ERR; if (ndims != REDEF_NDIMS || nvars != 2 || natts != 2 || unlimdimid != -1) ERR; if (nc_inq_var(ncid, 0, var_name, &xtype_in, &ndims, dimids_in, &natts)) ERR; if (strcmp(var_name, REDEF_VAR1_NAME) || xtype_in != NC_INT || ndims != REDEF_NDIMS || dimids_in[0] != dimids[0] || dimids_in[1] != dimids[1]) ERR; if (nc_inq_var(ncid, 1, var_name, &xtype_in, &ndims, dimids_in, &natts)) ERR; if (strcmp(var_name, REDEF_VAR2_NAME) || xtype_in != NC_BYTE || ndims != REDEF_NDIMS || dimids_in[0] != dimids[0] || dimids_in[1] != dimids[1]) ERR; if (nc_close(ncid)) ERR; /* Reopen the file and check it, add a variable and attribute. */ if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR; /* Check it out. */ if (nc_inq(ncid, &ndims, &nvars, &natts, &unlimdimid)) ERR; if (ndims != REDEF_NDIMS || nvars != 2 || natts != 2 || unlimdimid != -1) ERR; /* Add var. */ if ((format != NC_FORMAT_NETCDF4) && nc_redef(ncid)) ERR; if (nc_def_var(ncid, REDEF_VAR3_NAME, NC_BYTE, REDEF_NDIMS, dimids, &varid)) ERR; /* Add att. */ ret = nc_put_att_uchar(ncid, NC_GLOBAL, REDEF_ATT3_NAME, NC_BYTE, 1, &uchar_out); if (format != NC_FORMAT_NETCDF4 && ret) ERR; else if (format == NC_FORMAT_NETCDF4 && ret != NC_ERANGE) ERR; /* Check it out. */ if (nc_inq(ncid, &ndims, &nvars, &natts, &unlimdimid)) ERR; if (ndims != REDEF_NDIMS || nvars != 3 || natts != 3 || unlimdimid != -1) ERR; if (nc_inq_var(ncid, 0, var_name, &xtype_in, &ndims, dimids_in, &natts)) ERR; if (strcmp(var_name, REDEF_VAR1_NAME) || xtype_in != NC_INT || ndims != REDEF_NDIMS || dimids_in[0] != dimids[0] || dimids_in[1] != dimids[1]) ERR; if (nc_inq_var(ncid, 1, var_name, &xtype_in, &ndims, dimids_in, &natts)) ERR; if (strcmp(var_name, REDEF_VAR2_NAME) || xtype_in != NC_BYTE || ndims != REDEF_NDIMS || dimids_in[0] != dimids[0] || dimids_in[1] != dimids[1]) ERR; if (nc_inq_var(ncid, 2, var_name, &var_type, &ndims, dimids_var, &natts)) ERR; if (ndims != REDEF_NDIMS || strcmp(var_name, REDEF_VAR3_NAME) || var_type != NC_BYTE || natts != 0) ERR; if (nc_close(ncid)) ERR; /* Reopen it and check each dim, var, and att. */ if (nc_open(FILE_NAME, 0, &ncid)) ERR; if (nc_inq_dim(ncid, 0, dim_name, &dim_len)) ERR; if (dim_len != REDEF_DIM1_LEN || strcmp(dim_name, REDEF_DIM1_NAME)) ERR; if (nc_inq_dim(ncid, 1, dim_name, &dim_len)) ERR; if (dim_len != REDEF_DIM2_LEN || strcmp(dim_name, REDEF_DIM2_NAME)) ERR; if (nc_inq_var(ncid, 0, var_name, &var_type, &ndims, dimids_var, &natts)) ERR; if (ndims != REDEF_NDIMS || strcmp(var_name, REDEF_VAR1_NAME) || var_type != NC_INT || natts != 0) ERR; if (nc_inq_var(ncid, 1, var_name, &var_type, &ndims, dimids_var, &natts)) ERR; if (ndims != REDEF_NDIMS || strcmp(var_name, REDEF_VAR2_NAME) || var_type != NC_BYTE || natts != 0) ERR; if (nc_inq_var(ncid, 2, var_name, &var_type, &ndims, dimids_var, &natts)) ERR; if (ndims != REDEF_NDIMS || strcmp(var_name, REDEF_VAR3_NAME) || var_type != NC_BYTE || natts != 0) ERR; if (nc_get_att_float(ncid, NC_GLOBAL, REDEF_ATT1_NAME, &float_in) != NC_ERANGE) ERR; if (nc_get_att_int(ncid, NC_GLOBAL, REDEF_ATT2_NAME, &int_in)) ERR; if (int_in != short_out) ERR; ret = nc_get_att_uchar(ncid, NC_GLOBAL, REDEF_ATT3_NAME, &uchar_in); if (format == NC_FORMAT_NETCDF4) { if (ret != NC_ERANGE) ERR; } else if (ret) ERR; if (uchar_in != uchar_out) ERR; if (nc_close(ncid)) ERR; return NC_NOERR; }
int main(int argc, char **argv) { printf("\n*** Testing netcdf-4 file functions, some more.\n"); last_sbrk = sbrk(0); printf("*** testing lots of open files...\n"); { #define NUM_TRIES 6 int *ncid_in; int mem_used, mem_used2; /* int mem_per_file; */ int num_files[NUM_TRIES] = {1, 5, 10, 20, 35, 50}; char file_name[NUM_TRIES][NC_MAX_NAME + 1]; int num_vars[NUM_TRIES]; size_t cache_size[NUM_TRIES]; int mode[NUM_TRIES]; char mode_name[NUM_TRIES][8]; int ndims[NUM_TRIES]; int dim_len[NUM_TRIES][MAX_DIMS]; int dim_4d[MAX_DIMS] = {NC_UNLIMITED, 10, 100, 100}; char dimstr[30]; char chunkstr[30]; int num_recs[NUM_TRIES] = {1, 1, 1, 1, 1, 1}; struct timeval start_time, end_time, diff_time; struct timeval close_start_time, close_end_time, close_diff_time; int open_us, close_us, create_us; size_t chunksize[MAX_DIMS]; int storage; int d, f, t; printf("dims\t\tchunks\t\tformat\tnum_files\tcache(kb)\tnum_vars\tmem(kb)\t" "open_time(us/file)\tclose_time(us/file)\tcreate_time(us/file)\n"); for (t = 0; t < NUM_TRIES; t++) { strcpy(mode_name[t], "netcdf4"); mode[t] = NC_NETCDF4; cache_size[t] = 16000000; num_vars[t] = 10; ndims[t] = 4; for (d = 0; d < ndims[t]; d++) dim_len[t][d] = dim_4d[d]; /* Create sample files. */ if (gettimeofday(&start_time, NULL)) ERR; for (f = 0; f < num_files[t]; f++) { /* Set up filename. */ sprintf(file_name[t], "tst_files2_%d_%d.nc", t, f); if (create_sample_file(file_name[t], ndims[t], dim_len[t], num_vars[t], mode[t], num_recs[t])) ERR; /* How long did it take? */ if (gettimeofday(&end_time, NULL)) ERR; if (nc4_timeval_subtract(&diff_time, &end_time, &start_time)) ERR; create_us = ((int)diff_time.tv_sec * MILLION + (int)diff_time.tv_usec) / num_files[t]; } /* /\* Change the cache settings. *\/ */ /* if (nc_set_chunk_cache(cache_size[t], 20000, .75)) ERR; */ /* We need storage for an array of ncids. */ if (!(ncid_in = malloc(num_files[t] * sizeof(int)))) ERR; /* How much memory is in use now? */ if (get_mem_used1(&mem_used)) ERR; /* Open the first file to get chunksizes. */ if (gettimeofday(&start_time, NULL)) ERR; if (nc_open(file_name[t], 0, &ncid_in[0])) ERR; if (nc_inq_var_chunking(ncid_in[0], 0, &storage, chunksize)) ERR; /* Now reopen this file a large number of times. */ for (f = 1; f < num_files[t]; f++) if (nc_open(file_name[t], 0, &ncid_in[f])) ERR_RET; /* How long did it take per file? */ if (gettimeofday(&end_time, NULL)) ERR; if (nc4_timeval_subtract(&diff_time, &end_time, &start_time)) ERR; open_us = ((int)diff_time.tv_sec * MILLION + (int)diff_time.tv_usec) / num_files[t]; /* How much memory is in use by this process now? */ if (get_mem_used1(&mem_used2)) ERR; /* Close all netcdf files. */ if (gettimeofday(&close_start_time, NULL)) ERR; for (f = 0; f < num_files[t]; f++) if (nc_close(ncid_in[f])) ERR_RET; /* How long did it take to close all files? */ if (gettimeofday(&close_end_time, NULL)) ERR; if (nc4_timeval_subtract(&close_diff_time, &close_end_time, &close_start_time)) ERR; close_us = ((int)close_diff_time.tv_sec * MILLION + (int)close_diff_time.tv_usec) / num_files[t]; /* We're done with this. */ free(ncid_in); /* How much memory was used for each open file? */ /* mem_per_file = mem_used2/num_files[t]; */ /* Prepare the dimensions string. */ if (ndims[t] == MAX_DIMS) sprintf(dimstr, "%dx%dx%dx%d", dim_len[t][0], dim_len[t][1], dim_len[t][2], dim_len[t][3]); else sprintf(dimstr, "%dx%dx%d", dim_len[t][0], dim_len[t][1], dim_len[t][2]); /* Prepare the chunksize string. */ if (storage == NC_CHUNKED) { if (ndims[t] == MAX_DIMS) sprintf(chunkstr, "%dx%dx%dx%d", (int)chunksize[0], (int)chunksize[1], (int)chunksize[2], (int)chunksize[3]); else sprintf(chunkstr, "%dx%dx%d", (int)chunksize[0], (int)chunksize[1], (int)chunksize[2]); } else strcpy(chunkstr, "contig "); /* Output results. */ printf("%s\t%s\t%s\t%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d\n", dimstr, chunkstr, mode_name[t], num_files[t], (int)(cache_size[t]/1024), num_vars[t], mem_used2, open_us, close_us, create_us); } } SUMMARIZE_ERR; printf("Test for memory consumption...\n"); { #define NUM_TRIES_100 100 int ncid, i; int mem_used, mem_used1, mem_used2; get_mem_used2(&mem_used); mem_used1 = mem_used; mem_used2 = mem_used; printf("start: memuse= %d\t%d\t%d \n",mem_used, mem_used1, mem_used2); printf("bef_open\taft_open\taft_close\tused_open\tused_closed\n"); for (i=0; i < NUM_TRIES_100; i++) { /* Open the file. NC_NOWRITE tells netCDF we want read-only access * to the file.*/ get_mem_used2(&mem_used); nc_set_chunk_cache(10,10,.5); if (nc_open(FILE_NAME, NC_NOWRITE, &ncid)) ERR; get_mem_used2(&mem_used1); /* Close the file, freeing all resources. ???? */ if (nc_close(ncid)) ERR; get_mem_used2(&mem_used2); if (mem_used2 - mem_used) printf("try %d - %d\t\t%d\t\t%d\t\t%d\t\t%d \n", i, mem_used, mem_used1, mem_used2, mem_used1 - mem_used, mem_used2 - mem_used); } } SUMMARIZE_ERR; FINAL_RESULTS; }