hdf5/test/ragged.c
1999-04-16 14:18:46 -05:00

701 lines
19 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright © 1998 Spizella Software
* All rights reserved.
*
* Programmer: Robb Matzke <robb@arborea.spizella.com>
* Tuesday, August 25, 1998
*/
/* See H5private.h for how to include headers */
#undef NDEBUG
#include <hdf5.h>
#include <H5private.h> /*for performance monitoring*/
#ifdef STDC_HEADERS
# include <signal.h>
#endif
#define NOTIFY_INTERVAL 2 /*seconds*/
#define TIME_LIMIT 60 /*seconds*/
#define CH_SIZE 8192*8 /*approx chunk size in bytes*/
#define MAX_NELMTS 3000000
#define C_MTYPE unsigned int /*type in memory */
#define H_MTYPE H5T_NATIVE_UINT /*type in memory */
#define H_FTYPE H5T_NATIVE_UINT /*type in file */
typedef struct {
double percent;
size_t lo, hi;
size_t nhits;
} quant_t;
#if 1
/* Typical VBT sizes */
static quant_t quant_g[] = {
{10.00, 1, 5},
{89.00, 6, 20},
{ 0.90, 21, 100},
{ 0.09, 101, 1000},
{ 0.01, 1001, 10000},
};
#elif 0
/* Sizes for testing */
static quant_t quant_g[] = {
{10.0, 1, 5},
{80.0, 6, 15},
{10.0, 16, 20},
};
#elif 0
/* Larger I/O */
static quant_t quant_g[] = {
{10.0, 1, 1000},
{80.0, 1001, 5000},
{10.0, 5001, 10000},
};
#else
/* All same size */
static quant_t quant_g[] = {
{100.0, 1000, 1000}
};
#endif
static volatile sig_atomic_t alarm_g = 0;
static volatile sig_atomic_t timeout_g = 0;
/*-------------------------------------------------------------------------
* Function: catch_alarm
*
* Purpose: Increments the global `alarm_g' and resets the alarm for
* another few seconds.
*
* Return: void
*
* Programmer: Robb Matzke
* Wednesday, August 26, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static void
catch_alarm(int UNUSED signum)
{
static int ncalls=0;
ncalls++;
if (0==ncalls % NOTIFY_INTERVAL) {
alarm_g++;
}
if (timeout_g>0) --timeout_g;
alarm(1);
}
/*-------------------------------------------------------------------------
* Function: display_error_cb
*
* Purpose: Displays the error stack after printing "*FAILED*".
*
* Return: Success: 0
*
* Failure: -1
*
* Programmer: Robb Matzke
* Wednesday, March 4, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static herr_t
display_error_cb (void UNUSED *client_data)
{
putchar('\n');
H5Eprint (stdout);
return 0;
}
/*-------------------------------------------------------------------------
* Function: rand_nelmts
*
* Purpose: Returns a the length of a 1-d array according to the
* probabilities described above.
*
* Return: Success: Number of elements
*
* Failure: never fails
*
* Programmer: Robb Matzke
* Thursday, August 20, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static size_t
rand_nelmts(int reset_counters)
{
double p = (rand() % 1000000)/1000000.0;
double total = 0.0;
size_t size=0, i;
static size_t ncalls=0;
if (reset_counters) {
printf(" %9s %8s %8s\n", "Length", "Requsted", "Actual");
printf(" --------------- -------- --------\n");
for (i=0; i<NELMTS(quant_g); i++) {
printf(" [%6lu,%6lu] %7.3f%% %7.3f%%\n",
(unsigned long)(quant_g[i].lo),
(unsigned long)(quant_g[i].hi),
quant_g[i].percent,
100.0*(double)(quant_g[i].nhits)/(double)ncalls);
quant_g[i].nhits = 0;
}
printf(" --------------- -------- --------\n");
ncalls = 0;
size = 0;
} else {
for (i=0; i<NELMTS(quant_g); i++) {
total += quant_g[i].percent/100.0;
if (p<total) {
size = rand()%(1+(quant_g[i].hi-quant_g[i].lo)) +
quant_g[i].lo;
quant_g[i].nhits++;
break;
}
}
assert(i<NELMTS(quant_g));
ncalls++;
}
return size;
}
/*-------------------------------------------------------------------------
* Function: ragged_write_all
*
* Purpose: Writes rows to the ragged array RA.
*
* Return: Success: 0
*
* Failure: -1
*
* Programmer: Robb Matzke
* Thursday, August 27, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static int
ragged_write_all(hid_t ra, hsize_t rows_at_once)
{
int *dd, total_nelmts=0;
hssize_t row; /*current row number */
hsize_t i; /*counter */
hsize_t max_width = quant_g[NELMTS(quant_g)-1].hi;
hsize_t interval_nelmts; /*elmts/interval timer */
hsize_t *size=NULL; /*size of each row */
void **buf=NULL; /*buffer for each row */
H5_timer_t timer, timer_total; /*performance timers */
char s[64]; /*tempory string buffer */
char testname[80];
sprintf(testname, "Testing write all, units of %lu",
(unsigned long)rows_at_once);
printf("%s...\n", testname);
fflush(stdout);
timeout_g = TIME_LIMIT;
/* Create the ragged array row in memory */
if (NULL==(dd = malloc(max_width*sizeof(C_MTYPE))) ||
NULL==(size = malloc(rows_at_once*sizeof(*size))) ||
NULL==(buf = malloc(rows_at_once*sizeof(*buf)))) {
puts("Memory allocation failed");
goto error;
}
for (i=0; i<max_width; i++) dd[i] = i+1;
/*
* Describe a few rows then add them to the ragged array. Print a status
* report every once in a while too.
*/
printf(" %8s %8s %8s %10s\n",
"Row", "Nelmts", "Complete", "Bandwidth");
printf(" -------- -------- -------- ----------\n");
H5_timer_reset(&timer_total);
H5_timer_begin(&timer);
interval_nelmts = 0;
for (row=0; total_nelmts<MAX_NELMTS && timeout_g>0; row+=i) {
for (i=0; i<rows_at_once && total_nelmts<MAX_NELMTS; i++) {
size[i] = rand_nelmts(0);
total_nelmts += size[i];
buf[i] = dd;
interval_nelmts += size[i];
}
if (H5RAwrite(ra, row, i, H_MTYPE, size, buf)<0) goto error;
if (0==row || alarm_g || 0==timeout_g) {
alarm_g = 0;
H5_timer_end(&timer_total, &timer);
/*
* The extra cast in the following statement is a bug workaround
* for the Win32 version 5.0 compiler.
* 1998-11-06 ptl
*/
H5_bandwidth(s,
(double)(hssize_t)interval_nelmts*sizeof(C_MTYPE),
timer.etime);
printf(" %8lu %8lu %7.3f%% %10s%s\n",
(unsigned long)(row+i), (unsigned long)total_nelmts,
100.0*total_nelmts/MAX_NELMTS, s,
0==timeout_g?" (aborting)":"");
interval_nelmts = 0;
H5_timer_begin(&timer);
}
}
/* Conclusions */
if (timeout_g) { /*a minor race condition, but who really cares?*/
H5_timer_end(&timer_total, &timer);
/*
* The extra cast in the following statement is a bug workaround for
* the Win32 version 5.0 compiler.
* 1998-11-06 ptl
*/
H5_bandwidth(s, (double)(hssize_t)interval_nelmts*sizeof(C_MTYPE),
timer.etime);
printf(" %8lu %8lu %7.3f%% %10s\n",
(unsigned long)row, (unsigned long)total_nelmts,
100.0*total_nelmts/MAX_NELMTS, s);
}
printf(" -------- -------- -------- ----------\n");
H5_bandwidth(s, (double)total_nelmts*sizeof(C_MTYPE), timer_total.etime);
printf(" %27s%10s\n", "", s);
/* Cleanup */
free(dd);
free(size);
free(buf);
printf("%-70s PASSED\n\n", testname);
return 0;
error:
printf("%-70s*FAILED*\n\n", testname);
return -1;
}
/*-------------------------------------------------------------------------
* Function: ragged_read_all
*
* Purpose: Reads all rows of a ragged array in row order a few rows at a
* time.
*
* Return: Success: 0
*
* Failure: -1
*
* Programmer: Robb Matzke
* Thursday, August 27, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static int
ragged_read_all(hid_t ra, hsize_t rows_at_once)
{
int total_nelmts=0;
hsize_t i, j; /*counters */
hssize_t row; /*current row number */
hsize_t interval_nelmts; /*elmts/interval timer */
hsize_t *size=NULL; /*size of each row */
C_MTYPE **buf=NULL; /*buffer for each row */
H5_timer_t timer, timer_total; /*performance timers */
char s[64]; /*tempory string buffer */
char testname[80];
sprintf(testname, "Testing read all, units of %lu",
(unsigned long)rows_at_once);
printf("%s...\n", testname);
fflush(stdout);
timeout_g = TIME_LIMIT;
/* Create the ragged array row in memory */
if (NULL==(size = malloc(rows_at_once*sizeof(*size))) ||
NULL==(buf = malloc(rows_at_once*sizeof(*buf)))) {
puts("Memory allocation failed");
goto error;
}
/*
* Read a few rows at a time from the ragged array. Print a status report
* every once in a while too.
*/
printf(" %8s %8s %8s %10s\n",
"Row", "Nelmts", "Complete", "Bandwidth");
printf(" -------- -------- -------- ----------\n");
H5_timer_reset(&timer_total);
H5_timer_begin(&timer);
interval_nelmts = 0;
for (row=0; total_nelmts<MAX_NELMTS && timeout_g>0; row+=i) {
/* Clear data then read */
HDmemset(size, 0, rows_at_once*sizeof(*size));
HDmemset(buf, 0, rows_at_once*sizeof(*buf));
if (H5RAread(ra, row, rows_at_once, H_MTYPE, size,
(void**)buf)<0) {
goto error;
}
/* Check values read */
for (i=0; i<rows_at_once && size[i]; i++) {
interval_nelmts += size[i];
total_nelmts += size[i];
for (j=0; j<size[i]; j++) {
if (buf[i][j]!=j+1) {
printf("Wrong value(s) read for row %ld.\n",
(long)(row+i));
for (j=0; j<size[i]; j++) {
printf("%s%d", j?",":"", buf[i][j]);
}
putchar('\n');
goto error;
}
}
#ifndef _HDF5USEDLL_
/*
For NT dll version we free memory down at the bottom. crashed otherwise.
*/
free(buf[i]);
buf[i] = NULL;
#endif
}
/* Print statistics? */
if (0==row || alarm_g || 0==timeout_g) {
alarm_g = 0;
H5_timer_end(&timer_total, &timer);
/*
* The extra cast in the following statement is a bug workaround
* for the Win32 version 5.0 compiler.
* 1998-11-06 ptl
*/
H5_bandwidth(s, (double)(hssize_t)interval_nelmts*sizeof(C_MTYPE),
timer.etime);
printf(" %8lu %8lu %7.3f%% %10s%s\n",
(unsigned long)(row+i), (unsigned long)total_nelmts,
100.0*total_nelmts/MAX_NELMTS, s,
0==timeout_g?" (aborting)":"");
interval_nelmts = 0;
H5_timer_begin(&timer);
}
if (0==size[rows_at_once-1]) {
/* Reached the end of the array */
if (total_nelmts<MAX_NELMTS) {
puts(" * Short read, previous write probably aborted");
}
row += i;
break;
}
}
/* Conclusions */
if (timeout_g) { /*a minor race condition, but who really cares?*/
H5_timer_end(&timer_total, &timer);
/*
* The extra cast in the following statement is a bug workaround for
* the Win32 version 5.0 compiler.
* 1998-11-06 ptl
*/
H5_bandwidth(s, (double)(hssize_t)interval_nelmts*sizeof(C_MTYPE),
timer.etime);
printf(" %8lu %8lu %7.3f%% %10s\n",
(unsigned long)row, (unsigned long)total_nelmts,
100.0*total_nelmts/MAX_NELMTS, s);
}
printf(" -------- -------- -------- ----------\n");
H5_bandwidth(s, (double)total_nelmts*sizeof(C_MTYPE), timer_total.etime);
printf(" %27s%10s\n", "", s);
/* Cleanup */
#ifdef _HDF5USEDLL_
/*
Need to clean up the memory we allocated. Had to move this down here
for NT. Crashing when it was up in the original location
*/
for (i = 0; i < rows_at_once && size[i]; i++){
free(buf[i]);
// buf[i] = NULL;
}
#endif
free(size);
free(buf);
printf("%-70s PASSED\n\n", testname);
return 0;
error:
printf("%-70s*FAILED*\n\n", testname);
return -1;
}
/*-------------------------------------------------------------------------
* Function: ragged_read_short
*
* Purpose: Reads all the data but only the part that is in the `raw'
* dataset. We should see a nice speed increase because we
* don't have to perform the little reads into the overflow
* array.
*
* Return: Success: 0
*
* Failure: -1
*
* Programmer: Robb Matzke
* Friday, August 28, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static int
ragged_read_short(hid_t ra, hsize_t rows_at_once, hsize_t width)
{
int total_nelmts=0;
hsize_t i, j;
hssize_t row; /*current row number */
hsize_t interval_nelmts; /*elmts/interval timer */
hsize_t read_nelmts=0; /*total elements read */
hsize_t *size=NULL; /*size of each row */
C_MTYPE **buf=NULL; /*buffer for each row */
H5_timer_t timer, timer_total; /*performance timers */
char s[64]; /*tempory string buffer */
char testname[80];
sprintf(testname, "Testing read short, units of %lu",
(unsigned long)rows_at_once);
printf("%s...\n", testname);
fflush(stdout);
timeout_g = TIME_LIMIT;
/* Create the ragged array row in memory */
if (NULL==(size = malloc(rows_at_once*sizeof(*size))) ||
NULL==(buf = malloc(rows_at_once*sizeof(*buf)))) {
puts("Memory allocation failed");
goto error;
}
for (i=0; i<rows_at_once; i++) {
if (NULL==(buf[i] = malloc(width*sizeof(C_MTYPE)))) {
puts("Memory allocation failed");
goto error;
}
}
/*
* Read a few rows at a time from the ragged array. Print a status report
* every once in a while too.
*/
printf(" %8s %8s %8s %10s\n",
"Row", "Nelmts", "Complete", "Bandwidth");
printf(" -------- -------- -------- ----------\n");
H5_timer_reset(&timer_total);
H5_timer_begin(&timer);
interval_nelmts = 0;
for (row=0; total_nelmts<MAX_NELMTS && timeout_g>0; row+=i) {
/* Read data */
for (i=0; i<rows_at_once; i++) size[i] = width;
if (H5RAread(ra, row, rows_at_once, H_MTYPE, size,
(void**)buf)<0) {
goto error;
}
/* Check values read */
for (i=0; i<rows_at_once && size[i]; i++) {
/*
* Number of useful elements actually read in this timing
* interval. This is used to calculate bandwidth.
*/
interval_nelmts += MIN(width, size[i]);
/*
* Total number of elements actually read for rows so far.
*/
read_nelmts += MIN(width, size[i]);
/*
* Total number of elements attributed to the rows read so far.
* This is used to calculate the percent done.
*/
total_nelmts += size[i];
/* Check the values */
for (j=0; j<MIN(width, size[i]); j++) {
if (buf[i][j]!=j+1) {
printf("Wrong value(s) read for row %ld.\n",
(long)(row+i));
for (j=0; j<MIN(width, size[i]); j++) {
printf("%s%d", j?",":"", buf[i][j]);
}
putchar('\n');
goto error;
}
}
}
/* Print statistics? */
if (0==row || alarm_g || 0==timeout_g) {
alarm_g = 0;
H5_timer_end(&timer_total, &timer);
/*
* The extra cast in the following statement is a bug workaround
* for the Win32 version 5.0 compiler.
* 1998-11-06 ptl
*/
H5_bandwidth(s,
(double)(hssize_t)interval_nelmts*sizeof(C_MTYPE),
timer.etime);
printf(" %8lu %8lu %7.3f%% %10s%s\n",
(unsigned long)(row+i), (unsigned long)read_nelmts,
100.0*total_nelmts/MAX_NELMTS, s,
0==timeout_g?" (aborting)":"");
interval_nelmts = 0;
H5_timer_begin(&timer);
}
if (0==size[rows_at_once-1]) {
/* Reached the end of the array */
if (total_nelmts<MAX_NELMTS) {
puts(" * Short read, previous write probably aborted");
}
row += i;
break;
}
}
/* Conclusions */
if (timeout_g) { /*a minor race condition, but who really cares?*/
H5_timer_end(&timer_total, &timer);
/*
* The extra cast in the following statement is a bug workaround for
* the Win32 version 5.0 compiler.
* 1998-11-06 ptl
*/
H5_bandwidth(s, (double)(hssize_t)interval_nelmts*sizeof(C_MTYPE),
timer.etime);
printf(" %8lu %8lu %7.3f%% %10s\n",
(unsigned long)row, (unsigned long)read_nelmts,
100.0*total_nelmts/MAX_NELMTS, s);
}
printf(" -------- -------- -------- ----------\n");
/*
* The extra cast in the following statement is a bug workaround for the
* Win32 version 5.0 compiler.
* 1998-11-06 ptl
*/
H5_bandwidth(s, (double)(hssize_t)read_nelmts*sizeof(C_MTYPE),
timer_total.etime);
printf(" %27s%10s\n", "", s);
/* Cleanup */
for (i=0; i<rows_at_once; i++) free(buf[i]);
free(size);
free(buf);
printf("%-70s PASSED\n\n", testname);
return 0;
error:
printf("%-70s*FAILED*\n\n", testname);
return -1;
}
/*-------------------------------------------------------------------------
* Function: main
*
* Purpose:
*
* Return: Success:
*
* Failure:
*
* Programmer: Robb Matzke
* Friday, August 21, 1998
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
int
main(int argc, char *argv[])
{
hid_t file, dcpl, ra;
hsize_t ch_size[2]; /*chunk size */
hsize_t rows_at_once=100; /*row aggregation */
int argno=1;
/* Parse command line options */
if (argno<argc) {
rows_at_once = strtol(argv[argno++], NULL, 0);
}
/* Display HDF5 API errors in a special way */
H5Eset_auto(display_error_cb, NULL);
/* Get a SIGALRM every few seconds */
#ifdef HAVE_SIGACTION
{
struct sigaction act;
act.sa_handler = catch_alarm;
sigemptyset(&(act.sa_mask));
act.sa_flags = 0;
sigaction(SIGALRM, &act, NULL);
alarm(1);
}
#else
puts("No sigaction(). This test may run for a *long* time.");
#endif
/* Create the file and ragged array */
if ((file=H5Fcreate("ragged.h5", H5F_ACC_TRUNC, H5P_DEFAULT,
H5P_DEFAULT))<0) goto error;
if ((dcpl=H5Pcreate(H5P_DATASET_CREATE))<0) goto error;
ch_size[1] = 20;
ch_size[0] = MAX(1, CH_SIZE/(ch_size[1]*sizeof(C_MTYPE))); /*length*/
printf("Chunk size is %lu by %lu\n",
(unsigned long)(ch_size[0]), (unsigned long)(ch_size[1]));
if (H5Pset_chunk(dcpl, 2, ch_size)<0) goto error;
if ((ra=H5RAcreate(file, "ra", H_FTYPE, dcpl))<0) goto error;
if (H5Pclose(dcpl)<0) goto error;
/* The tests */
if (ragged_write_all(ra, rows_at_once)<0) goto error;
if (ragged_read_all(ra, rows_at_once)<0) goto error;
if (ragged_read_short(ra, rows_at_once, ch_size[1])<0) goto error;
/* The tests again */
if (ragged_write_all(ra, rows_at_once)<0) goto error;
if (ragged_read_all(ra, rows_at_once)<0) goto error;
if (ragged_read_short(ra, rows_at_once, ch_size[1])<0) goto error;
/* Conclusions */
printf("\n\nDistribution of row lengths:\n");
rand_nelmts(1);
/* Cleanup */
if (H5RAclose(ra)<0) goto error;
if (H5Fclose(file)<0) goto error;
puts("All ragged array tests passed.");
return 0;
error:
puts("*** RAGGED ARRAY TEST(S) FAILED ***");
return -1;
}