Repository navigation
Faster later calls of the generic interpolation path: memoize refactor and numpy flattening - #9
Merged
Merged
Conversation
- memoize(maxsize, key=None): with a key function, the key is computed by the decorator only when caching is active; with maxsize <= 0 the function is returned undecorated. Without key, the hkey keyword argument works as before. - Least recently used eviction (OrderedDict) instead of the oldest entry, and a lock around the cache so that it is safe to use from threads. - The caches of grid_interp use key functions with exact array keys (shape, dtype, content). The reprojection keys now include the source CRS, and the regular grid nearest key no longer assumes a POI dimension named "poi". - Document the in-memory caches and how to set their sizes or deactivate them with GRID_PROCESS__cache_size__<name> (Usage page, docstrings, yaml). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- _flatten_concat (interp2poi) and _flatten_concat_grids (interp2grid) get the flat coordinates and values with numpy (_flat_coord, _flat_values) instead of xarray.stack, which built a pandas MultiIndex over all points. - The grid points NaN in all fields are found from the candidates NaN in their first field (_valid_points), and the data are copied only when some are excluded. Same results as isnull().all(), including NaT and no field. - Remove _flatten_coords_crs, replaced by dm.get_coords_name_crs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…red grid interp2poi raised an IndexError in _fullnan_ds when slicing an unstructured grid left no grid point (all POIs outside of the domain): the empty spatial dimension is now padded so that the all-NaN output can be built. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
data4web-pipelines uses it to slice the input data with the largest buffer of its configured interpolation methods. No alias is kept for the private name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
The generic (non-regular) path of
interp2poiandinterp2gridwas much slower on later calls than the regular path, even though the neighbor indices were cached. Profiling showed that the time went into flattening the grids, not into the lookup. For example, for GFS 0.25° → 33 POIs, about 0.13 s of the 0.16 s per call went toxarray.stack(pandas MultiIndex), against 0.012 s for the lookup.Changes
memoizerefactor (grid_process/optimization.py)key=function computes the cache key, only when caching is active. The grid-process call sites no longer build keys.hkey=keyword argument still works as before (it is used by seamlessweatherprovider).Cache key fixes
poi(GRID_PROCESS__data_model__poi__dim).Cache documentation: a new "In-memory caching" section on the Usage page lists the four caches, their sizes, and how to set or deactivate them with
GRID_PROCESS__cache_size__<name>(set before importing grid-process). Theinterp2poi/interp2gridnotes andgrid_process.yamlpoint to it.Numpy flattening (
grid_process/grid_interp.py)xarray.stack._flatten_coords_crsis removed.interp2poistill excludes grid points with NaN in all fields, as before. It now looks for them only among the points with NaN in the middle field. The first field is not used because accumulated variables are NaN everywhere at the first lead time.main). Gathering neighbors from a strided view was 2–4× slower.interp2gridis unchanged in this respect, after an evaluation:Fix:
interp2poiraised anIndexError(in_fullnan_ds, also onmain) when all POIs are outside an unstructured grid. They now get NaN, without numpy "Mean of empty slice" warnings. This fix is its own commit and can be moved to a separate PR if preferred.Tests: new tests cover:
memoize: LRU,key=, size 0,hkey, metadata, and a fork while another thread holds the lock;xarray.stack;Plus the ruff E731 fixes in the tests.
Results
The benchmark ran 124 cases (operational gridefix IFS/ICON-CH1/ICON-CH2 to production POIs and seamless2km, native ICON from OGD, notebooks, global, topo),
mainvs branch in fresh processes, 2 rounds.interp2poicases were rerun after the middle-field change.mainon theinterp2poicases. No case is consistently slower.mainnearest→ production POIsnearest_alt→ production POIstemp, large-kidw,snowlim, andinterp2gridfrom gridefix or native ICON. Their time goes into the interpolation itself.main.Checks
pytest: 252 passed.ruff format --checkandruff check: clean (0 errors, including the E731 fixes).mypy: clean.pylint: 9.55, up from 9.52.GRID_PROCESS__cache_size__<name>=0, all five cached functions are undecorated and the results are identical.The example notebooks were not re-executed (their timing tables would change).
🤖 Generated with Claude Code