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