htrdr

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

commit b304fcd71625e8b630831e54bf20c168036bec24
parent 13595a239be0c313f269dc69916ce97b1baccd47
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Thu, 25 Oct 2018 17:57:00 +0200

Report the progress status of each MPI process

Diffstat:
Msrc/htrdr.c | 111+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/htrdr.h | 4++++
Msrc/htrdr_c.h | 22+++++++++++++++++++++-
Msrc/htrdr_draw_radiance_sw.c | 83++++++++++++++++---------------------------------------------------------------
Msrc/htrdr_sky.c | 38+++++++++++++++++++++++++++-----------
5 files changed, 180 insertions(+), 78 deletions(-)

diff --git a/src/htrdr.c b/src/htrdr.c @@ -248,6 +248,7 @@ spherical_to_cartesian_dir static res_T init_mpi(struct htrdr* htrdr) { + size_t n; int err; res_T res = RES_OK; ASSERT(htrdr); @@ -280,6 +281,29 @@ init_mpi(struct htrdr* htrdr) goto error; } + /* Allocate #processes progress statuses on the master process and only 1 + * progress status on the other ones: the master process will gather the + * status of the other processes to report their progression. */ + n = (size_t)(htrdr->mpi_rank == 0 ? htrdr->mpi_nprocs : 1); + + htrdr->mpi_progress_octree = MEM_CALLOC + (htrdr->allocator, n, sizeof(*htrdr->mpi_progress_octree)); + if(!htrdr->mpi_progress_octree) { + htrdr_log_err(htrdr, + "could not allocate the progress state of the octree building.\n"); + res = RES_MEM_ERR; + goto error; + } + + htrdr->mpi_progress_render = MEM_CALLOC + (htrdr->allocator, n, sizeof(*htrdr->mpi_progress_render)); + if(!htrdr->mpi_progress_render) { + htrdr_log_err(htrdr, + "could not allocate the progress state of the scene rendering.\n"); + res = RES_MEM_ERR; + goto error; + } + exit: return res; error: @@ -451,6 +475,12 @@ htrdr_release(struct htrdr* htrdr) if(htrdr->cam) htrdr_camera_ref_put(htrdr->cam); if(htrdr->buf) htrdr_buffer_ref_put(htrdr->buf); if(htrdr->mpi_err_str) MEM_RM(htrdr->allocator, htrdr->mpi_err_str); + if(htrdr->mpi_progress_octree) { + MEM_RM(htrdr->allocator, htrdr->mpi_progress_octree); + } + if(htrdr->mpi_progress_render) { + MEM_RM(htrdr->allocator, htrdr->mpi_progress_render); + } if(htrdr->lifo_allocators) { size_t i; FOR_EACH(i, 0, htrdr->nthreads) { @@ -757,3 +787,84 @@ error: goto exit; } +void +fetch_mpi_progress(struct htrdr* htrdr, const enum htrdr_mpi_progress tag) +{ + int8_t* progress = NULL; + int iproc; + ASSERT(htrdr && progress && htrdr->mpi_rank == 0); + + switch(tag) { + case HTRDR_MPI_PROGRESS_BUILD_OCTREE: + progress = htrdr->mpi_progress_octree; + break; + case HTRDR_MPI_PROGRESS_RENDERING: + progress = htrdr->mpi_progress_render; + break; + default: FATAL("Unreachable code.\n"); break; + } + + FOR_EACH(iproc, 1, htrdr->mpi_nprocs) { + + /* Flush the last sent percentage of the process `iproc' */ + for(;;) { + int flag; + + CHK(MPI_Iprobe + (iproc, tag, MPI_COMM_WORLD, &flag, MPI_STATUS_IGNORE) == MPI_SUCCESS); + if(flag == 0) break; /* No more message */ + + CHK(MPI_Recv(&progress[iproc], sizeof(size_t), MPI_CHAR, iproc, tag, + MPI_COMM_WORLD, MPI_STATUS_IGNORE) == MPI_SUCCESS); + } + } +} + +void +print_mpi_progress(struct htrdr* htrdr, const enum htrdr_mpi_progress tag) +{ + int iproc; + ASSERT(htrdr && htrdr->mpi_rank == 0); + FOR_EACH(iproc, 0, htrdr->mpi_nprocs) { + switch(tag) { + case HTRDR_MPI_PROGRESS_BUILD_OCTREE: + htrdr_fprintf(htrdr, stderr, + "\033[2K\rProcess %d -- building octree: %3d%%\n", + iproc, htrdr->mpi_progress_octree[iproc]); + break; + case HTRDR_MPI_PROGRESS_RENDERING: + htrdr_fprintf(htrdr, stderr, + "\033[2K\rProcess %d -- rendering: %3d%%\n", + iproc, htrdr->mpi_progress_render[iproc]); + break; + default: FATAL("Unreachable code.\n"); break; + } + } +} + +int8_t +total_mpi_progress(const struct htrdr* htrdr, const enum htrdr_mpi_progress tag) +{ + const int8_t* progress = NULL; + int total = 0; + int iproc; + ASSERT(htrdr && progress && htrdr->mpi_rank == 0); + + switch(tag) { + case HTRDR_MPI_PROGRESS_BUILD_OCTREE: + progress = htrdr->mpi_progress_octree; + break; + case HTRDR_MPI_PROGRESS_RENDERING: + progress = htrdr->mpi_progress_render; + break; + default: FATAL("Unreachable code.\n"); break; + } + + FOR_EACH(iproc, 0, htrdr->mpi_nprocs) { + total += progress[iproc]; + } + total = total / htrdr->mpi_nprocs; + ASSERT(total <= 100); + return (int8_t)total; +} + diff --git a/src/htrdr.h b/src/htrdr.h @@ -65,6 +65,10 @@ struct htrdr { int mpi_nprocs; /* Overall #processes in the MPI group */ char* mpi_err_str; /* Temp buffer used to store MPI error string */ + /* Process progress percentage */ + int8_t* mpi_progress_octree; + int8_t* mpi_progress_render; + struct logger logger; struct mem_allocator* allocator; struct mem_allocator* lifo_allocators; /* Per thread lifo allocator */ diff --git a/src/htrdr_c.h b/src/htrdr_c.h @@ -18,6 +18,11 @@ #include <rsys/rsys.h> +enum htrdr_mpi_progress { + HTRDR_MPI_PROGRESS_BUILD_OCTREE, + HTRDR_MPI_PROGRESS_RENDERING +}; + struct htrdr; #define SW_WAVELENGTH_MIN 380 /* In nanometer */ @@ -96,7 +101,7 @@ is_file_updated extern LOCAL_SYM res_T update_file_stamp - (struct htrdr* htrdr, + (struct htrdr* htrdr, const char* filename); extern LOCAL_SYM res_T @@ -104,5 +109,20 @@ create_directory (struct htrdr* htrdt, const char* path); +extern LOCAL_SYM void +fetch_mpi_progress + (struct htrdr* htrdr, + const enum htrdr_mpi_progress progress); + +extern LOCAL_SYM void +print_mpi_progress + (struct htrdr* htrdr, + const enum htrdr_mpi_progress progress); + +extern int8_t +total_mpi_progress + (const struct htrdr* htrdr, + const enum htrdr_mpi_progress progress); + #endif /* HTRDR_C_H */ diff --git a/src/htrdr_draw_radiance_sw.c b/src/htrdr_draw_radiance_sw.c @@ -208,36 +208,6 @@ draw_tile return RES_OK; } -/* Return the overall percentage */ -static size_t -fetch_process_progress(struct htrdr* htrdr, size_t* progress) -{ - size_t overall_pcent; - int iproc; - ASSERT(htrdr && progress && htrdr->mpi_rank == 0); - - overall_pcent = progress[0]; - FOR_EACH(iproc, 1, htrdr->mpi_nprocs) { - size_t proc_pcent = progress[iproc]; - - /* Flush the last sent percentage of the process `iproc' */ - for(;;) { - int flag; - - CHK(MPI_Iprobe(iproc, 0/*tag*/, MPI_COMM_WORLD, &flag, - MPI_STATUS_IGNORE) == MPI_SUCCESS); - if(flag == 0) break; /* No more message */ - - CHK(MPI_Recv(&proc_pcent, sizeof(size_t), MPI_CHAR, iproc, 0/*tag*/, - MPI_COMM_WORLD, MPI_STATUS_IGNORE) == MPI_SUCCESS); - } - - progress[iproc] = proc_pcent; - overall_pcent += progress[iproc]; - } - return overall_pcent / (size_t)htrdr->mpi_nprocs; -} - /******************************************************************************* * Local functions ******************************************************************************/ @@ -251,13 +221,11 @@ htrdr_draw_radiance_sw struct ssp_rng_proxy* rng_proxy = NULL; struct ssp_rng** rngs = NULL; size_t ntiles_x, ntiles_y, ntiles, ntiles_adjusted; - size_t* progress = NULL; size_t i; int32_t mcode; /* Morton code of the tile */ struct htrdr_buffer_layout layout; double pix_sz[2]; /* Pixel size in the normalized image plane */ size_t spp; - size_t overall_pcent = 0; ATOMIC nsolved_tiles = 0; ATOMIC res = RES_OK; ASSERT(htrdr && cam && buf); @@ -311,20 +279,6 @@ htrdr_draw_radiance_sw } } - if(htrdr->mpi_rank == 0) { - progress = MEM_CALLOC - (htrdr->allocator, (size_t)htrdr->mpi_nprocs, sizeof(size_t)); - } else { - progress = MEM_CALLOC - (htrdr->allocator, 1, sizeof(size_t)); - } - if(!progress) { - htrdr_log_err(htrdr, - "%s: could not allocate the process progress counter.\n", FUNC_NAME); - res = RES_MEM_ERR; - goto error; - } - ntiles_x = (layout.width + (TILE_SIZE-1)/*ceil*/)/TILE_SIZE; ntiles_y = (layout.height+ (TILE_SIZE-1)/*ceil*/)/TILE_SIZE; ntiles_adjusted = round_up_pow2(MMAX(ntiles_x, ntiles_y)); @@ -334,8 +288,10 @@ htrdr_draw_radiance_sw pix_sz[0] = 1.0 / (double)layout.width; pix_sz[1] = 1.0 / (double)layout.height; - htrdr_fprintf(htrdr, stderr, "Rendering: %3i%%", 0); - htrdr_fflush(htrdr, stderr); + if(htrdr->mpi_rank == 0) { + fetch_mpi_progress(htrdr, HTRDR_MPI_PROGRESS_RENDERING); + print_mpi_progress(htrdr, HTRDR_MPI_PROGRESS_RENDERING); + } omp_set_num_threads((int)htrdr->nthreads); #pragma omp parallel for schedule(static, 1/*chunck size*/) @@ -344,9 +300,9 @@ htrdr_draw_radiance_sw struct ssp_rng* rng = rngs[ithread]; size_t tile_org[2]; size_t tile_sz[2]; - size_t pcent; size_t n; res_T res_local = RES_OK; + int8_t pcent; /* Decode the morton code to retrieve the tile index */ tile_org[0] = morton2D_decode((uint32_t)(mcode>>0)); @@ -370,21 +326,19 @@ htrdr_draw_radiance_sw } n = (size_t)ATOMIC_INCR(&nsolved_tiles); - pcent = n * 100 / ntiles; + pcent = (int8_t)(n * 100 / ntiles); #pragma omp critical - if((size_t)pcent > progress[0]) { - progress[0] = pcent; - + if(pcent > htrdr->mpi_progress_render[0]) { + htrdr->mpi_progress_render[0] = pcent; if(htrdr->mpi_rank != 0) { /* Send the progress percentage of the process to the master process */ - CHK(MPI_Send(&pcent, sizeof(size_t), MPI_CHAR, 0/*dst*/, 0/*tag*/, - MPI_COMM_WORLD) == MPI_SUCCESS); + CHK(MPI_Send(&pcent, sizeof(pcent), MPI_CHAR, 0/*dst*/, + HTRDR_MPI_PROGRESS_RENDERING/*tag*/, MPI_COMM_WORLD) == MPI_SUCCESS); } else { - overall_pcent = fetch_process_progress(htrdr, progress); - htrdr_fprintf(htrdr, stderr, "%c[2K\rRendering: %3lu%%", - 27, (unsigned long)overall_pcent); - htrdr_fflush(htrdr, stderr); + fetch_mpi_progress(htrdr, HTRDR_MPI_PROGRESS_RENDERING); + htrdr_fprintf(htrdr, stderr, "\033[%dA", htrdr->mpi_nprocs); + print_mpi_progress(htrdr, HTRDR_MPI_PROGRESS_RENDERING); } } @@ -392,14 +346,12 @@ htrdr_draw_radiance_sw } if(htrdr->mpi_rank == 0) { - while(overall_pcent != 100) { - overall_pcent = fetch_process_progress(htrdr, progress); - htrdr_fprintf(htrdr, stderr, "%c[2K\rRendering: %3lu%%", - 27, (unsigned long)overall_pcent); - htrdr_fflush(htrdr, stderr); + while(total_mpi_progress(htrdr, HTRDR_MPI_PROGRESS_RENDERING) != 100) { + fetch_mpi_progress(htrdr, HTRDR_MPI_PROGRESS_RENDERING); + htrdr_fprintf(htrdr, stderr, "\033[%dA", htrdr->mpi_nprocs); + print_mpi_progress(htrdr, HTRDR_MPI_PROGRESS_RENDERING); sleep(1); } - htrdr_fprintf(htrdr, stderr, "\n"); } /* Gather accum buffers from the group of processes */ @@ -408,7 +360,6 @@ htrdr_draw_radiance_sw exit: if(rng_proxy) SSP(rng_proxy_ref_put(rng_proxy)); - if(progress) MEM_RM(htrdr->allocator, progress); if(rngs) { FOR_EACH(i, 0, htrdr->nthreads) { if(rngs[i]) SSP(rng_ref_put(rngs[i])); diff --git a/src/htrdr_sky.c b/src/htrdr_sky.c @@ -38,6 +38,7 @@ #include <fcntl.h> /* open */ #include <libgen.h> #include <math.h> +#include <mpi.h> #include <omp.h> #include <string.h> #include <sys/stat.h> /* mkdir */ @@ -1076,7 +1077,6 @@ setup_clouds { struct darray_specdata specdata; size_t nvoxs[3]; - size_t progress = 0; double vxsz[3]; double low[3]; double upp[3]; @@ -1205,8 +1205,10 @@ setup_clouds omp_set_num_threads(1); } else { omp_set_num_threads((int)sky->htrdr->nthreads); - htrdr_fprintf(sky->htrdr, stderr, "Building octrees: %3u%%", 0); - htrdr_fflush(sky->htrdr, stderr); + if(sky->htrdr->mpi_rank == 0) { + fetch_mpi_progress(sky->htrdr, HTRDR_MPI_PROGRESS_BUILD_OCTREE); + print_mpi_progress(sky->htrdr, HTRDR_MPI_PROGRESS_BUILD_OCTREE); + } } #pragma omp parallel for for(ispecdata=0; @@ -1217,7 +1219,7 @@ setup_clouds const size_t iband = darray_specdata_data_get(&specdata)[ispecdata].iband; const size_t iquad = darray_specdata_data_get(&specdata)[ispecdata].iquad; const size_t id = iband - sky->sw_bands_range[0]; - size_t pcent; + int8_t pcent; size_t n; res_T res_local = RES_OK; @@ -1266,18 +1268,32 @@ setup_clouds if(!sky->htrdr->cache_grids) { /* Update the progress message */ n = (size_t)ATOMIC_INCR(&nbuilt_octrees); - pcent = n * 100 / darray_specdata_size_get(&specdata); + pcent = (int8_t)(n * 100 / darray_specdata_size_get(&specdata)); #pragma omp critical - if(pcent > progress) { - progress = pcent; - htrdr_fprintf(sky->htrdr, stderr, - "%c[2K\rBuilding octrees: %3u%%", 27, (unsigned)pcent); - htrdr_fflush(sky->htrdr, stderr); + if(pcent > sky->htrdr->mpi_progress_octree[0]) { + sky->htrdr->mpi_progress_octree[0] = pcent; + if(sky->htrdr->mpi_rank != 0) { + /* Send the progress percentage of the process to the master process */ + CHK(MPI_Send(&pcent, sizeof(pcent), MPI_CHAR, 0/*dst*/, + HTRDR_MPI_PROGRESS_BUILD_OCTREE, MPI_COMM_WORLD) == MPI_SUCCESS); + } else { + fetch_mpi_progress(sky->htrdr, HTRDR_MPI_PROGRESS_BUILD_OCTREE); + htrdr_fprintf(sky->htrdr, stderr, "\033[%dA", sky->htrdr->mpi_nprocs); + print_mpi_progress(sky->htrdr, HTRDR_MPI_PROGRESS_BUILD_OCTREE); + } } } } - if(!sky->htrdr->cache_grids) htrdr_fprintf(sky->htrdr, stderr, "\n"); + + if(!sky->htrdr->cache_grids && sky->htrdr->mpi_rank == 0) { + while(total_mpi_progress(sky->htrdr, HTRDR_MPI_PROGRESS_BUILD_OCTREE) != 100) { + fetch_mpi_progress(sky->htrdr, HTRDR_MPI_PROGRESS_BUILD_OCTREE); + htrdr_fprintf(sky->htrdr, stderr, "\033[%dA", sky->htrdr->mpi_nprocs); + print_mpi_progress(sky->htrdr, HTRDR_MPI_PROGRESS_BUILD_OCTREE); + sleep(1); + } + } exit: darray_specdata_release(&specdata);