-
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: Fix data dependency issue on dimension-wide WAR #2200
Conversation
Codecov Report
@@ Coverage Diff @@
## master #2200 +/- ##
===========================================
- Coverage 87.08% 62.90% -24.19%
===========================================
Files 228 144 -84
Lines 40611 22716 -17895
Branches 7429 4143 -3286
===========================================
- Hits 35367 14290 -21077
- Misses 4644 7694 +3050
- Partials 600 732 +132
|
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.
Looking good to me!
Minors: can you rebase, merge together squashable commits, rename them to honor our commit message rules (@georgebisbas can explain and point to the right documentation?
Also (another nitpick), I'm incrementally trying to shorten our comments and to wrap them around the 80th(ish) character, while the previous limit wash 90 characters long rows. While this is still loosely applied, it would help to refactor the comments to keep this mind. Also, as I said, the more compact, the better. And, final nitpick: if a comment belongs to e.g. the body of an if
, it should go inside the if
, not outside
devito/ir/support/basic.py
Outdated
# For example: | ||
# Eq(u[0, y], 1) | ||
# Eq(u[1, y+1], u[0, 1]) | ||
elif i.is_Number and not j.is_Number: |
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.
instead of not j.is_Number
you can also use j.is_Symbol
, they should be equivalent in this context
also you must cover the symmetric case:
elif (i.is_Number and j.is_Symbol) or (i.is_Symbol and j.is_Number):
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.
(parametrize test?)
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.
instead of
not j.is_Number
you can also usej.is_Symbol
, they should be equivalent in this contextalso you must cover the symmetric case:
elif (i.is_Number and j.is_Symbol) or (i.is_Symbol and j.is_Number):
For this George and I figured that we only need i.is_Number and j.is_Symbol
case since we would only have a dependency if we are reading from one location and writing over an entire dimension. The other case would have been caught previously.
Consider the equations
eq0 = Eq(u[0,y], 1)
eq1 = Eq(u[1,1], u[0, y+1])
The dependency between reading from u[0, y+1]
and writing to u[0,y]
is caught by
v = i - j
if v.is_Number and v.is_finite:
# If i and j are numbers, we append an (I) distance
if i.is_Number and j.is_Number:
return Vector(S.ImaginaryUnit)
# If both i and j are not numbers,
# there may be dimension-dependent dependencies
# so we append the distance
else:
ret.append(v)
The dependency between reading from u[0,y+1]
and writing to u[1,1]
is imaginary. Hence the algorithm doesn't append anything to the distance vector
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 not so particularly convinced we shouldn't care about the symmetrict case
what if you have
Eq(u[0, 1], 1)
Eq(u[x, y], u[0, y])
?
Also:
- you're still using "not j.is_Number", instead of "is_Symbol"
- how is your solution any stronger and/or more robust than just having
if i.is_Symbol or j.is_Symbol:
..
# If both i and j are not numbers, there may be dimension-dependent | ||
# dependencies so we append the distance | ||
else: | ||
ret.append(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.
we might want to append Infinite here, otherwise I think we would have never ended up in this place, because we would have never left the first big loop at the top of the method over the iteration intervals
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 equation pair
eq0 = Eq(u[0,y], 1)
eq1 = Eq(u[1,1], u[0, y+1])
would resulting in the execution ending up at line 435
Also I'm confused to why adding an Infinite here would help with never reaching this part of the code
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.
History requires rebase and squashing
commit messages do not adhere to our format. Please see the contributing guidelines
tests/test_ir.py
Outdated
@@ -826,6 +826,61 @@ def test_dep_nasty(self, eqns): | |||
scope = Scope(eqns) | |||
assert len(scope.d_all) == 1 | |||
|
|||
def test_2194(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.
if u are performing numerical evaluation, you should rather move these tests to TestOperator::TestLoopScheduling
You could also slightly tweak them to rather have one single macro-test with pytest.parametrize(exprs, expected)
just like we do with several other tests
tests/test_operator.py
Outdated
@@ -1933,7 +1933,65 @@ def test_topofuse_w_numeric_dim(self): | |||
op = Operator(eqns) | |||
|
|||
assert_structure(op, ['r,i', 'r'], 'r,i') | |||
|
|||
def test_2194(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.
what's the difference between these tests and the ones before?
they look redundant to me at first glance?
in fact, these seem to be a superset of those in test_ir, by also checking the structure of the resulting loop nest
if that's the case:
- compact them as a single test + py.test.parametrize
- drop the redundant tests in test_ir
devito/ir/support/basic.py
Outdated
# If i and j are numbers, we append an (I) distance | ||
if i.is_Number and j.is_Number: | ||
return Vector(S.ImaginaryUnit) | ||
# If both i and j are not numbers, there may be dimension-dependent |
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 is also another useless comment, maybe we can instead use a tiny E.g.
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.
possibly inside the else, not on the outside...
devito/ir/support/basic.py
Outdated
# For example: | ||
# Eq(u[0, y], 1) | ||
# Eq(u[1, y+1], u[0, 1]) | ||
elif i.is_Number and not j.is_Number: |
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 not so particularly convinced we shouldn't care about the symmetrict case
what if you have
Eq(u[0, 1], 1)
Eq(u[x, y], u[0, y])
?
Also:
- you're still using "not j.is_Number", instead of "is_Symbol"
- how is your solution any stronger and/or more robust than just having
if i.is_Symbol or j.is_Symbol:
..
Also: pep8 isn't honored. See failing build |
26df87c
to
482936d
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.
Left a few more comments
Also, given the nature and the size of the edits, I suggest to squash all of the 5 commits into a single commit with message "compiler: Patch ..."
devito/ir/support/basic.py
Outdated
|
||
# We are writing over an entire dimension | ||
# but reading from one point. | ||
# If there are overlaps between the two |
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.
Drop this entire paragraph (starting with "If there are overlaps...")
devito/ir/support/basic.py
Outdated
# Eq(u[1, 1], u[0, y+1]) | ||
ret.append(S.Infinity) | ||
|
||
# We are writing over an entire dimension |
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're breaking to a new line too soon. Use around 83~84 characters, then break line
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 simplify as "Writing (reading) over an entire dimension, reading (writing) from one point"
devito/ir/support/basic.py
Outdated
if i.is_Number and j.is_Number: | ||
return Vector(S.ImaginaryUnit) | ||
else: | ||
# If both i and j are not numbers, |
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.
Drop this paragraph
compiler: Addressed comments on PR #2200
1ded3da
to
76aac12
Compare
Co-Authored-By: AndrewCheng827 <ac1721.ac.uk>
76aac12
to
fc57d84
Compare
Closing in favour of #2212 |
No description provided.