Skip to content
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 #2208

Merged
merged 79 commits into from
Oct 16, 2023

Conversation

FabioLuporini
Copy link
Contributor

Superseds #2183

No new features added; mostly restructuring, improvements, tweaks, minor fixes

@review-notebook-app
Copy link

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@codecov
Copy link

codecov bot commented Sep 18, 2023

Codecov Report

Merging #2208 (c1ebe2f) into master (b6f7308) will decrease coverage by 0.14%.
The diff coverage is 85.45%.

@@            Coverage Diff             @@
##           master    #2208      +/-   ##
==========================================
- Coverage   87.04%   86.91%   -0.14%     
==========================================
  Files         229      229              
  Lines       40955    41545     +590     
  Branches     7498     7660     +162     
==========================================
+ Hits        35648    36107     +459     
- Misses       4695     4816     +121     
- Partials      612      622      +10     
Files Coverage Δ
devito/core/operator.py 85.16% <100.00%> (ø)
devito/finite_differences/finite_difference.py 100.00% <100.00%> (+1.92%) ⬆️
devito/finite_differences/tools.py 92.85% <100.00%> (-0.87%) ⬇️
devito/ir/clusters/algorithms.py 97.29% <100.00%> (+0.17%) ⬆️
devito/ir/clusters/visitors.py 90.08% <100.00%> (-2.55%) ⬇️
devito/ir/equations/algorithms.py 100.00% <100.00%> (ø)
devito/ir/equations/equation.py 89.47% <100.00%> (ø)
devito/ir/iet/nodes.py 92.05% <ø> (ø)
devito/ir/stree/algorithms.py 91.55% <100.00%> (ø)
devito/ir/support/__init__.py 100.00% <100.00%> (ø)
... and 48 more

... and 3 files with indirect coverage changes

Copy link
Contributor

@georgebisbas georgebisbas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not finished yet, will look again

try:
relations = {tuple(sorted(c.ispace.itdims, key=key))}
except ValueError:
# See issue #X
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#x ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2204, fixing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btw; this is not a new issue; it's in fact a long standing issue that now crops up here (as well)


def tailor_properties(properties, ispace):
"""
Create a new Properties object off `properties` that retains all and only
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do not "create", right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not?

@@ -506,7 +536,7 @@ def __getitem__(self, key):
return super(IntervalGroup, self).__getitem__(key)
elif isinstance(key, slice):
retval = super(IntervalGroup, self).__getitem__(key)
return IntervalGroup(retval, relations=self.relations)
return IntervalGroup(retval, relations=self.relations, mode=self.mode)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

empty line as above?


@cached_property
def nonderived_directions(self):
return {k: v for k, v in self.directions.items() if not k.is_Derived}


null_ispace = IterationSpace([])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

devito/finite_differences/finite_difference.py Outdated Show resolved Hide resolved
devito/finite_differences/finite_difference.py Outdated Show resolved Hide resolved
"""
indices = tuple(reversed(self))

free_dim = StencilDimension(self.free_dim.name,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.free_dim.transpose

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

@@ -308,7 +295,8 @@ def dspace(self):

# Special case: if the factor of a ConditionalDimension has value 1,
# then we can safely resort to the parent's Interval
intervals = intervals.promote(lambda d: d.is_Conditional and d.factor == 1)
key = lambda d: d.is_Conditional and d.factor == 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not handled yet but would add d.condition is None for safety as will probably show up to have both factor and condition

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

for i in properties:
for d in as_tuple(i):
if d not in ispace.itdims:
properties = properties.drop(d)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed? It's also slightly cheaper to do that first since everything added above is in ispace.itdims

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to remove stuff that would merely represent pollution after e.g. a reconstruction

this doesn't impact functionality; but it makes the objects neater

and yes, ok, I'll move it above

if e2 == e1:
# No luck, stick to `e` to preserve e.g. the original
# coefficient factorization
processed.append(e)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be worth to checke1 == e before factorize to skip it if not needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would be wrong. There can be factorization opportunities even if the aggregator spits out the same equations

devito/symbolics/inspection.py Show resolved Hide resolved
devito/tools/data_structures.py Show resolved Hide resolved
if py_ge_37:
def filter_ordered(elements, key=None):
# This method exploits the fact that dictionary keys are unique and ordered
# (since Python 3.7). It's concise and often faster for larger lists
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How much faster?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

significantly, but I don't remember the band, this was one of several compilation speed improvements

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry wrote too fast. I mean how "bad" is it with python <3.7 if we just drop the old version

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in some benchmarks I've tried it was up to 10% ! But only the bigger ones IIRC (e.g. tti)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For 10% I don't think it's worth keeping both just ditch the numpy one

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Turns out I could...

But only as long as we officially discontinue py36.
I had (sort-of) documented this in the comment above:

        # This method exploits the fact that dictionary keys are unique and ordered
        # (since Python 3.7). It's concise and often faster for larger lists

devito/types/dimension.py Outdated Show resolved Hide resolved
@FabioLuporini
Copy link
Contributor Author

I was nearly forgetting.

Bonus:

compilation speed now approx twice as fast

@@ -693,6 +711,10 @@ def _evaluate(self, **kwargs):
return expr


ordering_of_classes.insert(ordering_of_classes.index('Derivative') + 1,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this for?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adding comment in upcoming PR

devito/finite_differences/finite_difference.py Outdated Show resolved Hide resolved
free_dim = self.free_dim.transpose()

try:
expr = self.expr._subs(self.free_dim, -free_dim)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's not part of self.free_dim.transpose() ?

else:
new_args.append(a)
if not covered:
new_args.append(v)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have v twice in the case candidates, other = [], [relation, v] so probably if not covered and candidates

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the sympy And will automatically simplify it away

return wrapper

@_normalize
def intersection(self, o):
def intersection(self, o, relations, mode):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should relations/mode default to self ? Same below

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's all handled via the _normalize decorator

tot = 0
for v in as_mapper(self, lambda i: i.ispace).values():
exprs = [i.pivot for i in v]
tot += estimate_cost(_cse(exprs, make), True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_cse is a bit pricey to call here no?

if py_ge_37:
def filter_ordered(elements, key=None):
# This method exploits the fact that dictionary keys are unique and ordered
# (since Python 3.7). It's concise and often faster for larger lists
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For 10% I don't think it's worth keeping both just ditch the numpy one

devito/types/dense.py Show resolved Hide resolved
@mloubout mloubout force-pushed the revamp-opt-derivs-final branch from a96a803 to 7af8fa3 Compare October 2, 2023 17:45
@FabioLuporini FabioLuporini force-pushed the revamp-opt-derivs-final branch 2 times, most recently from b1fcb66 to 043591c Compare October 9, 2023 07:30
@mloubout mloubout force-pushed the revamp-opt-derivs-final branch from 9126ec3 to c1ebe2f Compare October 13, 2023 22:10
@FabioLuporini FabioLuporini merged commit fb32972 into master Oct 16, 2023
32 checks passed
@FabioLuporini FabioLuporini deleted the revamp-opt-derivs-final branch October 16, 2023 12:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants