Skip to content

Commit cf38077

Browse files
committed
data: Fix strided slice with start inside a subdomain
index_glb_to_loc mis-converted a strided global slice when its start (or, for a negative step, its high end) fell strictly inside the owning subdomain: the stride phase was computed from the subdomain boundary instead of the slice start, so the local block picked spurious leading or trailing elements (e.g. global 2:8:2 gave rank 0 local [0, 2] instead of [2]). This disagreed with the induced decomposition and made data_gather on such slices raise a shape mismatch. Begin the stride phase at the slice start when it lies within the subdomain, for both the positive (loc_min) and negative (loc_max) cases. Add a serial regression test for the conversion and exercise the failing gather slices (2:8:2, 7:0:-2) in the 2D/3D sliced-gather tests.
1 parent 9b29276 commit cf38077

2 files changed

Lines changed: 41 additions & 2 deletions

File tree

devito/data/decomposition.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,14 @@ def index_glb_to_loc(self, *args, rel=True):
296296
loc_min = loc_abs_min - base \
297297
+ np.mod(glb_idx.step - np.mod(base, glb_idx.step),
298298
glb_idx.step)
299-
else: # glb start is given explicitly
299+
elif glb_idx_min >= loc_abs_min:
300+
# The slice starts within this subdomain, so its first
301+
# selected index is the start itself (the stride phase
302+
# begins here, not at loc_abs_min).
303+
loc_min = glb_idx_min - base
304+
else: # the slice started in an earlier subdomain
305+
# Advance to the first in-stride index at or after this
306+
# subdomain's start.
300307
loc_min = loc_abs_min - base \
301308
+ np.mod(glb_idx.step - np.mod(base - glb_idx.start,
302309
glb_idx.step), glb_idx.step)
@@ -319,7 +326,14 @@ def index_glb_to_loc(self, *args, rel=True):
319326
loc_max = top - base \
320327
+ np.mod(glb_idx.step - np.mod(top - glb_max,
321328
glb_idx.step), glb_idx.step)
322-
else:
329+
elif glb_idx_max <= loc_abs_max:
330+
# The slice's high end (its start) is within this
331+
# subdomain, so the first selected index is the start
332+
# itself (the stride phase begins here, not at loc_abs_max).
333+
loc_max = glb_idx_max - base
334+
else: # the slice's high end is in a later subdomain
335+
# Step back to the first in-stride index at or below this
336+
# subdomain's end.
323337
loc_max = top - base \
324338
+ np.mod(glb_idx.step - np.mod(top - glb_idx.start,
325339
glb_idx.step), glb_idx.step)

tests/test_data.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,25 @@ def test_glb_to_loc_index_conversions(self):
451451
assert d.index_glb_to_loc((1, 6), rel=False) == (5, 6)
452452
assert d.index_glb_to_loc((None, None), rel=False) == (5, 7)
453453

454+
def test_glb_to_loc_strided_start_in_subdomain(self):
455+
"""
456+
Regression: a strided slice whose start (or, for a negative step, its
457+
high end) falls strictly inside the owning subdomain must begin the
458+
stride phase at the start, not at the subdomain boundary. Previously the
459+
local slice picked spurious leading/trailing elements (e.g. global
460+
``2:8:2`` gave rank 0 local ``[0, 2]`` instead of ``[2]``).
461+
"""
462+
d0 = Decomposition([[0, 1, 2], [3, 4], [5, 6, 7], [8, 9, 10, 11]], 0)
463+
d2 = Decomposition([[0, 1, 2], [3, 4], [5, 6, 7], [8, 9, 10, 11]], 2)
464+
465+
# Positive step, start strictly inside the owning subdomain
466+
assert d0.index_glb_to_loc(slice(2, 12, 2)) == slice(2, 3, 2) # -> [2]
467+
assert d2.index_glb_to_loc(slice(6, 12, 2)) == slice(1, 3, 2) # -> [6]
468+
469+
# Negative step, high end (the start) strictly inside the subdomain
470+
assert d2.index_glb_to_loc(slice(5, 0, -2)) == slice(0, None, -2) # -> [5]
471+
assert d0.index_glb_to_loc(slice(2, None, -2)) == slice(2, None, -2)
472+
454473
def test_glb_to_loc_w_side(self):
455474
d = Decomposition([[0, 1, 2], [3, 4], [5, 6, 7], [8, 9, 10, 11]], 2)
456475

@@ -1551,6 +1570,10 @@ def test_simple_gather(self, rank, mode):
15511570
(None, None, -1),
15521571
(None, None, -2),
15531572
(1, 8, 3),
1573+
# Strided slices whose start falls inside a subdomain (see
1574+
# TestDecomposition.test_glb_to_loc_strided_start_in_subdomain)
1575+
(2, 8, 2),
1576+
(7, 0, -2),
15541577
((0, 4), None, (2, 1))])
15551578
def test_sliced_gather_2D(self, start, stop, step, mode):
15561579
""" Test gather for various 2D slices."""
@@ -1585,6 +1608,8 @@ def test_sliced_gather_2D(self, start, stop, step, mode):
15851608
(None, None, -1),
15861609
(None, None, -2),
15871610
(1, 8, 3),
1611+
(2, 8, 2),
1612+
(7, 0, -2),
15881613
((0, 4, 4), None, (2, 1, 1))])
15891614
def test_sliced_gather_3D(self, start, stop, step, mode):
15901615
""" Test gather for various 3D slices."""

0 commit comments

Comments
 (0)