netcdf-c/nc_test4/tst_chunks2.c
2024-03-12 16:13:40 +00:00

457 lines
15 KiB
C

/* This is part of the netCDF package.
Copyright 2018 University Corporation for Atmospheric Research/Unidata
See COPYRIGHT file for conditions of use.
Test netcdf-4 chunking.
*/
#include <nc_tests.h>
#include "err_macros.h"
#define FILE_NAME "tst_chunks2.nc"
#define MAX_WASTE 25.0
#define NUM_RANDOM_TESTS 3
#define NDIMS3 3
/* Calculate the waste of the chunking. A waste of 10% means the
* chunked data is 10% larger then the unchunked data. */
static int
calculate_waste(int ndims, size_t *dimlen, size_t *chunksize, float *waste)
{
int d;
float chunked = 1, unchunked = 1;
size_t *num_chunks;
assert(waste && dimlen && chunksize && ndims);
if (!(num_chunks = calloc((size_t)ndims, sizeof(size_t)))) ERR;
#ifdef PRINT_CHUNK_WASTE_REPORT
printf("\n");
#endif
/* Caclulate the total space taken up by the chunked data. */
for (d = 0; d < ndims; d++)
{
/* How many chunks along this dimension are required to hold all the data? */
for (num_chunks[d] = 0; (num_chunks[d] * chunksize[d]) < (dimlen[d] ? dimlen[d] : 1);
num_chunks[d]++)
;
chunked *= (float)(num_chunks[d] * chunksize[d]);
}
/* Calculate the minimum space required for this data
* (i.e. unchunked) or one record of it. */
for (d = 0; d < ndims; d++)
unchunked *= (float)(dimlen[d] ? dimlen[d] : 1);
#ifdef PRINT_CHUNK_WASTE_REPORT
printf("size for unchunked %g elements; size for chunked %g elements\n",
unchunked, chunked);
#endif
/* Percent of the chunked file that is wasted space. */
*waste = ((float)(chunked - unchunked) / (float)chunked) * 100.0f;
#ifdef PRINT_CHUNK_WASTE_REPORT
printf("\ndimlen\tchunksize\tnum_chunks\n");
size_t chunk_size = 1;
for (d = 0; d < ndims; d++)
{
printf("%ld\t%ld\t\t%ld\n", (long int)dimlen[d], (long int)chunksize[d],
(long int)num_chunks[d]);
chunk_size *= chunksize[d];
}
printf("size of chunk: %ld elements; wasted space: %2.2f percent\n",
(long int)chunk_size, *waste);
#endif
free(num_chunks);
return 0;
}
int
main(int argc, char **argv)
{
printf("\n*** Testing netcdf-4 variable chunking.\n");
printf("**** testing default chunksizes...");
{
#define NDIMS3 3
#define NUM_VARS 1
#define Y_NAME "y"
#define X_NAME "x"
#define Z_NAME "z"
#define VAR_NAME_JOE "joe"
#define XDIM_LEN 2
#define YDIM_LEN 5
#define ZDIM_LEN 3000
int varid, ncid, dims[NDIMS3], dims_in[NDIMS3];
int ndims, nvars, ngatts, unlimdimid, natts;
char name_in[NC_MAX_NAME + 1];
nc_type type_in;
size_t len_in[NDIMS3];
int storage = 0;
size_t chunksizes[NDIMS3];
float waste = 0;
/* Create a file with 3D var, turn on chunking, but don't provide chunksizes. */
if (nc_create(FILE_NAME, NC_NETCDF4 | NC_CLOBBER, &ncid)) ERR;
if (nc_def_dim(ncid, X_NAME, XDIM_LEN, &dims[0])) ERR;
if (nc_def_dim(ncid, Y_NAME, YDIM_LEN, &dims[1])) ERR;
if (nc_def_dim(ncid, Z_NAME, ZDIM_LEN, &dims[2])) ERR;
if (nc_def_var(ncid, VAR_NAME_JOE, NC_FLOAT, NDIMS3, dims, &varid)) ERR;
if (nc_def_var_chunking(ncid, 0, NC_CHUNKED, NULL)) ERR;
/* Check it out. */
if (nc_inq(ncid, &ndims, &nvars, &ngatts, &unlimdimid)) ERR;
if (nvars != NUM_VARS || ndims != NDIMS3 || ngatts != 0 || unlimdimid != -1) ERR;
if (nc_inq_var(ncid, 0, name_in, &type_in, &ndims, dims_in, &natts)) ERR;
if (strcmp(name_in, VAR_NAME_JOE) || type_in != NC_FLOAT || ndims != NDIMS3 ||
dims_in[0] != dims[0] || dims_in[1] != dims[1] || dims_in[2] != dims[2] || natts != 0) ERR;
if (nc_inq_dim(ncid, 0, name_in, &len_in[0])) ERR;
if (strcmp(name_in, X_NAME) || len_in[0] != XDIM_LEN) ERR;
if (nc_inq_dim(ncid, 1, name_in, &len_in[1])) ERR;
if (strcmp(name_in, Y_NAME) || len_in[1] != YDIM_LEN) ERR;
if (nc_inq_dim(ncid, 2, name_in, &len_in[2])) ERR;
if (strcmp(name_in, Z_NAME) || len_in[2] != ZDIM_LEN) ERR;
if (nc_inq_var_chunking(ncid, 0, &storage, chunksizes)) ERR;
if (storage != NC_CHUNKED) ERR;
if (nc_close(ncid)) ERR;
/* Open the file and check again. */
if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
if (nc_inq(ncid, &ndims, &nvars, &ngatts, &unlimdimid)) ERR;
if (nvars != NUM_VARS || ndims != NDIMS3 || ngatts != 0 || unlimdimid != -1) ERR;
if (nc_inq_var(ncid, 0, name_in, &type_in, &ndims, dims_in, &natts)) ERR;
if (strcmp(name_in, VAR_NAME_JOE) || type_in != NC_FLOAT || ndims != NDIMS3 ||
dims_in[0] != dims[0] || dims_in[1] != dims[1] || dims_in[2] != dims[2] || natts != 0) ERR;
if (nc_inq_dim(ncid, 0, name_in, &len_in[0])) ERR;
if (strcmp(name_in, X_NAME) || len_in[0] != XDIM_LEN) ERR;
if (nc_inq_dim(ncid, 1, name_in, &len_in[1])) ERR;
if (strcmp(name_in, Y_NAME) || len_in[1] != YDIM_LEN) ERR;
if (nc_inq_dim(ncid, 2, name_in, &len_in[2])) ERR;
if (strcmp(name_in, Z_NAME) || len_in[2] != ZDIM_LEN) ERR;
if (nc_inq_var_chunking(ncid, 0, &storage, chunksizes)) ERR;
if (storage != NC_CHUNKED) ERR;
if (calculate_waste(NDIMS3, len_in, chunksizes, &waste)) ERR;
/*if (waste > MAX_WASTE) ERR;*/
if (nc_close(ncid)) ERR;
}
SUMMARIZE_ERR;
printf("**** testing default chunksizes some more for a 3D var...");
{
#define NDIMS3 3
#define VAR_NAME "op-amp"
int varid, ncid;
int dimids[NDIMS3];
size_t dim_len[NDIMS3] = {1, 11, 152750};
int storage = 0;
size_t chunksizes[NDIMS3];
int d;
char dim_name[NC_MAX_NAME + 1];
float waste;
if (nc_create(FILE_NAME, NC_NETCDF4 | NC_CLOBBER, &ncid)) ERR;
/* Create a few dimensions. */
for (d = 0; d < NDIMS3; d++)
{
snprintf(dim_name, sizeof(dim_name), "dim_%d", d);
if (nc_def_dim(ncid, dim_name, dim_len[d], &dimids[d])) ERR;
}
/* Define a var with these dimensions, and turn on chunking. */
if (nc_def_var(ncid, VAR_NAME, NC_FLOAT, NDIMS3, dimids, &varid)) ERR;
if (nc_def_var_chunking(ncid, varid, NC_CHUNKED, NULL)) ERR;
/* Check how default chunking worked. */
if (nc_inq_var_chunking(ncid, varid, &storage, chunksizes)) ERR;
if (storage != NC_CHUNKED) ERR;
if (calculate_waste(NDIMS3, dim_len, chunksizes, &waste)) ERR;
/* if (waste > MAX_WASTE) ERR;*/
if (nc_close(ncid)) ERR;
/* Open the file and check. */
if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
if (nc_close(ncid)) ERR;
}
SUMMARIZE_ERR;
printf("**** testing default chunksizes even more for a 3D var...");
{
int varid, ncid;
int dimids[NDIMS3];
size_t dim_len[NDIMS3] = {1804289383, 846930886, 1681692777};
int storage = 0;
size_t chunksizes[NDIMS3];
int d;
char dim_name[NC_MAX_NAME + 1];
float waste;
if (nc_create(FILE_NAME, NC_NETCDF4 | NC_CLOBBER, &ncid)) ERR;
/* Create a few dimensions. */
for (d = 0; d < NDIMS3; d++)
{
snprintf(dim_name, sizeof(dim_name), "dim_%d", d);
if (nc_def_dim(ncid, dim_name, dim_len[d], &dimids[d])) ERR;
}
/* Define a var with these dimensions, and turn on chunking. */
if (nc_def_var(ncid, VAR_NAME, NC_FLOAT, NDIMS3, dimids, &varid)) ERR;
if (nc_def_var_chunking(ncid, varid, NC_CHUNKED, NULL)) ERR;
/* Check how default chunking worked. */
if (nc_inq_var_chunking(ncid, varid, &storage, chunksizes)) ERR;
if (storage != NC_CHUNKED) ERR;
if (calculate_waste(NDIMS3, dim_len, chunksizes, &waste)) ERR;
/* if (waste > MAX_WASTE) ERR;*/
if (nc_close(ncid)) ERR;
/* Open the file and check. */
if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
if (nc_close(ncid)) ERR;
}
SUMMARIZE_ERR;
printf("**** testing default chunksizes even even more for a 3D var...");
{
int varid, ncid;
int dimids[NDIMS3];
size_t dim_len[NDIMS3] = {1714636915, 1957747793, 424238335};
int storage = 0;
size_t chunksizes[NDIMS3];
int d;
char dim_name[NC_MAX_NAME + 1];
float waste;
if (nc_create(FILE_NAME, NC_NETCDF4 | NC_CLOBBER, &ncid)) ERR;
/* Create a few dimensions. */
for (d = 0; d < NDIMS3; d++)
{
snprintf(dim_name, sizeof(dim_name), "dim_%d", d);
if (nc_def_dim(ncid, dim_name, dim_len[d], &dimids[d])) ERR;
}
/* Define a var with these dimensions, and turn on chunking. */
if (nc_def_var(ncid, VAR_NAME, NC_FLOAT, NDIMS3, dimids, &varid)) ERR;
if (nc_def_var_chunking(ncid, varid, NC_CHUNKED, NULL)) ERR;
/* Check how default chunking worked. */
if (nc_inq_var_chunking(ncid, varid, &storage, chunksizes)) ERR;
if (storage != NC_CHUNKED) ERR;
if (calculate_waste(NDIMS3, dim_len, chunksizes, &waste)) ERR;
/* if (waste > MAX_WASTE) ERR;*/
if (nc_close(ncid)) ERR;
/* Open the file and check. */
if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
if (nc_close(ncid)) ERR;
}
SUMMARIZE_ERR;
printf("**** testing default chunksizes some more for a 3D var...");
{
#define NDIMS3 3
#define VAR_NAME "op-amp"
int varid, ncid;
int dimids[NDIMS3];
size_t dim_len[NDIMS3] = {1967513926, 1365180540, 426};
int storage = 0;
size_t chunksizes[NDIMS3];
int d;
char dim_name[NC_MAX_NAME + 1];
float waste;
if (nc_create(FILE_NAME, NC_NETCDF4 | NC_CLOBBER, &ncid)) ERR;
/* Create a few dimensions. */
for (d = 0; d < NDIMS3; d++)
{
snprintf(dim_name, sizeof(dim_name), "dim_%d", d);
if (nc_def_dim(ncid, dim_name, dim_len[d], &dimids[d])) ERR;
}
/* Define a var with these dimensions, and turn on chunking. */
if (nc_def_var(ncid, VAR_NAME, NC_FLOAT, NDIMS3, dimids, &varid)) ERR;
if (nc_def_var_chunking(ncid, varid, NC_CHUNKED, NULL)) ERR;
/* Check how default chunking worked. */
if (nc_inq_var_chunking(ncid, varid, &storage, chunksizes)) ERR;
if (storage != NC_CHUNKED) ERR;
if (calculate_waste(NDIMS3, dim_len, chunksizes, &waste)) ERR;
/* if (waste > MAX_WASTE) ERR;*/
if (nc_close(ncid)) ERR;
/* Open the file and check. */
if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
if (nc_close(ncid)) ERR;
}
SUMMARIZE_ERR;
printf("**** testing default chunksizes for very large 3D var...");
{
#define NDIMS3 3
int varid, ncid;
int dimids[NDIMS3];
size_t dim_len[NDIMS3] = {1804289383, 846930886, 1681692777};
int storage = 0;
size_t chunksizes[NDIMS3];
int d;
char dim_name[NC_MAX_NAME + 1];
float waste;
if (nc_create(FILE_NAME, NC_NETCDF4 | NC_CLOBBER, &ncid)) ERR;
/* Create a few dimensions. */
for (d = 0; d < NDIMS3; d++)
{
snprintf(dim_name, sizeof(dim_name), "dim_%d", d);
if (nc_def_dim(ncid, dim_name, dim_len[d], &dimids[d])) ERR;
}
/* Define a var with these dimensions, and turn on chunking. */
if (nc_def_var(ncid, VAR_NAME, NC_FLOAT, NDIMS3, dimids, &varid)) ERR;
if (nc_def_var_chunking(ncid, varid, NC_CHUNKED, NULL)) ERR;
/* Check how default chunking worked. */
if (nc_inq_var_chunking(ncid, varid, &storage, chunksizes)) ERR;
if (storage != NC_CHUNKED) ERR;
if (calculate_waste(NDIMS3, dim_len, chunksizes, &waste)) ERR;
/* if (waste > MAX_WASTE) ERR;*/
if (nc_close(ncid)) ERR;
/* Open the file and check. */
if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
if (nc_close(ncid)) ERR;
}
SUMMARIZE_ERR;
printf("**** testing default chunksizes some randomly sized 3D vars...");
{
#define NDIMS3 3
int varid, ncid;
int dimids[NDIMS3];
size_t dim_len[NDIMS3];
int storage = 0;
size_t chunksizes[NDIMS3];
int d, t;
char dim_name[NC_MAX_NAME + 1];
float waste;
for (t = 0; t < NUM_RANDOM_TESTS; t++)
{
if (nc_create(FILE_NAME, NC_NETCDF4 | NC_CLOBBER, &ncid)) ERR;
/* Create a few dimensions. */
for (d = 0; d < NDIMS3; d++)
{
dim_len[d] = (size_t)rand();
snprintf(dim_name, sizeof(dim_name), "dim_%d", d);
if (nc_def_dim(ncid, dim_name, dim_len[d], &dimids[d])) ERR;
}
/* Define a var with these dimensions, and turn on chunking. */
if (nc_def_var(ncid, VAR_NAME, NC_FLOAT, NDIMS3, dimids, &varid)) ERR;
if (nc_def_var_chunking(ncid, varid, NC_CHUNKED, NULL)) ERR;
/* Check how well default chunking worked. */
if (nc_inq_var_chunking(ncid, varid, &storage, chunksizes)) ERR;
if (storage != NC_CHUNKED) ERR;
if (calculate_waste(NDIMS3, dim_len, chunksizes, &waste)) ERR;
if (waste > MAX_WASTE) ERR;
if (nc_close(ncid)) ERR;
}
}
SUMMARIZE_ERR;
printf("**** testing default chunksizes some randomly sized 3D vars, with one small dimension...");
{
int varid, ncid;
int dimids[NDIMS3];
size_t dim_len[NDIMS3];
int storage = 0;
size_t chunksizes[NDIMS3];
int d, t;
char dim_name[NC_MAX_NAME + 1];
float waste;
for (t = 0; t < NUM_RANDOM_TESTS; t++)
{
if (nc_create(FILE_NAME, NC_NETCDF4 | NC_CLOBBER, &ncid)) ERR;
dim_len[0] = (size_t)rand();
dim_len[1] = (size_t)rand();
dim_len[2] = (size_t)rand() % 1000;
/* Create a few dimensions. */
for (d = 0; d < NDIMS3; d++)
{
snprintf(dim_name, sizeof(dim_name), "dim_%d", d);
if (nc_def_dim(ncid, dim_name, dim_len[d], &dimids[d])) ERR;
}
/* Define a var with these dimensions, and turn on chunking. */
if (nc_def_var(ncid, VAR_NAME, NC_FLOAT, NDIMS3, dimids, &varid)) ERR;
if (nc_def_var_chunking(ncid, varid, NC_CHUNKED, NULL)) ERR;
/* Check how well default chunking worked. */
if (nc_inq_var_chunking(ncid, varid, &storage, chunksizes)) ERR;
if (storage != NC_CHUNKED) ERR;
if (calculate_waste(NDIMS3, dim_len, chunksizes, &waste)) ERR;
if (waste > MAX_WASTE) ERR;
if (nc_close(ncid)) ERR;
}
}
SUMMARIZE_ERR;
printf("**** testing default chunksizes some randomly sized 3D vars, with two small dimensions...");
{
int varid, ncid;
int dimids[NDIMS3];
size_t dim_len[NDIMS3];
int storage = 0;
size_t chunksizes[NDIMS3];
int d, t;
char dim_name[NC_MAX_NAME + 1];
float waste;
for (t = 0; t < NUM_RANDOM_TESTS; t++)
{
if (nc_create(FILE_NAME, NC_NETCDF4 | NC_CLOBBER, &ncid)) ERR;
dim_len[0] = (size_t)rand();
dim_len[1] = (size_t)rand() % 1000;
dim_len[2] = (size_t)rand() % 1000;
/* Create a few dimensions. */
for (d = 0; d < NDIMS3; d++)
{
snprintf(dim_name, sizeof(dim_name), "dim_%d", d);
if (nc_def_dim(ncid, dim_name, dim_len[d], &dimids[d])) ERR;
}
/* Define a var with these dimensions, and turn on chunking. */
if (nc_def_var(ncid, VAR_NAME, NC_FLOAT, NDIMS3, dimids, &varid)) ERR;
if (nc_def_var_chunking(ncid, varid, NC_CHUNKED, NULL)) ERR;
/* Check how well default chunking worked. */
if (nc_inq_var_chunking(ncid, varid, &storage, chunksizes)) ERR;
if (storage != NC_CHUNKED) ERR;
if (calculate_waste(NDIMS3, dim_len, chunksizes, &waste)) ERR;
if (waste > MAX_WASTE) ERR;
if (nc_close(ncid)) ERR;
}
}
SUMMARIZE_ERR;
FINAL_RESULTS;
}