Skip to content

Commit 3943951

Browse files
authored
Merge pull request #5799 from trexfeathers/v3.8.x.updates
v3.8.1 updates
2 parents b5a754e + a0adb70 commit 3943951

File tree

5 files changed

+62
-29
lines changed

5 files changed

+62
-29
lines changed

docs/src/whatsnew/3.8.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,22 @@ This document explains the changes made to Iris for this release
4242
any issues or feature requests for improving Iris. Enjoy!
4343

4444

45+
v3.8.1 (04 Mar 2024)
46+
====================
47+
48+
.. dropdown:: v3.8.1 Patches
49+
:color: primary
50+
:icon: alert
51+
:animate: fade-in
52+
:open:
53+
54+
The patches in this release of Iris include:
55+
56+
#. `@stephenworsley`_ fixed a potential memory leak for Iris uses of
57+
:func:`dask.array.map_blocks`; known specifically to be a problem in the
58+
:class:`iris.analysis.AreaWeighted` regridder. (:pull:`5767`)
59+
60+
4561
📢 Announcements
4662
================
4763

lib/iris/_lazy_data.py

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -450,10 +450,11 @@ def lazy_elementwise(lazy_array, elementwise_op):
450450
return da.map_blocks(elementwise_op, lazy_array, dtype=dtype)
451451

452452

453-
def map_complete_blocks(src, func, dims, out_sizes):
453+
def map_complete_blocks(src, func, dims, out_sizes, *args, **kwargs):
454454
"""Apply a function to complete blocks.
455455
456456
Complete means that the data is not chunked along the chosen dimensions.
457+
Uses :func:`dask.array.map_blocks` to implement the mapping.
457458
458459
Parameters
459460
----------
@@ -465,27 +466,47 @@ def map_complete_blocks(src, func, dims, out_sizes):
465466
Dimensions that cannot be chunked.
466467
out_sizes : tuple of int
467468
Output size of dimensions that cannot be chunked.
469+
*args : tuple
470+
Additional arguments to pass to `func`.
471+
**kwargs : dict
472+
Additional keyword arguments to pass to `func`.
473+
474+
Returns
475+
-------
476+
Array-like
477+
478+
See Also
479+
--------
480+
:func:`dask.array.map_blocks` : The function used for the mapping.
468481
469482
"""
483+
data = None
484+
result = None
485+
470486
if is_lazy_data(src):
471487
data = src
472488
elif not hasattr(src, "has_lazy_data"):
473489
# Not a lazy array and not a cube. So treat as ordinary numpy array.
474-
return func(src)
490+
result = func(src, *args, **kwargs)
475491
elif not src.has_lazy_data():
476-
return func(src.data)
492+
result = func(src.data, *args, **kwargs)
477493
else:
478494
data = src.lazy_data()
479495

480-
# Ensure dims are not chunked
481-
in_chunks = list(data.chunks)
482-
for dim in dims:
483-
in_chunks[dim] = src.shape[dim]
484-
data = data.rechunk(in_chunks)
496+
if result is None and data is not None:
497+
# Ensure dims are not chunked
498+
in_chunks = list(data.chunks)
499+
for dim in dims:
500+
in_chunks[dim] = src.shape[dim]
501+
data = data.rechunk(in_chunks)
485502

486-
# Determine output chunks
487-
out_chunks = list(data.chunks)
488-
for dim, size in zip(dims, out_sizes):
489-
out_chunks[dim] = size
503+
# Determine output chunks
504+
out_chunks = list(data.chunks)
505+
for dim, size in zip(dims, out_sizes):
506+
out_chunks[dim] = size
490507

491-
return data.map_blocks(func, chunks=out_chunks, dtype=src.dtype)
508+
result = data.map_blocks(
509+
func, *args, chunks=out_chunks, dtype=src.dtype, **kwargs
510+
)
511+
512+
return result

lib/iris/analysis/__init__.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,18 +1378,16 @@ def _percentile(data, percent, fast_percentile_method=False, **kwargs):
13781378
percent = [percent]
13791379
percent = np.array(percent)
13801380

1381-
# Perform the percentile calculation.
1382-
_partial_percentile = functools.partial(
1381+
result = iris._lazy_data.map_complete_blocks(
1382+
data,
13831383
_calc_percentile,
1384+
(-1,),
1385+
percent.shape,
13841386
percent=percent,
13851387
fast_percentile_method=fast_percentile_method,
13861388
**kwargs,
13871389
)
13881390

1389-
result = iris._lazy_data.map_complete_blocks(
1390-
data, _partial_percentile, (-1,), percent.shape
1391-
)
1392-
13931391
# Check whether to reduce to a scalar result, as per the behaviour
13941392
# of other aggregators.
13951393
if result.shape == (1,):

lib/iris/analysis/_area_weighted.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -392,20 +392,18 @@ def _regrid_area_weighted_rectilinear_src_and_grid__perform(
392392

393393
tgt_shape = (len(grid_y.points), len(grid_x.points))
394394

395-
# Calculate new data array for regridded cube.
396-
regrid = functools.partial(
395+
new_data = map_complete_blocks(
396+
src_cube,
397397
_regrid_along_dims,
398+
(src_y_dim, src_x_dim),
399+
meshgrid_x.shape,
398400
x_dim=src_x_dim,
399401
y_dim=src_y_dim,
400402
weights=weights,
401403
tgt_shape=tgt_shape,
402404
mdtol=mdtol,
403405
)
404406

405-
new_data = map_complete_blocks(
406-
src_cube, regrid, (src_y_dim, src_x_dim), meshgrid_x.shape
407-
)
408-
409407
# Wrap up the data as a Cube.
410408

411409
_regrid_callback = functools.partial(

lib/iris/analysis/_regrid.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -932,9 +932,11 @@ def __call__(self, src):
932932
x_dim = src.coord_dims(src_x_coord)[0]
933933
y_dim = src.coord_dims(src_y_coord)[0]
934934

935-
# Define regrid function
936-
regrid = functools.partial(
935+
data = map_complete_blocks(
936+
src,
937937
self._regrid,
938+
(y_dim, x_dim),
939+
sample_grid_x.shape,
938940
x_dim=x_dim,
939941
y_dim=y_dim,
940942
src_x_coord=src_x_coord,
@@ -945,8 +947,6 @@ def __call__(self, src):
945947
extrapolation_mode=self._extrapolation_mode,
946948
)
947949

948-
data = map_complete_blocks(src, regrid, (y_dim, x_dim), sample_grid_x.shape)
949-
950950
# Wrap up the data as a Cube.
951951
_regrid_callback = functools.partial(
952952
self._regrid,

0 commit comments

Comments
 (0)