commit 4e5c10ed6a84867a69389ac759aa1e63dbbcf429
parent af818c77a71be4303f5631cce7c4c19aaeac0967
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Fri, 28 Aug 2015 14:39:26 +0200
Add the setting of the internal RNG type
The RNG type is configurable at the creation of the SMC device and can be
updated with the smc_device_set_rng_type function.
Diffstat:
7 files changed, 111 insertions(+), 29 deletions(-)
diff --git a/src/smc.h b/src/smc.h
@@ -59,6 +59,7 @@
struct logger;
struct mem_allocator;
struct ssp_rng;
+struct ssp_rng_type;
/* Generic type descriptor */
struct smc_type {
@@ -139,6 +140,7 @@ smc_device_create
(struct logger* logger, /* May be NULL <=> use default logger */
struct mem_allocator* allocator, /* May be NULL <=> use default allocator */
const unsigned nthreads_hint, /* Hint on the number of threads to use */
+ const struct ssp_rng_type* type, /* May be NULL <=> use default RNG type */
struct smc_device** dev);
SMC_API res_T
@@ -149,6 +151,11 @@ SMC_API res_T
smc_device_ref_put
(struct smc_device* dev);
+SMC_API res_T
+smc_device_set_rng_type
+ (struct smc_device* dev,
+ const struct ssp_rng_type* type);
+
/*******************************************************************************
* Integration API
******************************************************************************/
diff --git a/src/smc_device.c b/src/smc_device.c
@@ -43,17 +43,34 @@
* Helper functions
******************************************************************************/
static void
+release_rngs(struct smc_device* dev)
+{
+ size_t i;
+ ASSERT(dev);
+ if(dev->rng_proxy) {
+ ssp_rng_proxy_ref_put(dev->rng_proxy);
+ dev->rng_proxy = NULL;
+ }
+ if(dev->rngs) {
+ ASSERT(dev->nthreads == sa_size(dev->rngs));
+ FOR_EACH(i, 0, dev->nthreads) {
+ if(dev->rngs[i]) {
+ ssp_rng_ref_put(dev->rngs[i]);
+ dev->rngs[i] = NULL;
+ }
+ }
+ sa_release(dev->rngs);
+ dev->rngs = NULL;
+ }
+}
+
+static void
device_release(ref_T* ref)
{
struct smc_device* dev;
- size_t i;
ASSERT(ref);
dev = CONTAINER_OF(ref, struct smc_device, ref);
- if(dev->rng_proxy) ssp_rng_proxy_ref_put(dev->rng_proxy);
- FOR_EACH(i, 0, sa_size(dev->rngs)) {
- ssp_rng_ref_put(dev->rngs[i]);
- }
- sa_release(dev->rngs);
+ release_rngs(dev);
MEM_RM(dev->allocator, dev);
}
@@ -65,11 +82,11 @@ smc_device_create
(struct logger* logger,
struct mem_allocator* mem_allocator,
const unsigned nthreads_hint,
+ const struct ssp_rng_type* rng_type,
struct smc_device** out_dev)
{
struct smc_device* dev = NULL;
struct mem_allocator* allocator;
- unsigned i, nthreads;
res_T res = RES_OK;
if(!out_dev || !nthreads_hint) {
@@ -86,20 +103,13 @@ smc_device_create
dev->allocator = allocator;
dev->logger = logger ? logger : LOGGER_DEFAULT;
- nthreads = MMIN(nthreads_hint, (unsigned)omp_get_num_procs());
- omp_set_num_threads((int)nthreads);
+ dev->nthreads = MMIN(nthreads_hint, (unsigned)omp_get_num_procs());
+ omp_set_num_threads((int)dev->nthreads);
- res = ssp_rng_proxy_create
- (allocator, &ssp_rng_mt19937_64, nthreads, &dev->rng_proxy);
+ res = smc_device_set_rng_type(dev, rng_type ? rng_type : &ssp_rng_threefry);
if(res != RES_OK)
goto error;
- dev->rngs = sa_add(dev->rngs, nthreads);
- FOR_EACH(i, 0, nthreads) {
- res = ssp_rng_proxy_create_rng(dev->rng_proxy, i, dev->rngs + i);
- if(res != RES_OK) goto error;
- }
-
exit:
if(out_dev) *out_dev = dev;
return res;
@@ -127,3 +137,53 @@ smc_device_ref_put(struct smc_device* dev)
return RES_OK;
}
+res_T
+smc_device_set_rng_type(struct smc_device* dev, const struct ssp_rng_type* type)
+{
+ size_t i;
+ res_T res = RES_OK;
+ struct ssp_rng_proxy* proxy = NULL;
+ struct ssp_rng** rngs = NULL;
+
+ if(!dev || !type) {
+ /* Skip the error block */
+ return RES_BAD_ARG;
+ }
+
+ proxy = dev->rng_proxy;
+ rngs = dev->rngs;
+ dev->rng_proxy = NULL;
+ dev->rngs = NULL;
+
+ /* Create the new rng_proxy */
+ res = ssp_rng_proxy_create
+ (dev->allocator, type, dev->nthreads, &dev->rng_proxy);
+ if(res != RES_OK) goto error;
+
+ /* Create the new per thread rng */
+ dev->rngs = sa_add(dev->rngs, dev->nthreads);
+ memset(dev->rngs, 0, dev->nthreads*sizeof(struct ssp_rng*));
+ FOR_EACH(i, 0, dev->nthreads) {
+ res = ssp_rng_proxy_create_rng(dev->rng_proxy, i, dev->rngs + i);
+ if(res != RES_OK) goto error;
+ }
+
+ /* Release the previous RNG data structure */
+ if(proxy) SSP(rng_proxy_ref_put(proxy));
+ if(rngs) {
+ FOR_EACH(i, 0, dev->nthreads) {
+ if(rngs[i]) SSP(rng_ref_put(rngs[i]));
+ }
+ sa_release(rngs);
+ }
+
+exit:
+ return res;
+error:
+ /* Restore the previous RNG type */
+ release_rngs(dev);
+ dev->rng_proxy = proxy;
+ dev->rngs = rngs;
+ goto exit;
+}
+
diff --git a/src/smc_device_c.h b/src/smc_device_c.h
@@ -40,6 +40,7 @@ struct smc_device {
struct ssp_rng** rngs;
struct logger* logger;
struct mem_allocator* allocator;
+ size_t nthreads;
ref_T ref;
};
diff --git a/src/test_smc_device.c b/src/test_smc_device.c
@@ -31,6 +31,8 @@
#include <rsys/logger.h>
+#include <star/ssp.h>
+
static void
log_stream(const char* msg, void* ctx)
{
@@ -47,8 +49,8 @@ main(int argc, char** argv)
struct smc_device* dev;
(void)argc, (void)argv;
- CHECK(smc_device_create(NULL, NULL, SMC_NTHREADS_DEFAULT, NULL), RES_BAD_ARG);
- CHECK(smc_device_create(NULL, NULL, SMC_NTHREADS_DEFAULT, &dev), RES_OK);
+ CHECK(smc_device_create(NULL, NULL, SMC_NTHREADS_DEFAULT, NULL, NULL), RES_BAD_ARG);
+ CHECK(smc_device_create(NULL, NULL, SMC_NTHREADS_DEFAULT, NULL, &dev), RES_OK);
CHECK(smc_device_ref_get(NULL), RES_BAD_ARG);
CHECK(smc_device_ref_get(dev), RES_OK);
@@ -56,13 +58,13 @@ main(int argc, char** argv)
CHECK(smc_device_ref_put(dev), RES_OK);
CHECK(smc_device_ref_put(dev), RES_OK);
- CHECK(smc_device_create(NULL, NULL, 0, &dev), RES_BAD_ARG);
+ CHECK(smc_device_create(NULL, NULL, 0, NULL, &dev), RES_BAD_ARG);
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
CHECK(MEM_ALLOCATED_SIZE(&allocator), 0);
- CHECK(smc_device_create(NULL, &allocator, 1, NULL), RES_BAD_ARG);
- CHECK(smc_device_create(NULL, &allocator, 1, &dev), RES_OK);
+ CHECK(smc_device_create(NULL, &allocator, 1, NULL, NULL), RES_BAD_ARG);
+ CHECK(smc_device_create(NULL, &allocator, 1, NULL, &dev), RES_OK);
CHECK(smc_device_ref_put(dev), RES_OK);
CHECK(MEM_ALLOCATED_SIZE(&allocator), 0);
@@ -71,12 +73,21 @@ main(int argc, char** argv)
logger_set_stream(&logger, LOG_ERROR, log_stream, NULL);
logger_set_stream(&logger, LOG_WARNING, log_stream, NULL);
- CHECK(smc_device_create(&logger, NULL, 1, NULL), RES_BAD_ARG);
- CHECK(smc_device_create(&logger, NULL, 1, &dev), RES_OK);
+ CHECK(smc_device_create(&logger, NULL, 1, NULL, NULL), RES_BAD_ARG);
+ CHECK(smc_device_create(&logger, NULL, 1, NULL, &dev), RES_OK);
+ CHECK(smc_device_ref_put(dev), RES_OK);
+
+ CHECK(smc_device_create(&logger, &allocator, 4, NULL, NULL), RES_BAD_ARG);
+ CHECK(smc_device_create(&logger, &allocator, 4, NULL, &dev), RES_OK);
+
+ CHECK(smc_device_set_rng_type(NULL, NULL), RES_BAD_ARG);
+ CHECK(smc_device_set_rng_type(dev, NULL), RES_BAD_ARG);
+ CHECK(smc_device_set_rng_type(NULL, &ssp_rng_ranlux48), RES_BAD_ARG);
+ CHECK(smc_device_set_rng_type(dev, &ssp_rng_ranlux48), RES_OK);
+ CHECK(smc_device_set_rng_type(dev, &ssp_rng_kiss), RES_OK);
CHECK(smc_device_ref_put(dev), RES_OK);
- CHECK(smc_device_create(&logger, &allocator, 4, NULL), RES_BAD_ARG);
- CHECK(smc_device_create(&logger, &allocator, 4, &dev), RES_OK);
+ CHECK(smc_device_create(&logger, &allocator, 4, &ssp_rng_ranlux48, &dev), RES_OK);
CHECK(smc_device_ref_put(dev), RES_OK);
logger_release(&logger);
diff --git a/src/test_smc_integrate.c b/src/test_smc_integrate.c
@@ -110,7 +110,8 @@ main(int argc, char** argv)
(void)argc, (void)argv;
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
- CHECK(smc_device_create(NULL, &allocator, SMC_NTHREADS_DEFAULT, &dev), RES_OK);
+ CHECK(smc_device_create(NULL, &allocator, SMC_NTHREADS_DEFAULT, NULL, &dev),
+ RES_OK);
integrator.integrand = rcp_x;
integrator.type = &smc_accum_dbl2;
diff --git a/src/test_smc_light_path.c b/src/test_smc_light_path.c
@@ -372,7 +372,8 @@ main(int argc, char** argv)
CHECK(s3d_scene_begin_trace(scn), RES_OK);
- CHECK(smc_device_create(NULL, &allocator, SMC_NTHREADS_DEFAULT, &smc), RES_OK);
+ CHECK(smc_device_create(NULL, &allocator, SMC_NTHREADS_DEFAULT, NULL, &smc),
+ RES_OK);
integrator.integrand = light_path_integrator;
integrator.type = &smc_float;
diff --git a/src/test_smc_solve.c b/src/test_smc_solve.c
@@ -70,7 +70,8 @@ main(int argc, char** argv)
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
- CHECK(smc_device_create(NULL, &allocator, SMC_NTHREADS_DEFAULT, &dev), RES_OK);
+ CHECK(smc_device_create(NULL, &allocator, SMC_NTHREADS_DEFAULT, NULL, &dev),
+ RES_OK);
integrator.integrand = rcp_x;
integrator.type = &smc_double;