forked from blender/blender
main sync #3
@ -142,13 +142,30 @@
|
|||||||
#ifdef USE_HASH_TABLE_ACCUMULATE
|
#ifdef USE_HASH_TABLE_ACCUMULATE
|
||||||
/* Number of times to propagate hashes back.
|
/* Number of times to propagate hashes back.
|
||||||
* Effectively a 'triangle-number'.
|
* Effectively a 'triangle-number'.
|
||||||
* so 4 -> 7, 5 -> 10, 6 -> 15... etc.
|
* so 3 -> 7, 4 -> 11, 5 -> 16, 6 -> 22, 7 -> 29, ... etc.
|
||||||
|
*
|
||||||
|
* \note additional steps are expensive, so avoid high values unless necessary
|
||||||
|
* (with low strides, between 1-4) where a low value would cause the hashes to
|
||||||
|
* be un-evenly distributed.
|
||||||
*/
|
*/
|
||||||
# define BCHUNK_HASH_TABLE_ACCUMULATE_STEPS 4
|
# define BCHUNK_HASH_TABLE_ACCUMULATE_STEPS_DEFAULT 3
|
||||||
|
# define BCHUNK_HASH_TABLE_ACCUMULATE_STEPS_32BITS 4
|
||||||
|
# define BCHUNK_HASH_TABLE_ACCUMULATE_STEPS_16BITS 5
|
||||||
|
/**
|
||||||
|
* Singe bytes (or boolean) arrays need a higher number of steps
|
||||||
|
* because the resulting values are not unique enough to result in evenly distributed values.
|
||||||
|
* Use more accumulation when the the size of the structs is small, see: #105046.
|
||||||
|
*
|
||||||
|
* With 6 -> 22, one byte each - means an array of booleans can be combine into 22 bits
|
||||||
|
* representing 4,194,303 different combinations.
|
||||||
|
*/
|
||||||
|
# define BCHUNK_HASH_TABLE_ACCUMULATE_STEPS_8BITS 6
|
||||||
#else
|
#else
|
||||||
/* How many items to hash (multiplied by stride)
|
/**
|
||||||
|
* How many items to hash (multiplied by stride).
|
||||||
|
* The more values, the greater the chance this block has a unique hash.
|
||||||
*/
|
*/
|
||||||
# define BCHUNK_HASH_LEN 4
|
# define BCHUNK_HASH_LEN 16
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -216,7 +233,10 @@ typedef struct BArrayInfo {
|
|||||||
/* min/max limits (inclusive) */
|
/* min/max limits (inclusive) */
|
||||||
size_t chunk_byte_size_min;
|
size_t chunk_byte_size_min;
|
||||||
size_t chunk_byte_size_max;
|
size_t chunk_byte_size_max;
|
||||||
|
/**
|
||||||
|
* The read-ahead value should never exceed `chunk_byte_size`,
|
||||||
|
* otherwise the hash would be based on values in the next chunk.
|
||||||
|
*/
|
||||||
size_t accum_read_ahead_bytes;
|
size_t accum_read_ahead_bytes;
|
||||||
#ifdef USE_HASH_TABLE_ACCUMULATE
|
#ifdef USE_HASH_TABLE_ACCUMULATE
|
||||||
size_t accum_steps;
|
size_t accum_steps;
|
||||||
@ -943,9 +963,9 @@ static const BChunkRef *table_lookup(const BArrayInfo *info,
|
|||||||
|
|
||||||
static hash_key key_from_chunk_ref(const BArrayInfo *info, const BChunkRef *cref)
|
static hash_key key_from_chunk_ref(const BArrayInfo *info, const BChunkRef *cref)
|
||||||
{
|
{
|
||||||
const size_t data_hash_len = BCHUNK_HASH_LEN * info->chunk_stride;
|
|
||||||
hash_key key;
|
hash_key key;
|
||||||
BChunk *chunk = cref->link;
|
BChunk *chunk = cref->link;
|
||||||
|
const size_t data_hash_len = MIN2(chunk->data_len, BCHUNK_HASH_LEN * info->chunk_stride);
|
||||||
|
|
||||||
# ifdef USE_HASH_TABLE_KEY_CACHE
|
# ifdef USE_HASH_TABLE_KEY_CACHE
|
||||||
key = chunk->key;
|
key = chunk->key;
|
||||||
@ -1398,6 +1418,8 @@ static BChunkList *bchunk_list_from_data_merge(const BArrayInfo *info,
|
|||||||
|
|
||||||
BArrayStore *BLI_array_store_create(uint stride, uint chunk_count)
|
BArrayStore *BLI_array_store_create(uint stride, uint chunk_count)
|
||||||
{
|
{
|
||||||
|
BLI_assert(stride > 0 && chunk_count > 0);
|
||||||
|
|
||||||
BArrayStore *bs = MEM_callocN(sizeof(BArrayStore), __func__);
|
BArrayStore *bs = MEM_callocN(sizeof(BArrayStore), __func__);
|
||||||
|
|
||||||
bs->info.chunk_stride = stride;
|
bs->info.chunk_stride = stride;
|
||||||
@ -1410,14 +1432,32 @@ BArrayStore *BLI_array_store_create(uint stride, uint chunk_count)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_HASH_TABLE_ACCUMULATE
|
#ifdef USE_HASH_TABLE_ACCUMULATE
|
||||||
bs->info.accum_steps = BCHUNK_HASH_TABLE_ACCUMULATE_STEPS - 1;
|
/* One is always subtracted from this `accum_steps`, this is intentional
|
||||||
/* Triangle number, identifying now much read-ahead we need:
|
* as it results in reading ahead the expected amount. */
|
||||||
* https://en.wikipedia.org/wiki/Triangular_number (+ 1) */
|
if (stride <= sizeof(int8_t)) {
|
||||||
bs->info.accum_read_ahead_len =
|
bs->info.accum_steps = BCHUNK_HASH_TABLE_ACCUMULATE_STEPS_8BITS + 1;
|
||||||
(uint)(((bs->info.accum_steps * (bs->info.accum_steps + 1)) / 2) + 1);
|
}
|
||||||
|
else if (stride <= sizeof(int16_t)) {
|
||||||
|
bs->info.accum_steps = BCHUNK_HASH_TABLE_ACCUMULATE_STEPS_16BITS + 1;
|
||||||
|
}
|
||||||
|
else if (stride <= sizeof(int32_t)) {
|
||||||
|
bs->info.accum_steps = BCHUNK_HASH_TABLE_ACCUMULATE_STEPS_32BITS + 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bs->info.accum_steps = BCHUNK_HASH_TABLE_ACCUMULATE_STEPS_DEFAULT + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
bs->info.accum_steps -= 1;
|
||||||
|
/* Triangle number, identifying now much read-ahead we need:
|
||||||
|
* https://en.wikipedia.org/wiki/Triangular_number (+ 1) */
|
||||||
|
bs->info.accum_read_ahead_len = ((bs->info.accum_steps * (bs->info.accum_steps + 1)) / 2) + 1;
|
||||||
|
/* Only small chunk counts are likely to exceed the read-ahead length. */
|
||||||
|
} while (UNLIKELY(chunk_count < bs->info.accum_read_ahead_len));
|
||||||
|
|
||||||
bs->info.accum_read_ahead_bytes = bs->info.accum_read_ahead_len * stride;
|
bs->info.accum_read_ahead_bytes = bs->info.accum_read_ahead_len * stride;
|
||||||
#else
|
#else
|
||||||
bs->info.accum_read_ahead_bytes = BCHUNK_HASH_LEN * stride;
|
bs->info.accum_read_ahead_bytes = MIN2((size_t)BCHUNK_HASH_LEN, chunk_count) * stride;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bs->memory.chunk_list = BLI_mempool_create(sizeof(BChunkList), 0, 512, BLI_MEMPOOL_NOP);
|
bs->memory.chunk_list = BLI_mempool_create(sizeof(BChunkList), 0, 512, BLI_MEMPOOL_NOP);
|
||||||
@ -1426,6 +1466,8 @@ BArrayStore *BLI_array_store_create(uint stride, uint chunk_count)
|
|||||||
* (we could loop over all states as an alternative). */
|
* (we could loop over all states as an alternative). */
|
||||||
bs->memory.chunk = BLI_mempool_create(sizeof(BChunk), 0, 512, BLI_MEMPOOL_ALLOW_ITER);
|
bs->memory.chunk = BLI_mempool_create(sizeof(BChunk), 0, 512, BLI_MEMPOOL_ALLOW_ITER);
|
||||||
|
|
||||||
|
BLI_assert(bs->info.accum_read_ahead_bytes <= bs->info.chunk_byte_size);
|
||||||
|
|
||||||
return bs;
|
return bs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user