-
Notifications
You must be signed in to change notification settings - Fork 229
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
compiler: Revamp lowering of IndexDerivatives #2310
Conversation
@@ -324,10 +324,12 @@ def test_redundant_derivatives(self): | |||
assert len(get_arrays(op)) == 0 | |||
assert op._profiler._sections['section0'].sops == 74 | |||
exprs = FindNodes(Expression).visit(op) | |||
assert len(exprs) == 6 | |||
assert len(exprs) == 5 |
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.
Note for reviewers:
this is a result of this tweak: https://github.com/devitocodes/devito/pull/2310/files#diff-a012e847c0c9841809763e4c55eb89ee0ee9b985614693494911e4ab32bda7f1R193-R194
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## master #2310 +/- ##
=======================================
Coverage 86.67% 86.67%
=======================================
Files 229 229
Lines 43107 43150 +43
Branches 7996 8001 +5
=======================================
+ Hits 37363 37401 +38
- Misses 5050 5053 +3
- Partials 694 696 +2 ☔ View full report in Codecov by Sentry. |
@@ -803,9 +815,13 @@ def _evaluate(self, **kwargs): | |||
return EvalDerivative(expr, base=self.base) | |||
|
|||
|
|||
class DiffDerivative(IndexDerivative, DifferentiableOp): |
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.
Why not make IndexDerivative
directlu DifferentiableOp
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 tried all sort of ways; remember we discussed a sympy issue a few days ago, and eventually I landed here...
So, IndexDerivative
was (master branch) a DifferentiableOp
, since IndexSum
was (master branch) a DifferentiableOp
. The heart of the problem is: if an object is non differentiable but one of its arguments is, then a reconstruction will make the parent object differentiable as well
This new structuring distinguishes between DiffDerivative (differentiable) and the lower-level IndexDerivative (non-differentiable). This ensures that, once inside the compiler, everything will have been lowered such that no Differentiable objects can ever be (re)constructed, which in essence will make compilation behave as expected, having ruled out by construction any funky-ness due to the way SymPy handles subclasses and reconstruction
Does it make sense or does it sound like a ranting? I can elaborate or explain in a call if necessary
|
||
@property | ||
def scaling(self): | ||
return Mul(*[d.spacing**self.order for d in self.mapper]) |
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.
While yes we wanna go there, this doesn't belong here, this belongs in Derivatives
so we can progressively make the eval_fd
dimension-indep fir easier compiler pass irrespective of expand/no-expand
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 expression will also be wrong for an IndexDerivative along a diagonal such as
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 I can drop it, will 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.
removed.
@@ -247,7 +247,7 @@ def make_derivative(expr, dim, fd_order, deriv_order, side, matvec, x0, symbolic | |||
# Pure number | |||
pass | |||
|
|||
deriv = IndexDerivative(expr*weights, {dim: indices.free_dim}) | |||
deriv = DiffDerivative(expr*weights, {dim: indices.free_dim}, deriv_order) |
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 we should drop the if exand/else
since can just do this part and return deriv.evaluate
if expand=true
since IndexDerivative
are properly evaluable since a few PR ago
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 worry it opens a Pandora's box that I wouldn't be very willing to deal with at this stage, but I can try
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'm now opening a different PR for this
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.
How do u suggest we handle the second part of the if
:
if not expand and indices.expr is not None:
IIRC indices.expr
may be None for some low order derivatives.
I think we would first have to normalizate behavior at the top (always produce indices.expr
) then we could do what you suggested
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.
Hum right, didn't think that indices.expr would be None I guess we can park it for now
@@ -755,11 +758,12 @@ def __new__(cls, expr, mapper, **kwargs): | |||
obj = super().__new__(cls, expr, dimensions) | |||
obj._weights = weights | |||
obj._mapper = frozendict(mapper) | |||
obj._order = order |
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.
comment on this?
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 can actually probably drop it, it's now unused. It's the derivative order
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.
removed
|
||
def _lower_exprs(expressions, subs): |
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.
Note for later: subs
should not be added to mapper as it would make compiler pass easier (pure sympy) and do the subs at the tail end of iet pass
e, clusters = _core(a, c, weights, reusables, mapper, sregistry) | ||
args.append(e) | ||
processed.extend(clusters) | ||
if not isinstance(expr, IndexDerivative): |
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.
single dispatch on expr?
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 gonna work unless we handle it here , but don't remember the details, will look again
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 no sorry, ignore the comment above, I had totally misunderstood it
Yes, I like the idea, will change tomorrow
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.
done single-dispatch
@@ -63,9 +63,13 @@ def _normalize_kwargs(cls, **kwargs): | |||
# Distributed parallelism | |||
o['dist-drop-unwritten'] = oo.pop('dist-drop-unwritten', cls.DIST_DROP_UNWRITTEN) | |||
|
|||
# Misc | |||
# Code generation options for derivatives |
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 this be packed up into a function in a new file like devito.core.utils.py
? It's exactly repeated in both cpu.py
and gpu.py
. Something like parse_cgen_options(o, oo)
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.
probably yes, but you'll see there are a lot of small differences between the two
Not happening before Rice anyway, but I'll take note
88c39ba
to
7d76070
Compare
219b8c8
to
8db6b8b
Compare
This paves the way for external customisation, e.g.
w[i]*u[x + i]
vsw[i]*(u[x + i] - u[x - i])