htrdr

Solving radiative transfer in heterogeneous media
git clone git://git.meso-star.fr/htrdr.git
Log | Files | Refs | README | LICENSE

commit bddd7fdd86dfbbeb73ef43b974ef6384538ce0ff
parent 9fb45f8fb33244c05c12f37a110a09249b790b48
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 17 Apr 2019 09:54:31 +0200

Estimate the time per realisation for each pixel

Diffstat:
Msrc/htrdr.c | 49++++++++++++++++++++++++++++++-------------------
Msrc/htrdr_draw_radiance_sw.c | 35++++++++++++++++++++++++-----------
Msrc/htrdr_solve.h | 25++++++++++++++++++++++++-
3 files changed, 78 insertions(+), 31 deletions(-)

diff --git a/src/htrdr.c b/src/htrdr.c @@ -102,6 +102,7 @@ static res_T dump_accum_buffer (struct htrdr* htrdr, struct htrdr_buffer* buf, + struct htrdr_accum* time_acc, /* May be NULL */ const char* stream_name, FILE* stream) { @@ -112,34 +113,34 @@ dump_accum_buffer (void)stream_name; htrdr_buffer_get_layout(buf, &layout); - if(layout.elmt_size != sizeof(struct htrdr_accum[3])/*#channels*/ - || layout.alignment < ALIGNOF(struct htrdr_accum[3])) { + if(layout.elmt_size != sizeof(struct htrdr_accum[4])/*#channels*/ + || layout.alignment < ALIGNOF(struct htrdr_accum[4])) { htrdr_log_err(htrdr, "%s: invalid buffer layout. " - "The pixel size must be the size of an accumulator.\n", + "The pixel size must be the size of 4 accumulators.\n", FUNC_NAME); res = RES_BAD_ARG; goto error; } fprintf(stream, "%lu %lu\n", layout.width, layout.height); + + if(time_acc) *time_acc = HTRDR_ACCUM_NULL; FOR_EACH(y, 0, layout.height) { FOR_EACH(x, 0, layout.width) { const struct htrdr_accum* accums = htrdr_buffer_at(buf, x, y); int i; - FOR_EACH(i, 0, 3) { - const double N = (double)accums[i].nweights; - double E = 0; - double V = 0; - double SE = 0; - - if(accums[i].nweights) { - E = accums[i].sum_weights / N; - V = MMAX(accums[i].sum_weights_sqr / N - E*E, 0); - SE = sqrt(V/N); - } + FOR_EACH(i, 0, 4) { + double E, SE; + + htrdr_accum_get_estimation(&accums[i], &E, &SE); fprintf(stream, "%g %g ", E, SE); } + if(time_acc) { + time_acc->sum_weights += accums[3].sum_weights; + time_acc->sum_weights_sqr += accums[3].sum_weights_sqr; + time_acc->nweights += accums[3].nweights; + } fprintf(stream, "\n"); } fprintf(stream, "\n"); @@ -527,12 +528,15 @@ htrdr_init /* Create the image buffer only on the master process; the image parts * rendered by the processes are gathered onto the master process. */ if(!htrdr->dump_vtk && htrdr->mpi_rank == 0) { + /* 4 accums: X, Y, Z components and one more for the per realisation time */ + const size_t pixsz = sizeof(struct htrdr_accum[4]); + const size_t pixal = ALIGNOF(struct htrdr_accum[4]); res = htrdr_buffer_create(htrdr, args->image.definition[0], /* Width */ args->image.definition[1], /* Height */ - args->image.definition[0]*sizeof(struct htrdr_accum[3]), /* Pitch */ - sizeof(struct htrdr_accum[3]), - ALIGNOF(struct htrdr_accum[3]), /* Alignment */ + args->image.definition[0] * pixsz, /* Pitch */ + pixsz, /* Size of a pixel */ + pixal, /* Alignment of a pixel */ &htrdr->buf); if(res != RES_OK) goto error; } @@ -629,9 +633,16 @@ htrdr_run(struct htrdr* htrdr) htrdr->height, htrdr->spp, htrdr->buf); if(res != RES_OK) goto error; if(htrdr->mpi_rank == 0) { - res = dump_accum_buffer - (htrdr, htrdr->buf, str_cget(&htrdr->output_name), htrdr->output); + struct htrdr_accum path_time_acc = HTRDR_ACCUM_NULL; + double E, SE; + + res = dump_accum_buffer(htrdr, htrdr->buf, &path_time_acc, + str_cget(&htrdr->output_name), htrdr->output); if(res != RES_OK) goto error; + + htrdr_accum_get_estimation(&path_time_acc, &E, &SE); + htrdr_log(htrdr, + "Time per radiative path (in micro seconds): %g +/- %g\n", E, SE); } } exit: diff --git a/src/htrdr_draw_radiance_sw.c b/src/htrdr_draw_radiance_sw.c @@ -92,7 +92,7 @@ tile_create(struct mem_allocator* allocator) const size_t tile_sz = sizeof(struct tile) - sizeof(struct htrdr_accum)/*rm dummy accum*/; const size_t buf_sz = /* Flexiblbe array element */ - TILE_SIZE*TILE_SIZE*sizeof(struct htrdr_accum)*3/*#channels*/; + TILE_SIZE*TILE_SIZE*sizeof(struct htrdr_accum[4/*#channels*/]); ASSERT(allocator); tile = MEM_ALLOC(allocator, tile_sz+buf_sz); @@ -135,7 +135,7 @@ tile_at const size_t y) /* In tile space */ { ASSERT(tile && x < TILE_SIZE && y < TILE_SIZE); - return tile->data.accums + (y*TILE_SIZE + x)*3/*#channels*/; + return tile->data.accums + (y*TILE_SIZE + x)*4/*#channels*/; } static void @@ -150,6 +150,8 @@ write_tile_data(struct htrdr_buffer* buf, const struct tile_data* tile_data) htrdr_buffer_get_layout(buf, &layout); buf_mem = htrdr_buffer_get_data(buf); + ASSERT(layout.elmt_size == sizeof(struct htrdr_accum[4])); + /* Compute the row/column of the tile origin into the buffer */ icol = tile_data->x * (size_t)TILE_SIZE; @@ -163,9 +165,9 @@ write_tile_data(struct htrdr_buffer* buf, const struct tile_data* tile_data) FOR_EACH(irow_tile, 0, nrows_tile) { char* buf_row = buf_mem + (irow + irow_tile) * layout.pitch; const struct htrdr_accum* tile_row = - tile_data->accums + irow_tile*TILE_SIZE*3/*#channels*/; - memcpy(buf_row + icol*sizeof(struct htrdr_accum)*3, tile_row, - ncols_tile*sizeof(struct htrdr_accum)*3/*#channels*/); + tile_data->accums + irow_tile*TILE_SIZE*4/*#channels*/; + memcpy(buf_row + icol*sizeof(struct htrdr_accum[4/*#channels*/]), tile_row, + ncols_tile*sizeof(struct htrdr_accum[4/*#channels*/])); } } @@ -391,7 +393,7 @@ mpi_gather_tiles /* Compute the size of the tile_data */ const size_t msg_sz = sizeof(struct tile_data) - sizeof(struct htrdr_accum)/*dummy*/ - + TILE_SIZE*TILE_SIZE*sizeof(struct htrdr_accum)*3/*#channels*/; + + TILE_SIZE*TILE_SIZE*sizeof(struct htrdr_accum[4/*#channels*/]); struct list_node* node = NULL; struct tile* tile = NULL; @@ -480,7 +482,8 @@ draw_tile /* Fetch and reset the pixel accumulator */ pix_accums = tile_at(tile, ipix_tile[0], ipix_tile[1]); - + pix_accums[3] = HTRDR_ACCUM_NULL; /* Reset time per radiative path */ + /* Compute the pixel coordinate */ ipix[0] = tile_org[0] + ipix_tile[0]; ipix[1] = tile_org[1] + ipix_tile[1]; @@ -490,12 +493,14 @@ draw_tile pix_accums[ichannel] = HTRDR_ACCUM_NULL; FOR_EACH(isamp, 0, spp) { + struct time t0, t1; double pix_samp[2]; double ray_org[3]; double ray_dir[3]; double weight; size_t iband; size_t iquad; + double usec; /* Sample a position into the pixel, in the normalized image plane */ pix_samp[0] = ((double)ipix[0] + ssp_rng_canonical(rng)) * pix_sz[0]; @@ -523,14 +528,22 @@ draw_tile } /* Compute the radiance that reach the pixel through the ray */ + time_current(&t0); weight = htrdr_compute_radiance_sw (htrdr, ithread, rng, ray_org, ray_dir, iband, iquad); ASSERT(weight >= 0); + time_sub(&t0, time_current(&t1), &t0); + usec = (double)time_val(&t0, TIME_NSEC) * 0.001; - /* Update the pixel accumulator */ + /* Update the pixel accumulator of the current channel */ pix_accums[ichannel].sum_weights += weight; pix_accums[ichannel].sum_weights_sqr += weight*weight; pix_accums[ichannel].nweights += 1; + + /* Update the pixel accumulator of per realisation time */ + pix_accums[3].sum_weights += usec; + pix_accums[3].sum_weights_sqr += usec*usec; + pix_accums[3].nweights += 1; } } } @@ -724,11 +737,11 @@ htrdr_draw_radiance_sw ASSERT(layout.width || layout.height || layout.elmt_size); ASSERT(layout.width == width && layout.height == height); - if(layout.elmt_size != sizeof(struct htrdr_accum[3])/*#channels*/ - || layout.alignment < ALIGNOF(struct htrdr_accum[3])) { + if(layout.elmt_size != sizeof(struct htrdr_accum[4])/*#channels*/ + || layout.alignment < ALIGNOF(struct htrdr_accum[4])) { htrdr_log_err(htrdr, "%s: invalid buffer layout. " - "The pixel size must be the size of 3 * accumulators.\n", + "The pixel size must be the size of 4 accumulators.\n", FUNC_NAME); res = RES_BAD_ARG; goto error; diff --git a/src/htrdr_solve.h b/src/htrdr_solve.h @@ -51,7 +51,7 @@ htrdr_draw_radiance_sw const size_t width, /* Image width */ const size_t height, /* Image height */ const size_t spp, /* #samples per pixel, i.e. #realisations */ - /* Buffer of struct htrdr_accum[3]. May be NULL on on non master processes */ + /* Buffer of struct htrdr_accum[4]. May be NULL on non master processes */ struct htrdr_buffer* buf); extern LOCAL_SYM int @@ -62,4 +62,27 @@ htrdr_ground_filter void* ray_data, void* filter_data); +static FINLINE void +htrdr_accum_get_estimation + (const struct htrdr_accum* acc, + double* expected_value, + double* std_err) +{ + ASSERT(acc && expected_value && std_err); + + if(!acc->nweights) { + *expected_value = 0; + *std_err = 0; + } else { + const double N = (double)acc->nweights; + double E, V, SE; + E = acc->sum_weights / N; + V = MMAX(acc->sum_weights_sqr / N - E*E, 0); + SE = sqrt(V/N); + + *expected_value = E; + *std_err = SE; + } +} + #endif /* HTRDR_SOLVE_H */