Preserve input dtype on perlin() dask backends#3471
Open
brendancol wants to merge 4 commits into
Open
Conversation
The dask+numpy and dask+cupy paths hardcoded float32 in their map_blocks calls, so a float64 input was silently downcast to float32 while the numpy and cupy backends kept float64. Derive the output dtype from data.dtype in both dask functions and add cross-backend dtype regression tests covering all four backends.
brendancol
commented
Jun 23, 2026
brendancol
left a comment
Contributor
Author
There was a problem hiding this comment.
PR Review: Preserve input dtype on perlin() dask backends
Blockers
None.
Suggestions
None.
Nits
- test_perlin.py:127
test_perlin_dask_cpu_preserves_dtypechecks only the output dtype. Since this bug was specifically about float64, you could also assert the float64 result is finite and in [0, 1], the waytest_perlin_float64_inputdoes for numpy. Optional; the existing parity tests already check the values.
What looks good
- Both dask paths derive
out_dtypefromdata.dtypenow, so they line up with numpy and cupy, which already preserved it. - The
partialimport was unused once the inline closure replaced it, and it got removed. - New tests hit all four backends across float32 and float64.
perlin()rejects non-floating dtypes upfront, soout_dtypeis always float32 or float64 and the cast is safe.
Note on precision
For float64 input the noise is still computed in float32 inside _perlin and the GPU kernel, then stored as float64. That is storage precision, not compute precision. It matches what numpy and cupy already do (float32 math written into a float64 buffer), so parity holds and nothing regresses here.
Checklist
- Algorithm unchanged; only the output dtype derivation moved
- All four backends agree (parity tests pass)
- NaN handling untouched (perlin overwrites the input buffer)
- dtype covered for both float32 and float64
- Dask chunk boundaries unaffected (no shape change)
- No premature materialization
- No benchmark needed
- README unchanged
- Docstrings unchanged
brendancol
commented
Jun 23, 2026
brendancol
left a comment
Contributor
Author
There was a problem hiding this comment.
PR Review (follow-up)
The one nit from the previous pass is fixed: test_perlin_dask_cpu_preserves_dtype now also asserts the result is finite and normalized to [0, 1] for both dtypes, matching test_perlin_float64_input.
No remaining findings. Blockers: none. Suggestions: none.
…erlin-2026-06-23-01
…erlin-2026-06-23-01 # Conflicts: # xrspatial/tests/test_perlin.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
perlin()returned a different output dtype depending on the backend. A float64 input kept float64 on numpy and cupy but came back as float32 on both dask backends, because_perlin_dask_numpyand_perlin_dask_cupypassed a hardcoded float32 toda.map_blocks.(GitHub issues are disabled on this repo, so there is no linked issue.)
What changed
map_blocksoutput dtype fromdata.dtypeinstead of pinning float32.Backend coverage
numpy / cupy already preserved the input dtype; this fixes dask+numpy and dask+cupy to match. Verified all four return float32 for float32 input and float64 for float64 input.
Test plan
pytest xrspatial/tests/test_perlin.py(18 passed, GPU paths included)