diff options
author | David Young <dyoung@hdfgroup.org> | 2019-10-17 21:36:17 (GMT) |
---|---|---|
committer | David Young <dyoung@hdfgroup.org> | 2019-10-17 21:36:17 (GMT) |
commit | 90a602634e0f283dcc100dfcb6e98977d5d74981 (patch) | |
tree | 57a8bf2b95c7f5bbf2940b5d20bcb97c9563b477 /test/dsets.c | |
parent | fcd490a0bca6004364b5bdbf5483e194b25a998f (diff) | |
download | hdf5-90a602634e0f283dcc100dfcb6e98977d5d74981.zip hdf5-90a602634e0f283dcc100dfcb6e98977d5d74981.tar.gz hdf5-90a602634e0f283dcc100dfcb6e98977d5d74981.tar.bz2 |
I've changed `test/dsets` so that every time it needs to visit all
cells in a matrix in an arbitrary order, first it chooses a random
starting `offset` in [0, rows * columns - 1]. Then it chooses a
random `increment` that's relatively prime to `rows * columns`.
Then it visits every cell in `rows * columns` steps:
for (i = 0; i < rows * columns; i++) {
visit(cell[offset / columns][offset % columns]);
offset = (increment + offset) % (rows * columns);
}
By moving the HDrandom() calls outside of the main loop and visiting
each cell only once, this probably speeds things up quite a bit. It's
also more resilient to a crummy random sequence. The new code visits
cells in an order that's probably arbitrary enough for testing purposes.
Diffstat (limited to 'test/dsets.c')
-rw-r--r-- | test/dsets.c | 153 |
1 files changed, 121 insertions, 32 deletions
diff --git a/test/dsets.c b/test/dsets.c index faf2ad7..39bed93 100644 --- a/test/dsets.c +++ b/test/dsets.c @@ -7002,6 +7002,70 @@ error: return -1; } /* end test_missing_chunk() */ +/* Using Euclid's algorithm, find the greatest common divisor (GCD) of + * the two arguments and return it. + * + * The GCD is negative if the arguments have opposite sign. Otherwise, + * it is positive. + * + * If either argument is zero, then the result is undefined. + */ +static long +gcd(const long l0, const long r0) +{ + long magnitude, remainder; + bool negative = ((l0 < 0) != (r0 < 0)); + long l = labs(l0), r = labs(r0); + + do { + if (l < r) { + r = r % l; + remainder = r; + } else /* r <= l */ { + l = l % r; + remainder = l; + } + } while (remainder != 0); + + magnitude = (l == 0) ? r : l; + return negative ? -magnitude : magnitude; +} + +/* Choose a random offset into an array `nelts` elements long, and store + * it at `offsetp`. The offset will be in the range [0, nelts - 1]. + * Also choose a random increment, `inc`, that "generates" all + * indices in [0, nelts - 1] when it is added to itself repeatedly. + * That is, the range of the discrete function `f(i) = (i * inc) + * mod nelts` on the domain [0, nelts - 1] is [0, nelts - 1]. Store + * `inc` at `incp`. + * + * If `nelts <= 0`, results are undefined. + */ +static void +make_random_offset_and_increment(long nelts, long *offsetp, long *incp) +{ + long inc; + + assert(0 < nelts); + + *offsetp = random() % nelts; + + /* `maxinc` is chosen so that for any `x` in [0, nelts - 1], + * `x + maxinc` does not overflow a long. + */ + const long maxinc = MIN(nelts - 1, LONG_MAX - nelts); + + /* Choose a random number in [1, nelts - 1]. If its greatest divisor + * in common with `nelts` is 1, then it will "generate" the additive ring + * [0, nelts - 1], so let it be our increment. Otherwise, choose a new + * number. + */ + do { + inc = 1 + random() % maxinc; + } while (gcd(inc, nelts) != 1); + + *incp = inc; +} /*------------------------------------------------------------------------- * Function: test_random_chunks_real @@ -7026,7 +7090,7 @@ test_random_chunks_real(const char *testname, hbool_t early_alloc, hid_t fapl) rbuf[NPOINTS], check2[20][20]; hsize_t coord[NPOINTS][2]; - hsize_t dsize[2]={100,100}, dmax[2]={H5S_UNLIMITED, H5S_UNLIMITED}, csize[2]={10,10}, nsize[2]={200,200}; + const hsize_t dsize[2]={100,100}, dmax[2]={H5S_UNLIMITED, H5S_UNLIMITED}, csize[2]={10,10}, nsize[2]={200,200}; hsize_t fixed_dmax[2] = {1000, 1000}; hsize_t msize[1]={NPOINTS}; const char dname[]="dataset"; @@ -7034,7 +7098,9 @@ test_random_chunks_real(const char *testname, hbool_t early_alloc, hid_t fapl) size_t i, j; H5D_chunk_index_t idx_type; /* Dataset chunk index type */ H5F_libver_t low; /* File format low bound */ - + long ofs, inc; + long rows; + long cols; TESTING(testname); @@ -7068,12 +7134,16 @@ test_random_chunks_real(const char *testname, hbool_t early_alloc, hid_t fapl) for(j=0; j<dsize[1]/csize[1]; j++) check2[i][j] = 0; + rows = (long)(dsize[0]/csize[0]); + cols = (long)(dsize[1]/csize[1]); + make_random_offset_and_increment(rows * cols, &ofs, &inc); + /* Generate random point coordinates. Only one point is selected per chunk */ for(i=0; i<NPOINTS; i++){ - do { - chunk_row = (int)HDrandom () % (int)(dsize[0]/csize[0]); - chunk_col = (int)HDrandom () % (int)(dsize[1]/csize[1]); - } while (check2[chunk_row][chunk_col]); + chunk_row = ofs / cols; + chunk_col = ofs % cols; + ofs = (ofs + inc) % (rows * cols); + assert(!check2[chunk_row][chunk_col]); wbuf[i] = check2[chunk_row][chunk_col] = chunk_row+chunk_col+1; coord[i][0] = (hsize_t)chunk_row * csize[0]; @@ -7191,12 +7261,16 @@ test_random_chunks_real(const char *testname, hbool_t early_alloc, hid_t fapl) for(j = 0; j < nsize[1] / csize[1]; j++) check2[i][j] = 0; + rows = nsize[0] / csize[0]; + cols = nsize[1] / csize[1]; + make_random_offset_and_increment(rows * cols, &ofs, &inc); + /* Generate random point coordinates. Only one point is selected per chunk */ for(i = 0; i < NPOINTS; i++){ - do { - chunk_row = (int)HDrandom() % (int)(nsize[0] / csize[0]); - chunk_col = (int)HDrandom() % (int)(nsize[1] / csize[1]); - } while (check2[chunk_row][chunk_col]); + chunk_row = ofs / cols; + chunk_col = ofs % cols; + ofs = (ofs + inc) % (rows * cols); + assert(!check2[chunk_row][chunk_col]); wbuf[i] = check2[chunk_row][chunk_col] = chunk_row + chunk_col + 1; coord[i][0] = (hsize_t)chunk_row * csize[0]; @@ -7297,12 +7371,16 @@ test_random_chunks_real(const char *testname, hbool_t early_alloc, hid_t fapl) for(j = 0; j < nsize[1] / csize[1]; j++) check2[i][j] = 0; + rows = (long)(nsize[0] / csize[0]); + cols = (long)(nsize[1] / csize[1]); + make_random_offset_and_increment(rows * cols, &ofs, &inc); + /* Generate random point coordinates. Only one point is selected per chunk */ for(i = 0; i < NPOINTS; i++){ - do { - chunk_row = (int)HDrandom() % (int)(nsize[0] / csize[0]); - chunk_col = (int)HDrandom() % (int)(nsize[1] / csize[1]); - } while (check2[chunk_row][chunk_col]); + chunk_row = ofs / cols; + chunk_col = ofs % cols; + ofs = (ofs + inc) % (rows * cols); + assert(!check2[chunk_row][chunk_col]); wbuf[i] = check2[chunk_row][chunk_col] = chunk_row + chunk_col + 1; coord[i][0] = (hsize_t)chunk_row * csize[0]; @@ -9318,7 +9396,7 @@ test_fixed_array(hid_t fapl) hid_t dsid_max = -1; /* Dataset ID for dataset with maximum dimensions set */ hsize_t dim2[2] = {48, 18}; /* Dataset dimensions */ - hsize_t dim2_big[2] = {500, 60}; /* Big dataset dimensions */ + const hsize_t dim2_big[2] = {500, 60}; /* Big dataset dimensions */ hsize_t dim2_max[2] = {120, 50}; /* Maximum dataset dimensions */ hid_t mem_id; /* Memory space ID */ @@ -9332,7 +9410,7 @@ test_fixed_array(hid_t fapl) int rbuf[POINTS]; /* read buffer */ int *rbuf_big = NULL; /* read buffer for big dataset */ - hsize_t chunk_dim2[2] = {4, 3}; /* Chunk dimensions */ + const hsize_t chunk_dim2[2] = {4, 3}; /* Chunk dimensions */ int chunks[12][6]; /* # of chunks for dataset dimensions */ int chunks_big[125][20]; /* # of chunks for big dataset dimensions */ int chunk_row; /* chunk row index */ @@ -9354,6 +9432,9 @@ test_fixed_array(hid_t fapl) size_t i, j; /* local index variables */ herr_t ret; /* Generic return value */ + long ofs, inc; + long rows; + long cols; TESTING("datasets w/fixed array as chunk index"); @@ -9412,16 +9493,20 @@ test_fixed_array(hid_t fapl) for(j = 0; j < dim2[1]/chunk_dim2[1]; j++) chunks[i][j] = 0; + rows = (long)(dim2[0]/chunk_dim2[0]); + cols = (long)(dim2[1]/chunk_dim2[1]); + make_random_offset_and_increment(rows * cols, &ofs, &inc); + /* Generate random point coordinates. Only one point is selected per chunk */ for(i = 0; i < POINTS; i++){ - do { - chunk_row = (int)HDrandom () % (int)(dim2[0]/chunk_dim2[0]); - chunk_col = (int)HDrandom () % (int)(dim2[1]/chunk_dim2[1]); - } while (chunks[chunk_row][chunk_col]); - - wbuf[i] = chunks[chunk_row][chunk_col] = chunk_row+chunk_col+1; - coord[i][0] = (hsize_t)chunk_row * chunk_dim2[0]; - coord[i][1] = (hsize_t)chunk_col * chunk_dim2[1]; + chunk_row = ofs / cols; + chunk_col = ofs % cols; + ofs = (ofs + inc) % (rows * cols); + assert(!chunks[chunk_row][chunk_col]); + + wbuf[i] = chunks[chunk_row][chunk_col] = chunk_row+chunk_col+1; + coord[i][0] = (hsize_t)chunk_row * chunk_dim2[0]; + coord[i][1] = (hsize_t)chunk_col * chunk_dim2[1]; } /* end for */ /* Create first dataset with cur and max dimensions */ @@ -9537,16 +9622,20 @@ test_fixed_array(hid_t fapl) for(j = 0; j < dim2_big[1]/chunk_dim2[1]; j++) chunks_big[i][j] = 0; + rows = (long)(dim2_big[0]/chunk_dim2[0]); + cols = (long)(dim2_big[1]/chunk_dim2[1]); + make_random_offset_and_increment(rows * cols, &ofs, &inc); + /* Generate random point coordinates. Only one point is selected per chunk */ for(i = 0; i < POINTS_BIG; i++){ - do { - chunk_row = (int)HDrandom () % (int)(dim2_big[0]/chunk_dim2[0]); - chunk_col = (int)HDrandom () % (int)(dim2_big[1]/chunk_dim2[1]); - } while (chunks_big[chunk_row][chunk_col]); - - wbuf_big[i] = chunks_big[chunk_row][chunk_col] = chunk_row+chunk_col+1; - coord_big[i][0] = (hsize_t)chunk_row * chunk_dim2[0]; - coord_big[i][1] = (hsize_t)chunk_col * chunk_dim2[1]; + chunk_row = ofs / cols; + chunk_col = ofs % cols; + ofs = (ofs + inc) % (rows * cols); + assert(!chunks_big[chunk_row][chunk_col]); + + wbuf_big[i] = chunks_big[chunk_row][chunk_col] = chunk_row+chunk_col+1; + coord_big[i][0] = (hsize_t)chunk_row * chunk_dim2[0]; + coord_big[i][1] = (hsize_t)chunk_col * chunk_dim2[1]; } /* end for */ /* Create dataspace for write buffer */ |