commit d5dc1afde8e99ca425cd9dd0dc6ee8f608ea27f5
parent 322d3145e26a1b71579cba02f8c0f35e636095df
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Wed, 20 Jan 2021 17:23:14 +0100
Upd how volumetric mesh voxelization is parallelised
Share one pool of voxels partition between all threads.
Diffstat:
2 files changed, 32 insertions(+), 51 deletions(-)
diff --git a/src/atrstm_setup_octrees.c b/src/atrstm_setup_octrees.c
@@ -38,7 +38,7 @@
struct build_octree_context {
struct atrstm* atrstm;
- struct pool* pools; /* Per thread pool of voxel partitions */
+ struct pool* pool; /* Pool of voxel partitions */
/* Optical thickness threshold criteria for the merge process */
double tau_threshold;
@@ -254,7 +254,7 @@ static res_T
voxelize_volumetric_mesh
(struct atrstm* atrstm,
const struct atrri_refractive_index* refract_id,
- struct pool* pools)
+ struct pool* pool)
{
struct darray_prims_list prims_list; /* Per thread list of primitives */
const size_t part_def = PARTITION_DEFINITION;
@@ -263,11 +263,12 @@ voxelize_volumetric_mesh
double vol_low[3];
double vol_upp[3];
double vxsz[3];
- uint64_t ipart;
+ int64_t i;
int progress = 0;
+ ATOMIC part_mcode = -1;
ATOMIC nparts_voxelized = 0;
ATOMIC res = RES_OK;
- ASSERT(atrstm && pools);
+ ASSERT(atrstm && pool);
darray_prims_list_init(atrstm->allocator, &prims_list);
@@ -298,9 +299,8 @@ voxelize_volumetric_mesh
* the primitives that intersect it */
omp_set_num_threads((int)atrstm->nthreads);
#pragma omp parallel for schedule(static, 1/*chunk size*/)
- for(ipart = 0; ipart < nparts_adjusted; ++ipart) {
+ for(i = 0; i < (int64_t)nparts_adjusted; ++i) {
struct darray_size_t* prims = NULL;
- struct pool* pool = NULL;
double part_low[3];
double part_upp[3];
uint32_t part_ids[3];
@@ -308,6 +308,7 @@ voxelize_volumetric_mesh
struct part* part = NULL;
int pcent;
size_t n;
+ uint64_t ipart;
res_T res_local = RES_OK;
/* Handle error */
@@ -316,8 +317,8 @@ voxelize_volumetric_mesh
/* Fetch the per thread list of primitives and partition pool */
prims = darray_prims_list_data_get(&prims_list)+ithread;
darray_size_t_clear(prims);
- pool = pools + ithread;
+ ipart = (uint64_t)ATOMIC_INCR(&part_mcode);
morton_xyz_decode_u21(ipart, part_ids);
/* Check that the partition is not out of bound due to Morton indexing */
@@ -354,6 +355,7 @@ voxelize_volumetric_mesh
ATOMIC_SET(&res, res_local);
continue;
}
+
pool_commit_partition(pool, part);
/* Update progress message */
@@ -381,10 +383,9 @@ static void
voxel_get(const size_t xyz[3], const uint64_t mcode, void* dst, void* context)
{
const struct build_octree_context* ctx = context;
- struct pool* pool = NULL;
struct part* part = NULL;
float* vox = NULL;
- uint64_t ivox, ipart, ipool;
+ uint64_t ivox, ipart;
ASSERT(xyz && dst && ctx);
(void)xyz;
@@ -395,16 +396,8 @@ voxel_get(const size_t xyz[3], const uint64_t mcode, void* dst, void* context)
ipart = (mcode >> (LOG2_PARTITION_DEFINITION*3));
ivox = (mcode & (BIT_U64(LOG2_PARTITION_DEFINITION*3)-1));
- /* Compute the pool index containing the partition. Partitions are
- * alternatively stored into the per thread pool. Consequentlu the i^th
- * partition is stored in the (i % #thread)^th pool. */
- ipool = ipart % ctx->atrstm->nthreads;
-
- /* Fetch the pool storing the partition */
- pool = ctx->pools + ipool;
-
/* Fetch the partition storing the voxel */
- part = pool_fetch_partition(pool, ipart);
+ part = pool_fetch_partition(ctx->pool, ipart);
if(!part) { /* An error occurs */
memset(dst, 0, NFLOATS_PER_VOXEL * sizeof(float));
@@ -416,7 +409,7 @@ voxel_get(const size_t xyz[3], const uint64_t mcode, void* dst, void* context)
/* Free the partition if the fetch voxel was its last one */
if(ivox == PARTITION_NVOXELS - 1) {
- pool_free_partition(pool, part);
+ pool_free_partition(ctx->pool, part);
}
}
}
@@ -537,7 +530,7 @@ voxels_challenge_merge
static res_T
build_octree
(struct atrstm* atrstm,
- struct pool* pools)
+ struct pool* pool)
{
struct svx_voxel_desc vox_desc = SVX_VOXEL_DESC_NULL;
struct build_octree_context ctx = BUILD_OCTREE_CONTEXT_NULL;
@@ -545,11 +538,11 @@ build_octree
double upper[3];
size_t definition[3];
res_T res = RES_OK;
- ASSERT(atrstm && pools);
+ ASSERT(atrstm && pool);
/* Setup the build octree context */
ctx.atrstm = atrstm;
- ctx.pools = pools;
+ ctx.pool = pool;
ctx.tau_threshold = atrstm->optical_thickness;
/* Setup the voxel descriptor. TODO in shortwave, the NFLOATS_PER_VOXEL
@@ -580,9 +573,9 @@ static res_T
build_octrees(struct atrstm* atrstm)
{
struct atrri_refractive_index refract_id = ATRRI_REFRACTIVE_INDEX_NULL;
- struct pool* pools = NULL;
- size_t i;
+ struct pool pool;
double wlen;
+ int pool_is_init = 0;
ATOMIC res = RES_OK;
ASSERT(atrstm && check_octrees_parameters(atrstm));
@@ -596,21 +589,18 @@ build_octrees(struct atrstm* atrstm)
res = atrri_fetch_refractive_index(atrstm->atrri, wlen, &refract_id);
if(res != RES_OK) goto error;
- /* Allocate the per thread pool of partition */
- pools = MEM_CALLOC(atrstm->allocator, atrstm->nthreads, sizeof(*pools));
- if(!pools) { res = RES_MEM_ERR; goto error; }
- FOR_EACH(i, 0, atrstm->nthreads) {
- res = pool_init(atrstm->allocator, pools+i);
- if(res != RES_OK) {
- log_err(atrstm,
- "Error initializing the pool of voxel partitions -- %s.\n",
- res_to_cstr((res_T)res));
- goto error;
- }
+ /* Initialise the pool of partitions */
+ res = pool_init(atrstm->allocator, 16 * atrstm->nthreads, &pool);
+ if(res != RES_OK) {
+ log_err(atrstm,
+ "Error initializing the pool of voxel partitions -- %s.\n",
+ res_to_cstr((res_T)res));
+ goto error;
}
+ pool_is_init = 1;
log_info(atrstm,
- "Evaluating and partitionning the field of optical properties.\n");
+ "Evaluate and partition the field of optical properties.\n");
omp_set_nested(1); /* Enable nested threads for voxelize_volumetric_mesh */
#pragma omp parallel sections num_threads(2)
@@ -618,28 +608,22 @@ build_octrees(struct atrstm* atrstm)
#pragma omp section
{
const res_T res_local = voxelize_volumetric_mesh
- (atrstm, &refract_id, pools);
+ (atrstm, &refract_id, &pool);
if(res_local != RES_OK) {
- size_t ipool;
log_err(atrstm, "Error voxelizing the volumetric mesh -- %s\n",
res_to_cstr(res_local));
- FOR_EACH(ipool, 0, atrstm->nthreads) {
- pool_invalidate(pools+ipool);
- }
+ pool_invalidate(&pool);
ATOMIC_SET(&res, res_local);
}
}
#pragma omp section
{
- const res_T res_local = build_octree(atrstm, pools);
+ const res_T res_local = build_octree(atrstm, &pool);
if(res_local != RES_OK) {
- size_t ipool;
log_err(atrstm, "Error building the octree -- %s\n",
res_to_cstr(res_local));
- FOR_EACH(ipool, 0, atrstm->nthreads) {
- pool_invalidate(pools+ipool);
- }
+ pool_invalidate(&pool);
ATOMIC_SET(&res, res_local);
}
}
@@ -661,10 +645,7 @@ build_octrees(struct atrstm* atrstm)
}
exit:
- if(pools) {
- FOR_EACH(i, 0, atrstm->nthreads) pool_release(pools+i);
- MEM_RM(atrstm->allocator, pools);
- }
+ if(pool_is_init) pool_release(&pool);
return (res_T)res;
error:
goto exit;
diff --git a/src/atrstm_setup_uvm.c b/src/atrstm_setup_uvm.c
@@ -68,7 +68,7 @@ setup_unstructured_volumetric_mesh
res_T res = RES_OK;
ASSERT(atrstm && sth_filename && out_volume);
- log_info(atrstm, "Loading and structuring the volumetric mesh '%s'\n",
+ log_info(atrstm, "Load and structure the volumetric mesh '%s'\n",
sth_filename);
time_current(&t0);