-
Notifications
You must be signed in to change notification settings - Fork 230
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
types: Remove increments from SubDimension names #2257
Conversation
…mes during compilation
…ionalDimension parents
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## master #2257 +/- ##
==========================================
+ Coverage 86.90% 86.96% +0.06%
==========================================
Files 229 229
Lines 41545 42262 +717
Branches 7660 7809 +149
==========================================
+ Hits 36105 36755 +650
- Misses 4818 4860 +42
- Partials 622 647 +25 ☔ View full report in Codecov by Sentry. |
devito/ir/equations/algorithms.py
Outdated
dims = set().union(*tuple(set(i.function.dimensions) | ||
for i in retrieve_indexed(e))) | ||
# Dimensions in conditions and ConditionalDimension parents | ||
dims = dims.union(*tuple(pull_dims(d.condition, flag=False) |
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.
you probably want to unclutter here and move most of this logic into pull_dims
ideally, all you need to do here would be:
dims = pull_dims(e, flag=...)
# Sort for groupby
dims = sorted(dims, key=lambda x: x.name)
because here you're performing a search
which, in theory, is just one, atomic step of separate_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.
IIrc, what's required here is more picky than pull_dims
(pull dims selects more dimensions than are needed). It just wants dimensions in the indices, conditional parent, and conditional condition
devito/symbolics/manipulation.py
Outdated
self.append(cls) | ||
_uxreplace_handle.register(cls, _uxreplace_handle_reconstructable) | ||
|
||
for kls, callback in (rkwargs_callback_mapper or {}).items(): | ||
_uxreplace_dispatch.register(kls, callback) | ||
|
||
def dispatchable(self, obj): | ||
return isinstance(obj, tuple(self)) | ||
def dispatchable(self, obj, deep=False): |
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.
So, I'm not sure I fully understand...
For ConditionalDimension
:
- sometimes you want it
deep
- but some other times, you don't ?
is this correct? in particular, you want it deep only when you calol it inside separate_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.
Inside separate_dimensions
, uxreplace
wants to recurse into ConditionalDimension
s and update all their args, kwargs, etc as necessary. However, elsewhere in the code, in particular here when called from here, this behaviour may not be desired. In the above case, the ConditionalDimension
may have already been indexified and shifted during the lowering of the expressions if it contains terms present in the Eq
(in the case that ConditionalDimension
is always affected by uxreplace
), causing shifting to get applied twice. Hence, the need to be able to have some kind of control over the classes touched by uxreplace
on a call-by-call basis
devito/types/dimension.py
Outdated
@@ -200,6 +200,10 @@ def is_const(self): | |||
def root(self): | |||
return self | |||
|
|||
@property | |||
def is_Root(self): | |||
return self == self.root |
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.
is self.root
devito/symbolics/manipulation.py
Outdated
# _uxreplace_registry.register(ConditionalDimension, deep=True) | ||
|
||
# Registry for dimension uxreplace | ||
_dxreplace_registry = UxreplaceRegistry() |
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.
rename as ReplaceRegistry
?
devito/ir/equations/algorithms.py
Outdated
for e in expressions: | ||
# Just want dimensions which appear in the expression | ||
# Dimensions in indices | ||
dims = set().union(*tuple(set(i.function.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.
Un-necessary extra "set" work, just set().union(*[i.function.dimensions ...])
devito/ir/equations/algorithms.py
Outdated
dims = set().union(*tuple(set(i.function.dimensions) | ||
for i in retrieve_indexed(e))) | ||
# Dimensions in conditions and ConditionalDimension parents | ||
dims = dims.union(*tuple(pull_dims(d.condition, flag=False) |
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.
same, no need for tuple
dims = dims.union(*tuple(pull_dims(d.condition, flag=False) | ||
for d in dims if d.is_Conditional | ||
and d.condition is not None), | ||
set(d.parent for d in dims if d.is_Conditional)) |
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 whole thing seems to be a bit intricated retrieve_dimensions(e, deep=True) + e.implicit_dims
should give you all dimensions.
Also why are we ignoring the conditionals with a factor?
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 issue is that retrieve_dimensions
collects too many things, not too few (even with flag=False). It wants to retrieve only indices in the equation, conditional dimension parent, and dimensions in the conditional dimension condition. Good point on the factor, that should probably be added in.
Fabio pointed out that separate_equations
probably wants to be after creation of LoweredEQ
, so may need to rethink this anyway.
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 wants to retrieve only indices in the equation
Why would a dimsion use as a free symbol rather than an index be ignored? It doesn't change the issue it's gonna be the wrong value if not changed. Any time both the conditional and the parent are used together irrespective of how is a clash.
|
||
# Group dimensions by matching names | ||
groups = tuple(tuple(g) for n, g in groupby(dims, key=lambda x: x.name)) | ||
clashes = tuple(g for g in groups if len(g) > 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.
you only need generator no need for tuple
devito/ir/equations/algorithms.py
Outdated
rdims = tuple(d for d in c if d.is_Root) | ||
ddims = tuple(d for d in c if not d.is_Root) | ||
|
||
for d in (ddims + rdims)[:-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.
I don't think this is safe, a root
dimension should never need to have its name change so this should only loop through ddims
and raise an error if there is still clashes
devito/ir/equations/algorithms.py
Outdated
subs[d] = resolutions[d] | ||
else: | ||
try: | ||
subs[d] = d._rebuild(d.name+str(count[d.name])) |
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.
devito standard is formating '%s%s' % (d.name, count[d.name])
not string concatenation
devito/ir/equations/algorithms.py
Outdated
subs[d] = d._rebuild(d.name+str(count[d.name])) | ||
count[d.name] += 1 | ||
except KeyError: | ||
subs[d] = d._rebuild(d.name+'0') |
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.
same, '%s0' % d.name
ddims = tuple(d for d in c if not d.is_Root) | ||
|
||
for d in (ddims + rdims)[:-1]: | ||
if d in resolutions.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.
and
resolutions[d] not in clashes
Need to make sure you don't replace a clash by another but that case gets tricky because you can't set resoltuion[d]
anymore or it would replace the existing one by a different one, not sure what the best way is for this very corner case.
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 could always check that the incremented dimension name isn't in dims
and incrementing until it is not?
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.
also no need for .keys()
devito/symbolics/manipulation.py
Outdated
# the object rather than the property, as the latter can | ||
# sometimes have default values which do not match the | ||
# default for the class | ||
v = {i: getattr(expr, "_"+i) for i in expr.__rkwargs__} |
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.
'_%s' % i
What if there isn't one and there is only the self.rkwargs
one directly .function
for any AbstractFunction
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 quite sure I understand?
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.
Some type have attribute such as self.function
that are in rkwargs
but self._function
doesn't exist
Check out this pull request on See visual diffs & provide feedback on Jupyter Notebooks. Powered by ReviewNB |
subs[d] = resolutions[d] | ||
else: | ||
try: | ||
subs[d] = d._rebuild('%s%s' % (d.name, count[d.name])) |
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.
use the sregistry
instead of count
You can plumb it down the compiler pass from the caller site -- it's one of the kwargs
@@ -220,8 +221,11 @@ def writes(self): | |||
def xreplace(self, rules): | |||
return LoweredEq(self.lhs.xreplace(rules), self.rhs.xreplace(rules), **self.state) | |||
|
|||
def func(self, *args): | |||
return self._rebuild(*args, evaluate=False) | |||
def func(self, *args, **kwargs): |
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.
since it's a Reconstructable, and in particular a Pickable, I think that the following should suffice:
func = Pickable._rebuild
|
||
|
||
@_uxreplace_dispatch.register(IterationSpace) | ||
def _(expr, rule, mode='ux'): |
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.
expr
should be called ispace
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.
but most importantly, see comments on slack
ddims = tuple(d for d in c if not d.is_Root) | ||
|
||
for d in (ddims + rdims)[:-1]: | ||
if d in resolutions.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.
also no need for .keys()
Superseded by #2269 |
Requires a compiler pass to resolve clashing dimension names, which in turn requires additions to
uxreplace
so it can be used onConditionalDimension
s.