Skip to content

Guard sink_d8() against unbounded memory allocations (#1356)#1361

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

Guard sink_d8() against unbounded memory allocations (#1356)#1361
brendancol merged 1 commit intomainfrom
issue-1356

Conversation

@brendancol
Copy link
Copy Markdown
Contributor

Summary

Closes #1356.

sink_d8() ran the BFS connected-component kernel on the eager numpy and cupy backends with no check on the input size. Large in-memory rasters could exhaust host or device memory.

This PR mirrors the pattern from #1319 and the rest of the hydro guard series.

Bytes per pixel

  • numpy: 24 B/px (labels float64 + queue_r int64 + queue_c int64)
  • cupy: 8 B/px (labels float64)

The caller-provided flow_dir is not double-counted.

Changes

  • New _BYTES_PER_PIXEL, _GPU_BYTES_PER_PIXEL, _available_memory_bytes, _available_gpu_memory_bytes, _check_memory, _check_gpu_memory helpers in sink_d8.py.
  • sink_d8() calls the matching _check_* helper on the numpy and cupy branches before dispatching. Dask branches skip the guard.
  • 5 new tests in TestMemoryGuard: numpy raises, normal input passes, dask skips the guard, error message points at dask, byte-per-pixel constants are pinned.

Test plan

  • pytest xrspatial/hydro/tests/test_sink_d8.py -- 21 passed
  • pytest xrspatial/hydro/tests/ (excluding the two known dask cleanup flakes) -- 642 passed

The numpy and cupy paths allocate H*W working buffers (labels and BFS
queues on CPU, labels grid on GPU) before any sanity check on the input
size. Passing a sufficiently large in-memory raster can OOM the host
or device.

Add per-module _BYTES_PER_PIXEL (24) and _GPU_BYTES_PER_PIXEL (8)
constants and _check_memory / _check_gpu_memory helpers that raise
MemoryError when the projected working set exceeds 50% of available
RAM / free GPU memory. Wire the guards into the eager numpy and cupy
branches of sink_d8(); dask paths skip the guard since per-tile
allocations are bounded.

Mirrors the pattern from #1318/#1319 and the rest of the hydro guard
series.
@github-actions github-actions Bot added the performance PR touches performance-sensitive code label Apr 29, 2026
@brendancol brendancol merged commit 9fd8df8 into main Apr 29, 2026
10 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.

sink_d8: no memory guard on H*W working arrays

1 participant