Skip to content

Commit 56cf14c

Browse files
Merge pull request #2719 from devitocodes/pytest-mark-name
compiler: improve rcompile
2 parents 4ee88fb + 26b17d0 commit 56cf14c

File tree

14 files changed

+105
-38
lines changed

14 files changed

+105
-38
lines changed

conftest.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import pytest
66
from sympy import Add
7+
from sympy.printing import sstr
78

89
from devito import Eq, configuration, Revolver # noqa
910
from devito.checkpointing import NoopRevolver
@@ -287,6 +288,20 @@ def pytest_runtest_makereport(item, call):
287288
result.outcome = 'passed'
288289

289290

291+
def pytest_make_parametrize_id(config, val, argname):
292+
"""
293+
Prevents pytest from making obscure parameter names (param0, param1, ...)
294+
and default to sympy.sstr(val) instead for better log readability.
295+
"""
296+
# First see if it has a name
297+
if hasattr(val, '__name__'):
298+
return val.__name__
299+
try:
300+
return sstr(val)
301+
except Exception:
302+
return None # Fall back to default behavior
303+
304+
290305
# A list of optimization options/pipelines to be used in testing
291306
# regarding spatial and/or temporal blocking.
292307
opts_tiling = ['advanced',

devito/arch/compiler.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ def __init__(self):
180180
"""
181181

182182
fields = {'cc', 'ld'}
183+
linker_opt = '-Wl,'
183184
_default_cpp = False
184185
_cxxstd = 'c++14'
185186
_cstd = 'c99'
@@ -425,7 +426,7 @@ def add_library_dirs(self, dirs, rpath=False):
425426
if rpath:
426427
# Add rpath flag to embed library dir
427428
for d in as_list(dirs):
428-
self.ldflags.append(f'-Wl,-rpath,{d}')
429+
self.ldflags.append(f'{self.linker_opt}-rpath,{d}')
429430

430431
def add_libraries(self, libs):
431432
self.libraries = filter_ordered(self.libraries + as_list(libs))
@@ -662,6 +663,7 @@ def __lookup_cmds__(self):
662663
class CudaCompiler(Compiler):
663664

664665
_default_cpp = True
666+
linker_opt = "--linker-options="
665667

666668
def __init_finalize__(self, **kwargs):
667669

devito/core/__init__.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
Cpu64CustomOperator, Cpu64CustomCXXOperator,
77
Cpu64CXXNoopCOperator, Cpu64CXXNoopOmpOperator,
88
Cpu64AdvCXXOperator, Cpu64AdvCXXOmpOperator,
9-
Cpu64FsgCXXOperator, Cpu64FsgCXXOmpOperator
9+
Cpu64FsgCXXOperator, Cpu64FsgCXXOmpOperator,
10+
Cpu64CustomCXXOmpOperator, Cpu64CustomCOperator
1011
)
1112
from devito.core.intel import (
1213
Intel64AdvCOperator, Intel64AdvOmpOperator,
@@ -33,11 +34,11 @@
3334
from devito.operator.registry import operator_registry
3435

3536
# Register CPU Operators
36-
operator_registry.add(Cpu64CustomOperator, Cpu64, 'custom', 'C')
37+
operator_registry.add(Cpu64CustomCOperator, Cpu64, 'custom', 'C')
3738
operator_registry.add(Cpu64CustomOperator, Cpu64, 'custom', 'openmp')
3839
operator_registry.add(Cpu64CustomOperator, Cpu64, 'custom', 'Copenmp')
3940
operator_registry.add(Cpu64CustomCXXOperator, Cpu64, 'custom', 'CXX')
40-
operator_registry.add(Cpu64CustomCXXOperator, Cpu64, 'custom', 'CXXopenmp')
41+
operator_registry.add(Cpu64CustomCXXOmpOperator, Cpu64, 'custom', 'CXXopenmp')
4142

4243
operator_registry.add(Cpu64NoopCOperator, Cpu64, 'noop', 'C')
4344
operator_registry.add(Cpu64NoopOmpOperator, Cpu64, 'noop', 'openmp')

devito/core/cpu.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,11 +321,24 @@ def _make_iet_passes_mapper(cls, **kwargs):
321321
assert not (set(_known_passes) & set(_known_passes_disabled))
322322

323323

324-
class Cpu64CustomCXXOperator(Cpu64CustomOperator):
324+
class Cpu64CustomCXXOmpOperator(Cpu64CustomOperator):
325325

326326
_Target = CXXOmpTarget
327327
LINEARIZE = True
328328

329+
330+
class Cpu64CustomCOperator(Cpu64CustomOperator):
331+
332+
_Target = CTarget
333+
LINEARIZE = False
334+
335+
336+
class Cpu64CustomCXXOperator(Cpu64CustomOperator):
337+
338+
_Target = CXXTarget
339+
LINEARIZE = True
340+
341+
329342
# Language level
330343

331344

devito/operator/operator.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
switch_log_level)
1919
from devito.ir.equations import LoweredEq, lower_exprs, concretize_subdims
2020
from devito.ir.clusters import ClusterGroup, clusterize
21-
from devito.ir.iet import (Callable, CInterface, EntryFunction, FindSymbols,
22-
MetaCall, derive_parameters, iet_build)
21+
from devito.ir.iet import (Callable, CInterface, EntryFunction, DeviceFunction,
22+
FindSymbols, MetaCall, derive_parameters, iet_build)
2323
from devito.ir.support import AccessMode, SymbolRegistry
2424
from devito.ir.stree import stree_build
2525
from devito.operator.profiling import create_profile
@@ -1270,9 +1270,12 @@ def rcompile(expressions, kwargs, options, target=None):
12701270

12711271
# Recursive compilation is expensive, so we cache the result because sometimes
12721272
# it is called multiple times for the same input
1273-
compiled = RCompiles(expressions, cls).compile(**kwargs)
1273+
irs, byproduct0 = RCompiles(expressions, cls).compile(**kwargs)
12741274

1275-
return compiled
1275+
key = lambda i: isinstance(i, (EntryFunction, DeviceFunction))
1276+
byproduct = byproduct0.filter(key)
1277+
1278+
return irs, byproduct
12761279

12771280

12781281
# *** Misc helpers
@@ -1518,7 +1521,7 @@ def nbytes_snapshots(self):
15181521
# Layers are sometimes aliases, so include aliases here
15191522
for i in self._op_symbols:
15201523
try:
1521-
if i._child is None:
1524+
if i._child is None and i.alias is not True:
15221525
# Use only the "innermost" layer to avoid counting snapshots
15231526
# twice. This layer will have no child.
15241527
v = self._apply_override(i)
@@ -1574,6 +1577,11 @@ def parse_kwargs(**kwargs):
15741577
else:
15751578
raise InvalidOperator(f"Illegal `opt={str(opt)}`")
15761579

1580+
# `openmp` in mode e.g `opt=('openmp', 'simd', {})`
1581+
if mode and 'openmp' in mode:
1582+
options['openmp'] = True
1583+
mode = tuple(i for i in as_tuple(mode) if i != 'openmp')
1584+
15771585
# `opt`, deprecated kwargs
15781586
kwopenmp = kwargs.get('openmp', options.get('openmp'))
15791587
if kwopenmp is None:

devito/passes/iet/definitions.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ class DataManager:
8686
The language used to express data allocations, deletions, and host-device transfers.
8787
"""
8888

89-
def __init__(self, rcompile=None, sregistry=None, platform=None, **kwargs):
89+
def __init__(self, rcompile=None, sregistry=None, platform=None,
90+
options=None, **kwargs):
9091
self.rcompile = rcompile
9192
self.sregistry = sregistry
9293
self.platform = platform

devito/passes/iet/engine.py

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
from collections import OrderedDict, defaultdict
1+
from collections import defaultdict
22
from functools import partial, singledispatch, wraps
33

44
import numpy as np
55
from sympy import Mul
66

77
from devito.ir.iet import (
88
Call, ExprStmt, Expression, Iteration, SyncSpot, AsyncCallable, FindNodes,
9-
FindSymbols, MapNodes, MetaCall, Transformer, EntryFunction,
10-
ThreadCallable, Uxreplace, derive_parameters
9+
FindSymbols, MapNodes, MetaCall, Transformer, EntryFunction, ThreadCallable,
10+
Uxreplace, derive_parameters
1111
)
1212
from devito.ir.support import SymbolRegistry
1313
from devito.mpi.distributed import MPINeighborhood
@@ -28,7 +28,31 @@
2828
__all__ = ['Graph', 'iet_pass', 'iet_visit']
2929

3030

31-
class Graph:
31+
class Byproduct:
32+
33+
"""
34+
A Byproduct is a mutable collection of metadata produced by one or more
35+
compiler passes.
36+
37+
This metadata may be used internally or by the caller itself, typically
38+
for code generation purposes.
39+
"""
40+
41+
def __init__(self, efuncs=None, includes=None, headers=None, namespaces=None,
42+
globs=None):
43+
self.efuncs = efuncs or {}
44+
self.includes = includes or []
45+
self.headers = headers or []
46+
self.namespaces = namespaces or []
47+
self.globals = globs or []
48+
49+
@property
50+
def funcs(self):
51+
return tuple(MetaCall(v, True) for v in self.efuncs.values()
52+
if not isinstance(v, EntryFunction))
53+
54+
55+
class Graph(Byproduct):
3256

3357
"""
3458
DAG representation of a call graph.
@@ -49,16 +73,9 @@ class Graph:
4973
"""
5074

5175
def __init__(self, iet, options=None, sregistry=None, **kwargs):
52-
self.efuncs = OrderedDict([(iet.name, iet)])
53-
5476
self.sregistry = sregistry
5577

56-
self.includes = []
57-
self.headers = []
58-
self.namespaces = []
59-
self.globals = []
60-
61-
# Stash immutable information useful for one or more compiler passes
78+
super().__init__({iet.name: iet})
6279

6380
# All written user-level objects
6481
writes = FindSymbols('writes').visit(iet)
@@ -79,10 +96,6 @@ def __init__(self, iet, options=None, sregistry=None, **kwargs):
7996
def root(self):
8097
return self.efuncs[list(self.efuncs).pop(0)]
8198

82-
@property
83-
def funcs(self):
84-
return tuple(MetaCall(v, True) for v in self.efuncs.values())[1:]
85-
8699
@property
87100
def sync_mapper(self):
88101
"""
@@ -146,7 +159,7 @@ def apply(self, func, **kwargs):
146159
new_efuncs = metadata.get('efuncs', [])
147160

148161
efuncs[i] = efunc
149-
efuncs.update(OrderedDict([(i.name, i) for i in new_efuncs]))
162+
efuncs.update(dict([(i.name, i) for i in new_efuncs]))
150163

151164
# Update the parameters / arguments lists since `func` may have
152165
# introduced or removed objects
@@ -176,10 +189,24 @@ def visit(self, func, **kwargs):
176189
dag = create_call_graph(self.root.name, self.efuncs)
177190
toposort = dag.topological_sort()
178191

179-
mapper = OrderedDict([(i, func(self.efuncs[i], **kwargs)) for i in toposort])
192+
mapper = dict([(i, func(self.efuncs[i], **kwargs)) for i in toposort])
180193

181194
return mapper
182195

196+
def filter(self, key):
197+
"""
198+
Return a Byproduct containing only the Callables in the Graph
199+
for which `key` evaluates to True. The resulting object cannot be
200+
further modified by an IET pass.
201+
"""
202+
return Byproduct(
203+
efuncs={i: v for i, v in self.efuncs.items() if key(v)},
204+
includes=as_tuple(self.includes),
205+
headers=as_tuple(self.headers),
206+
namespaces=as_tuple(self.namespaces),
207+
globs=as_tuple(self.globals)
208+
)
209+
183210

184211
def iet_pass(func):
185212
if isinstance(func, tuple):
@@ -732,7 +759,7 @@ def _filter(v, efunc=None):
732759

733760
return processed
734761

735-
efuncs = OrderedDict(efuncs)
762+
efuncs = dict(efuncs)
736763
efuncs[root.name] = root._rebuild(parameters=_filter(root.parameters, root))
737764

738765
# Update all call sites to use the new signature

examples/cfd/01_convection.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@
382382
"# Now combine the BC expressions with the stencil to form operator\n",
383383
"expressions = [Eq(u.forward, stencil)]\n",
384384
"expressions += [bc_left, bc_right, bc_top, bc_bottom]\n",
385-
"op = Operator(expressions=expressions, opt=None, openmp=False) # <-- Turn off performance optimisations\n",
385+
"op = Operator(expressions=expressions, opt=None, language='C') # <-- Turn off performance optimisations\n",
386386
"op(time=nt, dt=dt)\n",
387387
"\n",
388388
"plot_field(u.data[0])\n",

examples/cfd/01_convection_revisited.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@
359359
"# Now combine the BC expressions with the stencil to form operator.\n",
360360
"expressions = [Eq(u.forward, stencil, subdomain=grid.interior)]\n",
361361
"expressions += [bc_left, bc_right, bc_top, bc_bottom]\n",
362-
"op = Operator(expressions=expressions, opt=None, openmp=False) # <-- Turn off performance optimisations\n",
362+
"op = Operator(expressions=expressions, opt=None, language='C') # <-- Turn off performance optimisations\n",
363363
"op(time=nt, dt=dt)\n",
364364
"\n",
365365
"plot_field(u.data[0])\n",

examples/userapi/05_conditional_dimension.ipynb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -792,8 +792,8 @@
792792
"for n, i in enumerate(f.dimensions):\n",
793793
" eqs.append(Eq(g[k, n], f.dimensions[n], implicit_dims=(f.dimensions + (ci,))))\n",
794794
"\n",
795-
"# TODO: Must be openmp=False for now due to issue #2061\n",
796-
"op0 = Operator(eqs, openmp=False)\n",
795+
"# TODO: Must be language='C' for now due to issue #2061\n",
796+
"op0 = Operator(eqs, language='C')\n",
797797
"op0.apply()\n",
798798
"print(op0.body.body[-1])\n",
799799
"\n",

0 commit comments

Comments
 (0)