/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright by The HDF Group. * * Copyright by the Board of Trustees of the University of Illinois. * * All rights reserved. * * * * This file is part of HDF5. The full HDF5 copyright notice, including * * terms governing use, modification, and redistribution, is contained in * * the COPYING file, which can be found at the root of the source code * * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. * * If you do not have access to either file, you may request a copy from * * help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * Programmer: Robb Matzke * Thursday, May 14, 1998 * * Purpose: Checks the effect of various I/O request sizes and raw data * cache sizes. Performance depends on the amount of data read * from disk and we use a filter to get that number. */ /* See H5private.h for how to include headers */ #undef NDEBUG #include "hdf5.h" #ifdef H5_STDC_HEADERS # include # include # include # include #endif /* Solaris Studio defines attribute, but for the attributes we need */ #if !defined(H5_HAVE_ATTRIBUTE) || defined __cplusplus || defined(__SUNPRO_C) # undef __attribute__ # define __attribute__(X) /*void*/ # define H5_ATTR_UNUSED /*void*/ #else # define H5_ATTR_UNUSED __attribute__((unused)) #endif #define FILE_NAME "chunk.h5" #define LINESPOINTS "lines" #define CH_SIZE 100 /*squared in terms of bytes */ #define DS_SIZE 20 /*squared in terms of chunks */ #define FILTER_COUNTER 305 #define READ 0 #define WRITE 1 #define MIN(X,Y) ((X)<(Y)?(X):(Y)) #define MAX(X,Y) ((X)>(Y)?(X):(Y)) #define SQUARE(X) ((X)*(X)) /* The row-major test */ #define RM_CACHE_STRT 25 #define RM_CACHE_END 25 #define RM_CACHE_DELT 5 #define RM_START (double)0.50F #define RM_END (double)5.00F #define RM_DELTA (double)0.50F #define RM_W0 0.0F #define RM_NRDCC 521 /* Diagonal test */ #define DIAG_CACHE_STRT 25 #define DIAG_CACHE_END 25 #define DIAG_CACHE_DELT 5 #define DIAG_START (double)0.50F #define DIAG_END (double)5.00F #define DIAG_DELTA (double)0.50F /* #define DIAG_W0 0.65F */ /* #define DIAG_NRDCC 521 */ static size_t nio_g; static hid_t fapl_g = -1; /* Local function prototypes */ static size_t counter (unsigned H5_ATTR_UNUSED flags, size_t cd_nelmts, const unsigned *cd_values, size_t nbytes, size_t *buf_size, void **buf); /* This message derives from H5Z */ const H5Z_class2_t H5Z_COUNTER[1] = {{ H5Z_CLASS_T_VERS, /* H5Z_class_t version */ FILTER_COUNTER, /* Filter id number */ 1, 1, /* Encoding and decoding enabled */ "counter", /* Filter name for debugging */ NULL, /* The "can apply" callback */ NULL, /* The "set local" callback */ counter, /* The actual filter function */ }}; /*------------------------------------------------------------------------- * Function: counter * * Purpose: Count number of bytes but don't do anything. * * Return: Success: src_nbytes-1 * * Failure: never fails * * Programmer: Robb Matzke * Thursday, May 14, 1998 * * Modifications: * *------------------------------------------------------------------------- */ static size_t counter (unsigned H5_ATTR_UNUSED flags, size_t H5_ATTR_UNUSED cd_nelmts, const unsigned H5_ATTR_UNUSED *cd_values, size_t nbytes, size_t H5_ATTR_UNUSED *buf_size, void H5_ATTR_UNUSED **buf) { nio_g += nbytes; return nbytes; } /*------------------------------------------------------------------------- * Function: create_dataset * * Purpose: Creates a square dataset with square chunks, registers a * stupid compress/uncompress pair for counting I/O, and * initializes the dataset. The chunk size is in bytes, the * dataset size is in terms of chunks. * * Return: void * * Programmer: Robb Matzke * Thursday, May 14, 1998 * * Modifications: * *------------------------------------------------------------------------- */ static void create_dataset (void) { hid_t file, space, dcpl, dset; hsize_t size[2]; signed char *buf; /* The file */ file = H5Fcreate (FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, fapl_g); /* The data space */ size[0] = size[1] = DS_SIZE * CH_SIZE; space = H5Screate_simple(2, size, size); /* The storage layout and compression */ dcpl = H5Pcreate(H5P_DATASET_CREATE); size[0] = size[1] = CH_SIZE; H5Pset_chunk(dcpl, 2, size); H5Zregister(H5Z_COUNTER); H5Pset_filter(dcpl, FILTER_COUNTER, 0, 0, NULL); /* The dataset */ dset = H5Dcreate2(file, "dset", H5T_NATIVE_SCHAR, space, H5P_DEFAULT, dcpl, H5P_DEFAULT); assert(dset>=0); /* The data */ buf = (signed char *)calloc(1, SQUARE (DS_SIZE*CH_SIZE)); H5Dwrite(dset, H5T_NATIVE_SCHAR, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf); free(buf); /* Close */ H5Dclose(dset); H5Sclose(space); H5Pclose(dcpl); H5Fclose(file); } /*------------------------------------------------------------------------- * Function: test_rowmaj * * Purpose: Reads the entire dataset using the specified size-squared * I/O requests in row major order. * * Return: Efficiency: data requested divided by data actually read. * * Programmer: Robb Matzke * Thursday, May 14, 1998 * * Modifications: * *------------------------------------------------------------------------- */ static double test_rowmaj (int op, size_t cache_size, size_t io_size) { hid_t file, dset, mem_space, file_space; signed char *buf = (signed char *)calloc (1, (size_t)(SQUARE(io_size))); hsize_t i, j, hs_size[2]; hsize_t hs_offset[2]; int mdc_nelmts; size_t rdcc_nelmts; double w0; H5Pget_cache (fapl_g, &mdc_nelmts, &rdcc_nelmts, NULL, &w0); #ifdef RM_W0 w0 = RM_W0; #endif #ifdef RM_NRDCC rdcc_nelmts = RM_NRDCC; #endif H5Pset_cache (fapl_g, mdc_nelmts, rdcc_nelmts, cache_size*SQUARE (CH_SIZE), w0); file = H5Fopen(FILE_NAME, H5F_ACC_RDWR, fapl_g); dset = H5Dopen2(file, "dset", H5P_DEFAULT); file_space = H5Dget_space(dset); nio_g = 0; for (i=0; i0) nio -= SQUARE (io_size-offset); } free (buf); H5Sclose (file_space); H5Dclose (dset); H5Fclose (file); /* * The extra cast in the following statement is a bug workaround for the * Win32 version 5.0 compiler. * 1998-11-06 ptl */ return (double)nio/(double)nio_g; } /*------------------------------------------------------------------------- * Function: main * * Purpose: See file prologue. * * Return: Success: * * Failure: * * Programmer: Robb Matzke * Thursday, May 14, 1998 * * Modifications: * *------------------------------------------------------------------------- */ int main (void) { size_t io_size; double effic, io_percent; FILE *f, *d; size_t cache_size; double w0; /* * Create a global file access property list. */ fapl_g = H5Pcreate (H5P_FILE_ACCESS); H5Pget_cache (fapl_g, NULL, NULL, NULL, &w0); /* Create the file */ create_dataset (); f = fopen ("x-gnuplot", "w"); printf("Test %8s %8s %8s\n", "CacheSz", "ChunkSz", "Effic"); printf("--------- -------- -------- --------\n"); #if 1 /* * Test row-major reading of the dataset with various sizes of request * windows. */ if (RM_CACHE_STRT==RM_CACHE_END) { fprintf (f, "set yrange [0:1.2]\n"); fprintf (f, "set ytics 0, 0.1, 1\n"); fprintf (f, "set xlabel \"%s\"\n", "Request size as a fraction of chunk size"); fprintf (f, "set ylabel \"Efficiency\"\n"); fprintf (f, "set title \"Cache %d chunks, w0=%g, " "Size=(total=%d, chunk=%d)\"\n", RM_CACHE_STRT, w0, DS_SIZE*CH_SIZE, CH_SIZE); } else { fprintf (f, "set autoscale\n"); fprintf (f, "set hidden3d\n"); } fprintf (f, "set terminal postscript\nset output \"x-rowmaj-rd.ps\"\n"); fprintf (f, "%s \"x-rowmaj-rd.dat\" title \"RowMaj-Read\" with %s\n", RM_CACHE_STRT==RM_CACHE_END?"plot":"splot", LINESPOINTS); fprintf (f, "set terminal x11\nreplot\n"); d = fopen ("x-rowmaj-rd.dat", "w"); for (cache_size=RM_CACHE_STRT; cache_size<=RM_CACHE_END; cache_size+=RM_CACHE_DELT) { for (io_percent=RM_START; io_percent<=RM_END; io_percent+=RM_DELTA) { io_size = MAX (1, (size_t)(CH_SIZE*io_percent)); printf ("Rowmaj-rd %8d %8.2f", (int)cache_size, io_percent); fflush (stdout); effic = test_rowmaj (READ, cache_size, io_size); printf (" %8.2f\n", effic); if (RM_CACHE_STRT==RM_CACHE_END) { fprintf (d, "%g %g\n", io_percent, effic); } else { fprintf (d, "%g\n", effic); } } fprintf (d, "\n"); } fclose (d); fprintf (f, "pause -1\n"); #endif #if 1 /* * Test row-major writing of the dataset with various sizes of request * windows. */ if (RM_CACHE_STRT==RM_CACHE_END) { fprintf (f, "set yrange [0:1.2]\n"); fprintf (f, "set ytics 0, 0.1, 1\n"); fprintf (f, "set xlabel \"%s\"\n", "Request size as a fraction of chunk size"); fprintf (f, "set ylabel \"Efficiency\"\n"); fprintf (f, "set title \"Cache %d chunks,w0=%g, " "Size=(total=%d, chunk=%d)\"\n", RM_CACHE_STRT, w0, DS_SIZE*CH_SIZE, CH_SIZE); } else { fprintf (f, "set autoscale\n"); fprintf (f, "set hidden3d\n"); } fprintf (f, "set terminal postscript\nset output \"x-rowmaj-wr.ps\"\n"); fprintf (f, "%s \"x-rowmaj-wr.dat\" title \"RowMaj-Write\" with %s\n", RM_CACHE_STRT==RM_CACHE_END?"plot":"splot", LINESPOINTS); fprintf (f, "set terminal x11\nreplot\n"); d = fopen ("x-rowmaj-wr.dat", "w"); for (cache_size=RM_CACHE_STRT; cache_size<=RM_CACHE_END; cache_size+=RM_CACHE_DELT) { for (io_percent=RM_START; io_percent<=RM_END; io_percent+=RM_DELTA) { io_size = MAX (1, (size_t)(CH_SIZE*io_percent)); printf ("Rowmaj-wr %8d %8.2f", (int)cache_size, io_percent); fflush (stdout); effic = test_rowmaj (WRITE, cache_size, io_size); printf (" %8.2f\n", effic); if (RM_CACHE_STRT==RM_CACHE_END) { fprintf (d, "%g %g\n", io_percent, effic); } else { fprintf (d, "%g\n", effic); } } fprintf (d, "\n"); } fclose (d); fprintf (f, "pause -1\n"); #endif #if 1 /* * Test diagonal read */ if (DIAG_CACHE_STRT==DIAG_CACHE_END) { fprintf (f, "set yrange [0:1.2]\n"); fprintf (f, "set ytics 0, 0.1, 1\n"); fprintf (f, "set xlabel \"%s\"\n", "Request size as a fraction of chunk size"); fprintf (f, "set ylabel \"Efficiency\"\n"); fprintf (f, "set title \"Cache %d chunks,w0=%g, " "Size=(total=%d, chunk=%d)\"\n", DIAG_CACHE_STRT, w0, DS_SIZE*CH_SIZE, CH_SIZE); } else { fprintf (f, "set autoscale\n"); fprintf (f, "set hidden3d\n"); } fprintf (f, "set terminal postscript\nset output \"x-diag-rd.ps\"\n"); fprintf (f, "%s \"x-diag-rd.dat\" title \"Diag-Read\" with %s\n", DIAG_CACHE_STRT==DIAG_CACHE_END?"plot":"splot", LINESPOINTS); fprintf (f, "set terminal x11\nreplot\n"); d = fopen ("x-diag-rd.dat", "w"); for (cache_size=DIAG_CACHE_STRT; cache_size<=DIAG_CACHE_END; cache_size+=DIAG_CACHE_DELT) { for (io_percent=DIAG_START; io_percent<=DIAG_END; io_percent+=DIAG_DELTA) { io_size = MAX (1, (size_t)(CH_SIZE*io_percent)); printf ("Diag-rd %8d %8.2f", (int)cache_size, io_percent); fflush (stdout); effic = test_diag (READ, cache_size, io_size, MAX (1, io_size/2)); printf (" %8.2f\n", effic); if (DIAG_CACHE_STRT==DIAG_CACHE_END) { fprintf (d, "%g %g\n", io_percent, effic); } else { fprintf (d, "%g\n", effic); } } fprintf (d, "\n"); } fclose (d); fprintf (f, "pause -1\n"); #endif #if 1 /* * Test diagonal write */ if (DIAG_CACHE_STRT==DIAG_CACHE_END) { fprintf (f, "set yrange [0:1.2]\n"); fprintf (f, "set ytics 0, 0.1, 1\n"); fprintf (f, "set xlabel \"%s\"\n", "Request size as a fraction of chunk size"); fprintf (f, "set ylabel \"Efficiency\"\n"); fprintf (f, "set title \"Cache %d chunks, w0=%g, " "Size=(total=%d, chunk=%d)\"\n", DIAG_CACHE_STRT, w0, DS_SIZE*CH_SIZE, CH_SIZE); } else { fprintf (f, "set autoscale\n"); fprintf (f, "set hidden3d\n"); } fprintf (f, "set terminal postscript\nset output \"x-diag-wr.ps\"\n"); fprintf (f, "%s \"x-diag-wr.dat\" title \"Diag-Write\" with %s\n", DIAG_CACHE_STRT==DIAG_CACHE_END?"plot":"splot", LINESPOINTS); fprintf (f, "set terminal x11\nreplot\n"); d = fopen ("x-diag-wr.dat", "w"); for (cache_size=DIAG_CACHE_STRT; cache_size<=DIAG_CACHE_END; cache_size+=DIAG_CACHE_DELT) { for (io_percent=DIAG_START; io_percent<=DIAG_END; io_percent+=DIAG_DELTA) { io_size = MAX (1, (size_t)(CH_SIZE*io_percent)); printf ("Diag-wr %8d %8.2f", (int)cache_size, io_percent); fflush (stdout); effic = test_diag (WRITE, cache_size, io_size, MAX (1, io_size/2)); printf (" %8.2f\n", effic); if (DIAG_CACHE_STRT==DIAG_CACHE_END) { fprintf (d, "%g %g\n", io_percent, effic); } else { fprintf (d, "%g\n", effic); } } fprintf (d, "\n"); } fclose (d); fprintf (f, "pause -1\n"); #endif H5Pclose (fapl_g); fclose (f); return 0; }