Skip to content

Commit f483933

Browse files
authored
Merge pull request #2662 from devitocodes/red-space
mpi: fix allreduce iteration space
2 parents 99953d3 + ff1ff76 commit f483933

8 files changed

Lines changed: 77 additions & 39 deletions

File tree

.github/workflows/pytest-core-nompi.yml

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ jobs:
3838
pytest-ubuntu-py310-gcc9-omp,
3939
pytest-osx-py312-clang-omp,
4040
pytest-docker-py310-gcc-omp,
41-
pytest-docker-py310-icx-omp
41+
pytest-docker-py310-icx-omp,
42+
pytest-ubuntu-py313-gcc14-omp
4243
]
4344
set: [base, adjoint]
4445
include:
@@ -105,6 +106,13 @@ jobs:
105106
language: "openmp"
106107
sympy: "1.13"
107108

109+
- name: pytest-ubuntu-py313-gcc14-omp
110+
python-version: '3.13'
111+
os: ubuntu-24.04
112+
arch: "gcc-14"
113+
language: "openmp"
114+
sympy: "1.14"
115+
108116
- set: base
109117
test-set: 'not adjoint'
110118

@@ -155,8 +163,11 @@ jobs:
155163

156164
- name: Set pip flags for latest python (3.12)
157165
run: |
158-
if [ "${{ matrix.python-version }}" == '3.12' ]; then
159-
echo "PIPFLAGS='--break-system-packages'" >> $GITHUB_ENV
166+
ver="${{ matrix.python-version }}"
167+
major=${ver%%.*}
168+
minor=${ver#*.}; minor=${minor%%.*}
169+
if [ "$major" -eq 3 ] && [ "$minor" -ge 12 ]; then
170+
echo "PIPFLAGS='--break-system-packages'" >> $GITHUB_ENV
160171
fi
161172
162173
- name: Install dependencies

.github/workflows/pytest-gpu.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ jobs:
7474

7575
- name: Build docker image
7676
run: |
77-
docker build . --rm --pull --file docker/Dockerfile.devito --tag ${{ matrix.name }} --build-arg base=${{ matrix.base }}
77+
docker build . --rm --pull --file docker/Dockerfile.devito --tag ${{ matrix.name }}-${{ github.ref }} --build-arg base=${{ matrix.base }}
7878
7979
- name: Remove dangling layers
8080
run: |
@@ -87,13 +87,13 @@ jobs:
8787
docker ps -aq | xargs -r docker rm -f
8888
# Run tests
8989
ci_env=`bash <(curl -s https://codecov.io/env)`
90-
docker run ${{ matrix.flags }} ${{ matrix.name }} ${{ matrix.test_drive_cmd }}
91-
docker run ${{ matrix.flags }} $ci_env -e CI=true ${{ matrix.name }} pytest --cov --cov-config=.coveragerc --cov-report=xml ${{ matrix.test_files }}
90+
docker run ${{ matrix.flags }} ${{ matrix.name }}-${{ github.ref }} ${{ matrix.test_drive_cmd }}
91+
docker run ${{ matrix.flags }} $ci_env -e CI=true ${{ matrix.name }}-${{ github.ref }} pytest --cov --cov-config=.coveragerc --cov-report=xml ${{ matrix.test_files }}
9292
9393
- name: Test examples
9494
run: |
95-
docker run ${{ matrix.flags }} ${{ matrix.name }} pytest ${{ matrix.test_examples }}
95+
docker run ${{ matrix.flags }} ${{ matrix.name }}-${{ github.ref }} pytest ${{ matrix.test_examples }}
9696
9797
- name: Test examples with MPI
9898
run: |
99-
docker run ${{ matrix.flags }} --env DEVITO_MPI=1 ${{ matrix.name }} mpiexec -n 2 pytest ${{ matrix.test_examples }}
99+
docker run ${{ matrix.flags }} --env DEVITO_MPI=1 ${{ matrix.name }}-${{ github.ref }} mpiexec -n 2 pytest ${{ matrix.test_examples }}

devito/ir/clusters/algorithms.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from devito.exceptions import CompilationError
99
from devito.finite_differences.elementary import Max, Min
1010
from devito.ir.support import (Any, Backward, Forward, IterationSpace, erange,
11-
pull_dims, null_ispace)
11+
pull_dims)
1212
from devito.ir.equations import OpMin, OpMax, identity_mapper
1313
from devito.ir.clusters.analysis import analyze
1414
from devito.ir.clusters.cluster import Cluster, ClusterGroup
@@ -493,9 +493,9 @@ def reduction_comms(clusters):
493493
processed.append(c)
494494

