-
Notifications
You must be signed in to change notification settings - Fork 228
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
dsl: Introduce ability to define Functions on Subdomains #2245
base: master
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #2245 +/- ##
==========================================
+ Coverage 86.80% 86.98% +0.17%
==========================================
Files 233 233
Lines 43755 44534 +779
Branches 8078 8237 +159
==========================================
+ Hits 37983 38739 +756
- Misses 5063 5082 +19
- Partials 709 713 +4 ☔ View full report in Codecov by Sentry. |
devito/types/grid.py
Outdated
return None | ||
|
||
@property | ||
def has_grid(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
overkill
devito/types/grid.py
Outdated
|
||
@property | ||
def distributor(self): | ||
if self.has_grid: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The pythonic way of doing this is:
try:
return self.grid._distributor
except AttributeError:
return None
devito/types/grid.py
Outdated
for k, v, s in zip(self.define(grid.dimensions).keys(), | ||
self.define(grid.dimensions).values(), grid.shape): | ||
|
||
for k, v, s in zip(self.define(self.grid.dimensions).keys(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need for .keys()
devito/types/grid.py
Outdated
@@ -483,12 +500,17 @@ class SubDomain(AbstractSubDomain): | |||
""" | |||
|
|||
def __subdomain_finalize__(self, grid, **kwargs): | |||
if self.has_grid: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if self.grid:
5fc54ee
to
a0742f0
Compare
Check out this pull request on See visual diffs & provide feedback on Jupyter Notebooks. Powered by ReviewNB |
9fe8916
to
1092e78
Compare
1d37846
to
d462af1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the amount of changes introduced, I'd prefer to see a lot more new tests.
Shouldn't all (most) of the old tests that @rhodrin wrote be here as well?
devito/mpi/distributed.py
Outdated
class SubDomainDistributor(DenseDistributor): | ||
|
||
""" | ||
Decompose a subdomain over a set of MPI processes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpicking: SubDomain
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this class should be (or really is aside from needing a couple of tweaks) tied specifically to SubDomain
's - why not make the slightly more more general SubDistributor
class?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think just SubDistributor
would be good
devito/mpi/distributed.py
Outdated
Parameters | ||
---------- | ||
subdomain : SubDomain | ||
The subdomain to be decomposed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpicking: full stop
devito/mpi/distributed.py
Outdated
decomposition of the grid. | ||
""" | ||
dist_interval = {dim: Interval(s.start, s.stop-1) | ||
for dim, s in self.parent.glb_slices.items()} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for comprehensions, use d
instead of dim
. Not just for homogeneity, but also to minimize verbosity
devito/mpi/distributed.py
Outdated
bounds_map = {**{dim.symbolic_min: 0 | ||
for dim in self.parent.dimensions}, | ||
**{dim.symbolic_max: sha-1 | ||
for dim, sha in zip(self.parent.dimensions, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps you could add properties
subdomain dimensions -> subdims
self.parent.dimensions -> dimensions
self.parent.glb_shape -> glb_shape
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I seem to remember that making SubDistributor.dimensions
not match SubDomain.dimensions
requires a bunch of extra complexity anywhere it's accessed, so I want to leave these properties intact. Have introduced par_dimensions
and par_shape
for the latter two however, as I agree it would be tidier with the attributes.
devito/mpi/distributed.py
Outdated
# The domain decomposition | ||
decompositions = [] | ||
for dec, dim in zip(self.parent._decomposition, self.parent.dimensions): | ||
decompositions.append([d if sdim_interval[dim] is None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we need to find a way of decreasing verbosity because in its current form the deciphering overhead is too high
devito/types/dense.py
Outdated
@@ -333,8 +353,17 @@ def _size_outhalo(self): | |||
self._distributor.myrank, | |||
min(self.grid.shape_local)) | |||
if not self._distributor.is_boundary_rank: | |||
# FIXME: Will throw an error if a Function on a Subdomain doesn't | |||
# enter any boundary ranks -> Needs to not do this | |||
print("First warning") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
leftover
devito/types/dense.py
Outdated
@@ -552,13 +582,17 @@ def _data_in_region(self, region, dim, side): | |||
Typically, this accessor won't be used in user code to set or read | |||
data values. | |||
""" | |||
if self._distributor: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the changes in this method seem very odd to me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They were leftover from something previous I think? They weren't doing anything so have been reverted.
devito/types/equation.py
Outdated
@@ -169,6 +188,9 @@ def __str__(self): | |||
__repr__ = __str__ | |||
|
|||
|
|||
_uxreplace_registry.register(Eq) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah it's here now 😂 why?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To prevent a circular import. However, given what Rhodri said about explicitly specifying the subdomain, this could probably be put back
devito/types/grid.py
Outdated
"""The counter for a SubDomain""" | ||
if self.grid: | ||
try: | ||
_subdomain_count[self.grid].add(id(self)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to rework all this because:
- it's too ugly, being based on a global variable
- it can leak memory
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@georgebisbas indeed..
devito/types/grid.py
Outdated
if isinstance(v, Dimension): | ||
sub_dimensions.append(v) | ||
sdshape.append(s) | ||
else: | ||
name = 'i%d%s' % (self._counter, k.name) | ||
try: | ||
# Case ('middle', int, int) | ||
side, thickness_left, thickness_right = v |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you change it into side, ltkn, rtkn = v
588c25e
to
2cd952e
Compare
2cd952e
to
341ee08
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
quick pass
devito/mpi/distributed.py
Outdated
@@ -12,7 +12,8 @@ | |||
|
|||
from devito.data import LEFT, CENTER, RIGHT, Decomposition | |||
from devito.parameters import configuration | |||
from devito.tools import EnrichedTuple, as_tuple, ctypes_to_cstr, filter_ordered | |||
from devito.tools import EnrichedTuple, as_tuple, ctypes_to_cstr, filter_ordered, \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
convention through devito is parenthesise not line break
devito/mpi/distributed.py
Outdated
return self._comm | ||
|
||
@property | ||
def myrank(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rank
devito/mpi/distributed.py
Outdated
return 0 | ||
|
||
@property | ||
def mycoords(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
coords
@@ -831,10 +831,13 @@ def test_solve(self, operate_on_empty_cache): | |||
# created by the finite difference (u.dt, u.dx2). We would have had | |||
# three extra references to u(t + dt), u(x - h_x) and u(x + h_x). | |||
# But this is not the case anymore! | |||
# TODO: This cache doesn't clear currently as retained legacy SubDomain API |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sounds quite dangerous as it might end up preventing Function and TimeFucntion to be reachable by the gc
4268c54
to
af06ba9
Compare
devito/data/decomposition.py
Outdated
@@ -204,9 +204,19 @@ def index_glb_to_loc(self, *args, rel=True): | |||
>>> d.index_glb_to_loc((1, 6), rel=False) | |||
(5, 6) | |||
""" | |||
# Need to offset the loc_abs_min, loc_abs_min, glb_min, and glb_max |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
loc_abs_max
devito/types/grid.py
Outdated
@@ -22,6 +24,8 @@ | |||
|
|||
GlobalLocal = namedtuple('GlobalLocal', 'glb loc') | |||
|
|||
_subdomain_count = {} # Track attachment of grids to SubDomains for dimension labelling |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if this is good to have! Need to check!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it isn't
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we have to fix it
devito/types/grid.py
Outdated
self._distributor = SubDistributor(self) | ||
|
||
# Intervals of form Interval(n, n) automatically become FiniteSet | ||
# +1 as intervals are in terms of indices (inclusive of endpoints) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what does this +1 mean here?
devito/types/grid.py
Outdated
raise ValueError("`SubDomain` %s has already been attached to a `Grid`" | ||
% self) | ||
else: | ||
self._grid = grid |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
newline
devito/types/grid.py
Outdated
if grid: | ||
if self.grid: | ||
raise ValueError("`SubDomain` %s has already been attached to a `Grid`" | ||
% self) | ||
else: | ||
self._grid = grid |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be done in less lines?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dropped a line. Could I do this with a decorator, since it's used at the start of SubDomain.__init_finalize__
?
if spec[0] == 'middle': | ||
start = spec[1] | ||
end = size - spec[2] - 1 | ||
elif spec[0] == 'left': | ||
start = 0 | ||
end = spec[1] - 1 | ||
else: | ||
start = size - spec[1] | ||
end = size - 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can also be parametrized, having an 'expected' argument with the expected to be asserted result
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that would probably make it messier and less extensible, given the combinatorial use of subdomain specifications and their orientation vs the domain decomposition
devito/operations/interpolators.py
Outdated
@@ -226,6 +237,24 @@ def _interp_idx(self, variables, implicit_dims=None, pos_only=()): | |||
""" | |||
Generate interpolation indices for the DiscreteFunctions in ``variables``. | |||
""" | |||
# Check if any Functions are defined on SubDomains |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this new chunk of code deserves an utility function
devito/operator/operator.py
Outdated
@@ -585,25 +585,34 @@ def _prepare_arguments(self, autotune=None, **kwargs): | |||
discretizations = {getattr(kwargs[p.name], 'grid', None) for p in overrides} | |||
discretizations.update({getattr(p, 'grid', None) for p in defaults}) | |||
discretizations.discard(None) | |||
# Remove subgrids if multiple grids | |||
|
|||
# Remove subgrids if multiple Grids |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this chunk of code that pulls the grids and sanitizes them to ensure there's just one Grid could/should be now moved to a separate utility function, as I feel it could be reused in some other places as well (surely I found myself in need to extract the unique grid from a list of something... I think IIRC cluster.grid
is one such case)
devito/mpi/distributed.py
Outdated
return self._dimension_map | ||
|
||
@cached_property | ||
def _d_interval(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
btw _domain_interval
would be clearer, I wouldn't have guessed it w/o a _sd_interval
cdmapper = {} | ||
# Need to adjust bounds if Function defined on a SubDomain | ||
if subdomain: | ||
adjust_interp_indices(subdomain, mapper, smapper, cdmapper) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems overlly intricated and overkill to build everything then redo a pass to replace everything with the input dimensions. What's the problem with doing self._rrdims(grid)
and self._gdims(grid)
and catching directly the right dimensions instead of rebuilding everything?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I was thinking something along those lines. I figured it would be best to get it working then refactor it
if d in a.free_symbols: | ||
# Shift by origin d -> d - o. | ||
indices.append(sympy.sympify(a.subs(d, d - o).xreplace(s))) | ||
# Shift by origin and offset d -> d - o - of. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to have origin just directly return the right one, or maybe local_origin
?
Add Functions on SubDomains functionality.
Remaining todo: