Skip to content

flow_length_mfd: no memory guard on H*W working arrays #1351

Description

@brendancol

flow_length_mfd in xrspatial/hydro/flow_length_mfd.py allocates several full-grid working arrays in its eager numpy and cupy backends with no upfront budget check. A 50000x50000 raster asks for about 73 GB of host RAM before anything errors out.

Same shape as #1332 for flow_length_d8, and the broader hydro audit started with #1318/#1319 for flow_accumulation_d8. See also #1341 (stream_link_mfd) for the MFD overhead pattern. Eager backends check, dask backends skip since per-tile allocations are bounded by chunk size.

Allocations

_flow_length_mfd_downstream_cpu and _flow_length_mfd_upstream_cpu (called by both numpy and cupy backends) allocate:

Array dtype bytes/px
in_degree int32 4
valid int8 1
flow_len float64 8
order_r int64 8
order_c int64 8
Total 29

The numpy public dispatch also performs frac = data.astype(np.float64), an explicit 64 B/px copy of the (8, H, W) MFD fractions input that lives on top of the working set. Total numpy peak: 29 + 64 = 93 B/px.

For the cupy backend, _flow_length_mfd_cupy calls .get().astype(np.float64) then runs the CPU kernel, so the host pays the full 93 B/px during the call. On the device side the input (8, H, W) float64 already exists (64 B/px) and the output float64 result lives at 8 B/px - call it 100 B/px GPU as a conservative budget covering both copies plus headroom.

Worked example

50000x50000 = 2.5e9 pixels. CPU peak working set:

2.5e9 * 29 = 73 GB (kernel locals only)
2.5e9 * 93 = 232 GB (with the up-front astype copy)

Allocated before any sanity check runs.

Fix

Mirror PR #1332: _check_memory and _check_gpu_memory helpers, wired into the numpy and cupy dispatch in flow_length_mfd(). Leave dask alone. Add tests for oversize rejection, valid pass-through, dask bypass, and error message content.

One fix per PR per the security-sweep policy.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinghigh-priorityoomOut-of-memory risk with large datasets

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions