star-sp

Random number generators and distributions
git clone git://git.meso-star.fr/star-sp.git
Log | Files | Refs | README | LICENSE

commit 81387afd63319f66c55c3563640a497de14b954f
parent 80802ec9c8d00afb60791abddf4ba75614f21450
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue, 28 Nov 2017 16:07:56 +0100

Add the ssp_rng_proxy_create2 function

This function allows to tune the proxy allocator: size of a block,
number of buckets in a block, etc.

Diffstat:
Msrc/ssp.h | 10++++++++++
Msrc/ssp_rng_proxy.c | 58+++++++++++++++++++++++++++++++++++++++++++---------------
2 files changed, 53 insertions(+), 15 deletions(-)

diff --git a/src/ssp.h b/src/ssp.h @@ -236,6 +236,16 @@ ssp_rng_proxy_create_from_rng struct ssp_rng_proxy** proxy); SSP_API res_T +ssp_rng_proxy_create2 + (struct mem_allocator* mem_allocator, + const struct ssp_rng_type* type, + const size_t block_offset, /* #RNs before the 1st valid block */ + const size_t block_size, /* #RNs in a block */ + const size_t block_pitch, /* #RNs between 2 consecutive blocks */ + const size_t nbuckets, /* #buckets in a block */ + struct ssp_rng_proxy** out_proxy); + +SSP_API res_T ssp_rng_proxy_read (struct ssp_rng_proxy* proxy, FILE* stream); diff --git a/src/ssp_rng_proxy.c b/src/ssp_rng_proxy.c @@ -38,7 +38,7 @@ #include <limits.h> -#define BUCKET_SIZE 1000000 +#define BUCKET_SIZE_DEFAULT 1000000 /* FIFO list of RNG states */ struct rng_state_cache { @@ -56,12 +56,13 @@ enum rng_proxy_sig { /* A proxy manages a list of N independent RNGs of the same type named buckets. * One ensure that each bucket have independent `infinite' random numbers by * partitioning a unique random sequence in N random pools, each containing - * BUCKET_SIZE random numbers. When a bucket has no more random number in its - * affected pool, it silently retrieves a new pool of BUCKET_SIZE random + * `bucket_size' random numbers. When a bucket has no more random number in its + * affected pool, it silently retrieves a new pool of `bucket_size' random * numbers from the proxy. * * Mapping of the partitions of the unique random sequence to N buckets - * BUCKET_SIZE + * + * bucket_size * / \ * +---------+---------+- -+---------+---------+---------+- * | Bucket0 | Bucket1 | ... |BucketN-1| Bucket0 | Bucket1 | ... @@ -74,6 +75,8 @@ struct ssp_rng_proxy { /* The following arrays have the same size */ ATOMIC* buckets; /* Flag that defines which bucket RNGs are created */ + size_t block_bias; /* #RNs to discard between 2 consecutive pools */ + size_t bucket_size; /* #random numbers per bucket */ struct ssp_rng** pools; /* `type' RNGs wrapped by bucket RNGs */ struct rng_state_cache* states; /* Cache of `type' RNG states */ @@ -84,18 +87,20 @@ struct ssp_rng_proxy { ref_T ref; }; -/* Return a RNG with a pool of BUCKET_SIZE indenpendant random numbers. Each +/* Return a RNG with a pool of `bucket_size' indenpendant random numbers. Each * pool are ensure to be independant per `bucket_id' in [0, N) and per function * call, i.e. calling this function X times with the same bucket_id will * provide X different random pools. * - * BUCKET_SIZE - * / \ - * +------------+- -+------------+------------+- - * | Bucket 0 | ... | Bucket N-1 | Bucket 0 | ... - * | 1st pool | | 1st pool | 2nd pool | - * +------------+- -+------------+------------+- - * Unique random sequences */ + * bucket_size block_bias + * / \ / \ + * +-----+------------+- -+------------+----+------------+- + * |#####| Bucket 0 | ... | Bucket N-1 |####| Bucket 0 | ... + * |#####| 1st pool | | 1st pool |####| 2nd pool | + * +-----+------------+- -+------------+----+------------+- + * \ / \____________block_size_______/ + * block \___________block_pitch___________/ + * offset */ static struct ssp_rng* rng_proxy_next_ran_pool (struct ssp_rng_proxy* proxy, @@ -167,7 +172,7 @@ rng_state_cache_write(struct rng_state_cache* cache, struct ssp_rng* rng) * RNG that control the scheduling of random number pools for a given bucket ******************************************************************************/ struct rng_bucket { - struct ssp_rng* pool; /* Wrapped RNG providing a pool of BUCKET_SIZE RNs */ + struct ssp_rng* pool; /* Wrapped RNG providing a pool of `bucket_size' RNs */ struct ssp_rng_proxy* proxy; /* The RNG proxy */ size_t name; /* Unique bucket identifier in [0, #buckets) */ size_t count; /* Remaining unique random numbers in `pool' */ @@ -190,7 +195,7 @@ rng_bucket_next_ran_pool(struct rng_bucket* rng) { ASSERT(rng); rng->pool = rng_proxy_next_ran_pool(rng->proxy, rng->name); - rng->count = BUCKET_SIZE; + rng->count = rng->proxy->bucket_size; } static res_T @@ -301,8 +306,9 @@ rng_proxy_next_ran_pool FOR_EACH(ibucket, 0, sa_size(proxy->states)) { res = rng_state_cache_write(proxy->states + ibucket, proxy->rng); if(res != RES_OK) FATAL("RNG proxy: cannot write to state cache\n"); - ssp_rng_discard(proxy->rng, BUCKET_SIZE); + ssp_rng_discard(proxy->rng, proxy->bucket_size); } + ssp_rng_discard(proxy->rng, proxy->block_bias); } /* Read the RNG pool state of `bucket_name' */ @@ -385,6 +391,21 @@ ssp_rng_proxy_create const size_t nbuckets, struct ssp_rng_proxy** out_proxy) { + const size_t sz = BUCKET_SIZE_DEFAULT * nbuckets; + return ssp_rng_proxy_create2 + (mem_allocator, type, 0, sz, sz, nbuckets, out_proxy); +} + +res_T +ssp_rng_proxy_create2 + (struct mem_allocator* mem_allocator, + const struct ssp_rng_type* type, + const size_t block_offset, /* #RNs before the 1st valid block */ + const size_t block_size, /* #RNs in a block */ + const size_t block_pitch, /* #RNs between 2 consecutive blocks */ + const size_t nbuckets, /* #buckets in a block */ + struct ssp_rng_proxy** out_proxy) +{ struct mem_allocator* allocator = NULL; struct ssp_rng_proxy* proxy = NULL; size_t i; @@ -404,11 +425,16 @@ ssp_rng_proxy_create } proxy->allocator = allocator; ref_init(&proxy->ref); + proxy->bucket_size = block_size / nbuckets; + proxy->block_bias = block_pitch - (proxy->bucket_size * nbuckets); res = ssp_rng_create(allocator, type, &proxy->rng); if(res != RES_OK) goto error; proxy->type = *type; + res = ssp_rng_discard(proxy->rng, block_offset); + if(res != RES_OK) goto error; + proxy->mutex = mutex_create(); if(!proxy->mutex) { res = RES_MEM_ERR; @@ -461,6 +487,8 @@ ssp_rng_proxy_create_from_rng } proxy->allocator = allocator; ref_init(&proxy->ref); + proxy->bucket_size = BUCKET_SIZE_DEFAULT; + proxy->block_bias = 0; res = ssp_rng_get_type(rng, &type); if(res != RES_OK) goto error;