You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
orthophoto merge: parallelize block processing with parallel_map
The split-merge orthophoto merge runs all ~61k blocks in a single
thread, pegging one CPU for 10h+ on large surveys (issue #2034).
Each block is an independent pure function of its source windows and
source ordering, so all blocks can be processed in parallel.
Changes:
- Add `max_workers=1` parameter to `merge()` (default 1 = serial,
unchanged behavior).
- Hoist `dst_count = first.count` before the block loop so worker
closures see it without holding the outer file handle.
- Replace the `for idx, dst_window in dstrast.block_windows()` loop
with `parallel_map(process_block, block_windows, max_workers)`.
- Use thread-local rasterio source handles (`get_sources()` via
`threading.local`) since GDAL/rasterio file handles are not
thread-safe.
- Serialize writes to the shared output dataset under `write_lock`.
- Keep `merge_skip_blending` behavior: after pass 1, if the flag is
set, write under the lock and return early (skipping passes 2 & 3).
- Keep progress logging every 5% of blocks via `progress_lock`.
- Wire `max_workers=args.max_concurrency` in `stages/splitmerge.py`.
With `max_workers <= 1` (the default) `parallel_map` runs serially,
so existing deployments are unaffected. Set `--max-concurrency N` to
use N threads during the merge stage.
Validated on opendronemap/odm:3.5.6 (identical algorithm): serial
~26.7s vs 8-worker ~7.9s on a 3-submodel Griend split (~440 blocks).
The win grows with block count; a 15.9 Gpx prod orthophoto (~61k
blocks) was observed at ~1.6/16 vCPU utilization before this fix.
Pixel-identical correctness verified band-by-band vs serial output.
Closes#2034
0 commit comments