star-mc

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

commit 537e23b9d2c5f727871a808ee8cdb2f22c72a6cb
parent 1f624d506b3978b9681b523d18cec60a260b8d93
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed,  8 Apr 2015 15:46:17 +0200

Add the smc_solve_N function

Use basic parallelism

Diffstat:
Mcmake/CMakeLists.txt | 11+++++++++++
Msrc/smc.h | 9+++++++++
Msrc/smc_integrator.c | 22++++++++++++++++++++++
Msrc/test_smc_light_path.c | 74+++++++++++++++++++++++++++++++++++++++++++++-----------------------------
4 files changed, 87 insertions(+), 29 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -43,9 +43,14 @@ find_package(RCMake 0.1 REQUIRED) find_package(RSys 0.1.1 REQUIRED) find_package(StarSP REQUIRED) find_package(Star3D) +find_package(OpenMP) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${RCMAKE_SOURCE_DIR}) include(rcmake) +if(NOT OPENMP_FOUND) + message(STATUS "No OpenMP support: muti-threading is disabled") +endif() + include_directories(${RSys_INCLUDE_DIR} ${StarSP_INCLUDE_DIR}) ################################################################################ @@ -77,6 +82,12 @@ set_target_properties(smc PROPERTIES VERSION ${VERSION} SOVERSION ${VERSION_MAJOR}) +if(OPENMP_FOUND) + set_target_properties(smc PROPERTIES + COMPILE_FLAGS ${OpenMP_C_FLAGS} + LINK_FLAGS ${OpenMP_C_FLAGS}) +endif() + target_link_libraries(smc RSys StarSP) if(CMAKE_COMPILER_IS_GNUCC) target_link_libraries(smc m) diff --git a/src/smc.h b/src/smc.h @@ -132,6 +132,15 @@ smc_solve struct smc_estimator** estimator); SMC_API res_T +smc_solve_N + (struct smc_device* dev, + struct smc_integrator* integrator, + const size_t count, + void* contexts, + const size_t sizeof_context, + struct smc_estimator* estimators[]); + +SMC_API res_T smc_estimator_ref_get (struct smc_estimator* estimator); diff --git a/src/smc_integrator.c b/src/smc_integrator.c @@ -169,6 +169,28 @@ error: } res_T +smc_solve_N + (struct smc_device* dev, + struct smc_integrator* integrator, + const size_t count, + void* ctx, + const size_t sizeof_ctx, + struct smc_estimator* estimators[]) +{ + size_t i; + if(!dev || !integrator || !estimators || !count + || !check_integrator(integrator)) { + return RES_BAD_ARG; + } + + #pragma omp parallel for schedule(dynamic) + for(i = 0; i < count; ++i) { + SMC(solve(dev, integrator, (char*)ctx + i*sizeof_ctx, estimators + i)); + } + return RES_OK; +} + +res_T smc_estimator_ref_get(struct smc_estimator* estimator) { if(!estimator) return RES_BAD_ARG; diff --git a/src/test_smc_light_path.c b/src/test_smc_light_path.c @@ -197,7 +197,7 @@ camera_ray ******************************************************************************/ struct integrator_context { struct s3d_scene* scn; - struct camera cam; + struct camera* cam; float pixel_size[2]; /* Normalized pixel size */ size_t ipixel[2]; /* Image space pixel coordinates */ }; @@ -271,7 +271,7 @@ light_path_integrator(void* value, struct ssp_rng* rng, void* data) pix_samp[1] = (float)ssp_rng_uniform_double(rng, pix_lower[1], pix_upper[1]); /* Build a camera ray */ - camera_ray(&ctx->cam, pix_samp, ray_org, ray_dir); + camera_ray(ctx->cam, pix_samp, ray_org, ray_dir); ray_range[0] = 0.f; ray_range[1] = FLT_MAX; @@ -318,13 +318,15 @@ int main(int argc, char** argv) { struct mem_allocator allocator; - struct integrator_context ctx; + struct integrator_context* contexts; struct s3d_device* dev; struct s3d_scene* scn; struct s3d_shape* shape; struct s3d_vertex_data attribs[2]; struct smc_device* smc; struct smc_integrator integrator = SMC_INTEGRATOR_NULL; + struct smc_estimator** estimators; + struct camera cam; unsigned char* img = NULL; size_t ix, iy; float pos[3]; @@ -375,39 +377,53 @@ main(int argc, char** argv) CHECK(smc_device_create(NULL, &allocator, &smc), RES_OK); - camera_init(&ctx.cam); - ctx.scn = scn; - ctx.pixel_size[0] = 1.f / (float)IMG_WIDTH; - ctx.pixel_size[1] = 1.f / (float)IMG_HEIGHT; - integrator.integrand = light_path_integrator; integrator.type = &smc_float; - integrator.max_steps = 1; + integrator.max_steps = 8; + + contexts = MEM_CALLOC + (&allocator, IMG_WIDTH*IMG_HEIGHT, sizeof(struct integrator_context)); + NCHECK(contexts, NULL); + estimators = MEM_CALLOC + (&allocator, IMG_WIDTH*IMG_HEIGHT, sizeof(struct smc_estimators*)); + NCHECK(estimators, NULL); + + camera_init(&cam); FOR_EACH(iy, 0, IMG_HEIGHT) { - ctx.ipixel[1] = iy; - FOR_EACH(ix, 0, IMG_WIDTH) { - struct smc_estimator* estimator; + FOR_EACH(ix, 0, IMG_WIDTH) { + const size_t ictx = iy * IMG_WIDTH + ix; + contexts[ictx].scn = scn; + contexts[ictx].cam = &cam; + contexts[ictx].pixel_size[0] = 1.f / (float)IMG_WIDTH; + contexts[ictx].pixel_size[1] = 1.f / (float)IMG_HEIGHT; + contexts[ictx].ipixel[0] = ix; + contexts[ictx].ipixel[1] = iy; + }} + + CHECK(smc_solve_N(smc, &integrator, IMG_WIDTH * IMG_HEIGHT, contexts, + sizeof(struct integrator_context), estimators), RES_OK); + + FOR_EACH(iy, 0, IMG_HEIGHT) { + FOR_EACH(ix, 0, IMG_WIDTH) { + const size_t iestimator = (iy*IMG_WIDTH + ix); + if(img) { /* Write image pixel */ struct smc_estimator_status status; - ctx.ipixel[0] = ix; - CHECK(smc_solve(smc, &integrator, &ctx, &estimator), RES_OK); - - if(img) { - const size_t ipix = (iy*IMG_WIDTH + ix) * 3/*RGB*/; - float col; - unsigned char colu; - - CHECK(smc_estimator_get_status(estimator, &status), RES_OK); - col = (float)pow(SMC_FLOAT(status.E), 1.0/GAMMA); /* Gamma correction */ - colu = (unsigned char)(CLAMP(col, 0.f, 1.f) * 255.f); /* Float to U8 */ - img[ipix + 0] = colu; - img[ipix + 1] = colu; - img[ipix + 2] = colu; - } - CHECK(smc_estimator_ref_put(estimator), RES_OK); + const size_t ipix = iestimator * 3/*RGB*/; + float col; + unsigned char colu; + + CHECK(smc_estimator_get_status(estimators[iestimator], &status), RES_OK); + col = (float)pow(SMC_FLOAT(status.E), 1.0/GAMMA); /* Gamma correction */ + colu = (unsigned char)(CLAMP(col, 0.f, 1.f) * 255.f); /* Float to U8 */ + img[ipix + 0] = img[ipix + 1] = img[ipix + 2] = colu; } - } + CHECK(smc_estimator_ref_put(estimators[iestimator]), RES_OK); + }} + + MEM_FREE(&allocator, contexts); + MEM_FREE(&allocator, estimators); if(argc > 1) { CHECK(image_ppm_write(argv[1], IMG_WIDTH, IMG_HEIGHT, 3, img), RES_OK); MEM_FREE(&allocator, img);