Skip to content

Guard flow_path_mfd() against unbounded memory allocations (#1365)#1369

Merged
brendancol merged 1 commit intomainfrom
issue-1365
Apr 29, 2026
Merged

Guard flow_path_mfd() against unbounded memory allocations (#1365)#1369
brendancol merged 1 commit intomainfrom
issue-1365

Conversation

@brendancol
Copy link
Copy Markdown
Contributor

Summary

Closes #1365. The numpy and cupy flow_path_mfd paths allocate ~80 B/px of host working memory before any path tracing, driven by the (8, H, W) float64 cast of the input fractions plus the float64 start-points and output rasters. Without a pre-flight check, a large raster can drive the process into OOM.

This change adds the same memory guard pattern used in #1351 (flow_length_mfd) and #1337 (stream_link_mfd):

  • Per-module _BYTES_PER_PIXEL = 80 and _GPU_BYTES_PER_PIXEL = 88 constants with a comment breaking down the count.
  • _available_memory_bytes() reads /proc/meminfo, falls back to psutil, then a 2 GiB default.
  • _available_gpu_memory_bytes() queries cupy.cuda.runtime.memGetInfo, returns 0 when CUDA is unavailable.
  • _check_memory() and _check_gpu_memory() raise MemoryError when projected use exceeds 50% of available host / GPU RAM, with a message that points to the dask backend.
  • Both checks are wired into flow_path_mfd ahead of the eager allocations. The dask and dask+cupy paths skip the guard.

Tests

  • test_numpy_huge_raster_raises
  • test_numpy_normal_input_succeeds
  • test_dask_path_skips_guard
  • test_error_message_mentions_dimensions
  • test_cupy_huge_raster_raises (skipped without CUDA)

Test plan

  • pytest xrspatial/hydro/tests/test_flow_path_mfd.py (21 passed)
  • Full hydro suite minus the two known-flaky temp-cleanup tests (731 passed, 2 deselected)

The numpy and cupy backends eagerly allocate ~80 B/px of working
memory before tracing any paths, dominated by the (8, H, W) float64
copy of the input fractions. Large rasters can exhaust host or device
RAM with no error reaching the caller.

Add per-module memory guards mirroring #1351 / #1337: pre-flight
checks raise MemoryError when projected use exceeds 50% of available
host or GPU RAM, with a message pointing to the dask backends. Dask
and dask+cupy paths skip the guard.
@github-actions github-actions Bot added the performance PR touches performance-sensitive code label Apr 29, 2026
@brendancol brendancol merged commit 5d355fb into main Apr 29, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

performance PR touches performance-sensitive code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

flow_path_mfd: no memory guard on H*W working arrays

1 participant