diff options
author | Songyu Lu <songyulu@barracuda.ad.hdfgroup.org> | 2018-11-02 19:53:35 (GMT) |
---|---|---|
committer | Songyu Lu <songyulu@barracuda.ad.hdfgroup.org> | 2018-11-02 19:53:35 (GMT) |
commit | 6fa26d7e4939ac1b61b74bed7bca70055715be24 (patch) | |
tree | 8c6c9972cfa705fe1594378080ac7db24cf49e00 | |
parent | 20ad15a1a8e9008103fe7d30401408eaa2aff6e5 (diff) | |
download | hdf5-6fa26d7e4939ac1b61b74bed7bca70055715be24.zip hdf5-6fa26d7e4939ac1b61b74bed7bca70055715be24.tar.gz hdf5-6fa26d7e4939ac1b61b74bed7bca70055715be24.tar.bz2 |
HDFFV-10601 Issues with chunk cache hash value calcuation:
1. H5D__chunk_hash_val: When the number of chunks in the fastest changing dimension is larger than the number of slots in the hash table, H5D__chunk_hash_val abandons the normal hash value calculation algorithm and simply uses the scaled dimension. This will cause chunks a selection that cuts across chunks in dimensions other than the fastest changing to all have the same hash value, and they will therefore always evict each other from the cache, having an obvious major performance impact. Eliminated the check for the number of slots in this function and always use the full algorithm.
2. H5D__chunk_init: When the scaled dimensions (number of chunks in each dimension) are calculated in H5D__chunk_init, a simple divide ("/") operator is used with the dataset size in elements and the chunk size in elements. While this is fine when the dataset size is an exact multiple of the chunk size, in other cases, since "/" rounds down, it results in a scaled dimension one less than it should (it ignores the partial edge chunk). This has trickle down effects on hash value calculation that can cause excess hash value collisions and therefore performance issues. Changed the calculation to (((dataset_size - 1) / chunk_size) + 1).
Tested the build with Autotool and CMake.
-rw-r--r-- | src/H5Dchunk.c | 24 |
1 files changed, 12 insertions, 12 deletions
diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c index 22dc05a..7eeb866 100644 --- a/src/H5Dchunk.c +++ b/src/H5Dchunk.c @@ -949,7 +949,12 @@ H5D__chunk_init(H5F_t *f, const H5D_t *dset, hid_t dapl_id) /* Initial scaled dimension sizes */ if(dset->shared->layout.u.chunk.dim[u] == 0) HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "chunk size must be > 0, dim = %u ", u) - rdcc->scaled_dims[u] = dset->shared->curr_dims[u] / dset->shared->layout.u.chunk.dim[u]; + + /* Make a special case when the dimension is 0 because (0 - 1) is a big number for unsigned integer */ + if(dset->shared->curr_dims[u] == 0) + rdcc->scaled_dims[u] = 0; + else + rdcc->scaled_dims[u] = ((dset->shared->curr_dims[u] - 1) / dset->shared->layout.u.chunk.dim[u]) + 1; if( !(scaled_power2up = H5VM_power2up(rdcc->scaled_dims[u])) ) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get the next power of 2") @@ -2799,6 +2804,7 @@ H5D__chunk_hash_val(const H5D_shared_t *shared, const hsize_t *scaled) hsize_t val; /* Intermediate value */ unsigned ndims = shared->ndims; /* Rank of dataset */ unsigned ret = 0; /* Value to return */ + unsigned u; /* Local index variable */ FUNC_ENTER_STATIC_NOERR @@ -2809,17 +2815,11 @@ H5D__chunk_hash_val(const H5D_shared_t *shared, const hsize_t *scaled) /* If the fastest changing dimension doesn't have enough entropy, use * other dimensions too */ - if(ndims > 1 && shared->cache.chunk.scaled_dims[ndims - 1] <= shared->cache.chunk.nslots) { - unsigned u; /* Local index variable */ - - val = scaled[0]; - for(u = 1; u < ndims; u++) { - val <<= shared->cache.chunk.scaled_encode_bits[u]; - val ^= scaled[u]; - } /* end for */ - } /* end if */ - else - val = scaled[ndims - 1]; + val = scaled[0]; + for(u = 1; u < ndims; u++) { + val <<= shared->cache.chunk.scaled_encode_bits[u]; + val ^= scaled[u]; + } /* end for */ /* Modulo value against the number of array slots */ ret = (unsigned)(val % shared->cache.chunk.nslots); |