From 3cf05b08322dce38769736d8976075a468723dbe Mon Sep 17 00:00:00 2001 From: Vaclav Petras Date: Mon, 28 Sep 2026 10:44:21 -0400 Subject: [PATCH] r.sim: Simulate all walkers when running in parallel Each thread computed its own range of walkers from a chunk size rounded to the nearest integer, steps = (int)(nwalk / nthreads + 0.5). When the division rounded down, the walkers past the last range were never moved and never added their water, up to (nthreads - 1) / 2 walkers in every iteration: nwalk nthreads steps covered dropped 2205 4 551 2204 1 2206 4 552 2208 0 (last range cut at nwalk) 2211 8 276 2208 3 1000007 16 62500 1000000 7 Round the chunk size up instead, so that the ranges cover all walkers. The last range is then cut at nwalk as before, and with fewer walkers than threads, the last threads get empty ranges. Single-threaded results do not change: the depth, discharge, sediment flux and erosion/deposition maps computed from the nc_spm elevation are byte-identical to those before this change. Written with the help of Claude Code. --- raster/r.sim/simlib/hydro.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/raster/r.sim/simlib/hydro.c b/raster/r.sim/simlib/hydro.c index 215c22414ab..ccdf2735b3d 100644 --- a/raster/r.sim/simlib/hydro.c +++ b/raster/r.sim/simlib/hydro.c @@ -151,9 +151,8 @@ void main_loop(const Setup *setup, const Geometry *geometry, #pragma omp parallel firstprivate(l, lw, k) reduction(+ : nwalka) { #if defined(_OPENMP) - int steps = (int)((((double)sim->nwalk) / - ((double)omp_get_num_threads())) + - 0.5); + int steps = (sim->nwalk + omp_get_num_threads() - 1) / + omp_get_num_threads(); int tid = omp_get_thread_num(); int min_loop = tid * steps; int max_loop = ((tid + 1) * steps) > sim->nwalk