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:
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;