495495
# Leftover reductions are placed at the very end
496-
if fifo:
497-
exprs = [Eq(dr.var, dr) for dr in fifo]
498-
processed.append(Cluster(exprs=exprs, ispace=null_ispace))
496+
for ispace, reds in groupby(fifo, key=lambda r: r.ispace):
497+
exprs = [Eq(dr.var, dr) for dr in reds]
498+
processed.append(Cluster(exprs=exprs, ispace=ispace))
499499

500500
return processed
501501

devito/ir/iet/nodes.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
'Increment', 'Return', 'While', 'ListMajor', 'ParallelIteration',
3131
'ParallelBlock', 'Dereference', 'Lambda', 'SyncSpot', 'Pragma',
3232
'DummyExpr', 'BlankLine', 'ParallelTree', 'BusyWait', 'UsingNamespace',
33-
'Using', 'CallableBody', 'Transfer']
33+
'Using', 'CallableBody', 'Transfer', 'EmptyList']
3434

3535
# First-class IET nodes
3636

@@ -218,6 +218,11 @@ def __repr__(self):
218218
len(self.body), len(self.footer))
219219

220220

221+
class EmptyList(List):
222+
"""A plain List node without a body, such as a header/footer only"""
223+
_traversable = []
224+
225+
221226
class Block(List):
222227

223228
"""A sequence of Nodes, wrapped in a block {...}."""

devito/ir/iet/visitors.py

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,6 +1295,28 @@ def __init__(self, mapper, nested=False):
12951295
self.mapper = mapper
12961296
self.nested = nested
12971297

1298+
def transform(self, o, handle, **kwargs):
1299+
if handle is None:
1300+
# None -> drop `o`
1301+
return None
1302+
elif isinstance(handle, Iterable):
1303+
# Iterable -> inject `handle` into `o`'s children
1304+
if not o.children:
1305+
raise CompilationError("Cannot inject nodes in a leaf node")
1306+
if self.nested:
1307+
children = [self._visit(i, **kwargs) for i in o.children]
1308+
else:
1309+
children = o.children
1310+
children = (tuple(handle) + children[0],) + tuple(children[1:])
1311+
return o._rebuild(*children, **o.args_frozen)
1312+
else:
1313+
# Replace `o` with `handle`
1314+
if self.nested:
1315+
children = [self._visit(i, **kwargs) for i in handle.children]
1316+
return handle._rebuild(*children, **handle.args_frozen)
1317+
else:
1318+
return handle
1319+
12981320
def visit_object(self, o, **kwargs):
12991321
return o
13001322

