star-mc

Parallel estimation of Monte Carlo integrators
git clone git://git.meso-star.fr/star-mc.git
Log | Files | Refs | README | LICENSE

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:
Msrc/smc.h | 7+++++++
Msrc/smc_device.c | 94++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
Msrc/smc_device_c.h | 1+
Msrc/test_smc_device.c | 29++++++++++++++++++++---------
Msrc/test_smc_integrate.c | 3++-
Msrc/test_smc_light_path.c | 3++-
Msrc/test_smc_solve.c | 3++-
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;