@@ -1307,29 +1329,11 @@ def visit_tuple(self, o, **kwargs):
13071329
def visit_Node(self, o, **kwargs):
13081330
if o in self.mapper:
13091331
handle = self.mapper[o]
1310-
if handle is None:
1311-
# None -> drop `o`
1312-
return None
1313-
elif isinstance(handle, Iterable):
1314-
# Iterable -> inject `handle` into `o`'s children
1315-
if not o.children:
1316-
raise CompilationError("Cannot inject nodes in a leaf node")
1317-
if self.nested:
1318-
children = [self._visit(i, **kwargs) for i in o.children]
1319-
else:
1320-
children = o.children
1321-
children = (tuple(handle) + children[0],) + tuple(children[1:])
1322-
return o._rebuild(*children, **o.args_frozen)
1323-
else:
1324-
# Replace `o` with `handle`
1325-
if self.nested:
1326-
children = [self._visit(i, **kwargs) for i in handle.children]
1327-
return handle._rebuild(*children, **handle.args_frozen)
1328-
else:
1329-
return handle
1330-
else:
1331-
children = [self._visit(i, **kwargs) for i in o.children]
1332-
return o._rebuild(*children, **o.args_frozen)
1332+
return self.transform(o, handle, **kwargs)
1333+
children = [self._visit(i, **kwargs) for i in o.children]
1334+
if o._traversable and not any(children) and any(o.children):
1335+
return None
1336+
return o._rebuild(*children, **o.args_frozen)
13331337

13341338
def visit_Operator(self, o, **kwargs):
13351339
raise ValueError("Cannot apply a Transformer visitor to an Operator directly")

devito/passes/iet/misc.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from devito.finite_differences import Max, Min
88
from devito.finite_differences.differentiable import SafeInv
99
from devito.logger import warning
10-
from devito.ir import (Any, Forward, DummyExpr, Iteration, List, Prodder,
10+
from devito.ir import (Any, Forward, DummyExpr, Iteration, EmptyList, Prodder,
1111
FindApplications, FindNodes, FindSymbols, Transformer,
1212
Uxreplace, filter_iterations, retrieve_iteration_tree,
1313
pull_dims)
@@ -47,7 +47,7 @@ def avoid_denormals(iet, platform=None, **kwargs):
4747
cgen.Statement('_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON)'),
4848
cgen.Line())
4949

50-
body = iet.body._rebuild(body=(List(header=header),) + iet.body.body)
50+
body = iet.body._rebuild(body=(EmptyList(header=header),) + iet.body.body)
5151
iet = iet._rebuild(body=body)
5252

5353
return iet, {'includes': ('xmmintrin.h', 'pmmintrin.h')}

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ description = "Finite Difference DSL for symbolic computation."
1212
license = { file = "LICENSE.md" }
1313
readme = "README.md"
1414
keywords = ["finite-difference", "DSL", "symbolic", "jit", "devito"]
15-
requires-python = ">=3.10,<3.13"
15+
requires-python = ">=3.10,<3.14"
1616
authors = [
1717
{ name = "Imperial College London", email = "g.gorman@imperial.ac.uk" },
1818
{ name = "Fabio Luporini", email = "fabio@devitocodes.com" },

tests/test_mpi.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2014,6 +2014,24 @@ def test_merge_smart_if_within_conditional(self, mode):
20142014
for n in FindNodes(Conditional).visit(op1):
20152015
assert len(FindNodes(HaloUpdateCall).visit(n)) == 0
20162016

2017+
@pytest.mark.parallel(mode=2)
2018+
def test_allreduce_time(self, mode):
2019+
space_order = 8
2020+
nx, ny = 11, 11
2021+
2022+
grid = Grid(shape=(nx, ny))
2023+
tt = grid.time_dim
2024+
nt = 10
2025+
2026+
ux = TimeFunction(name="ux", grid=grid, time_order=1, space_order=space_order)
2027+
g = TimeFunction(name="g", grid=grid, dimensions=(tt, ), shape=(nt,))
2028+
2029+
op = Operator([Eq(ux.forward, ux + tt), Inc(g, ux)], name="Op")
2030+
assert_structure(op, ['t,x,y', 't'], 'txy')
2031+
2032+
op.apply(time_m=0, time_M=nt-1)
2033+
assert np.isclose(np.max(g.data), 4356.0)
2034+
20172035

20182036
class TestOperatorAdvanced:
20192037

0 commit comments

Comments
 (0)