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: Fix data dependency issue on dimension-wide WAR #2200

Closed
wants to merge 1 commit into from

Conversation

georgebisbas
Copy link
Contributor

No description provided.

@georgebisbas georgebisbas self-assigned this Sep 8, 2023
@georgebisbas georgebisbas linked an issue Sep 8, 2023 that may be closed by this pull request
@georgebisbas georgebisbas changed the title compiler: Fix data dependency issue on dimension-wide WAR close 2194 compiler: Fix data dependency issue on dimension-wide WAR Sep 8, 2023
@codecov
Copy link

codecov bot commented Sep 8, 2023

Codecov Report

Merging #2200 (fc57d84) into master (5eaad80) will decrease coverage by 24.19%.
The diff coverage is 96.15%.

@@             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     
Files Changed Coverage Δ
devito/ir/support/basic.py 84.58% <80.00%> (-8.29%) ⬇️
tests/test_operator.py 96.41% <100.00%> (-1.33%) ⬇️

... and 192 files with indirect coverage changes

Copy link
Contributor

@FabioLuporini FabioLuporini left a 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

# For example:
# Eq(u[0, y], 1)
# Eq(u[1, y+1], u[0, 1])
elif i.is_Number and not j.is_Number:
Copy link
Contributor

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):

Copy link
Contributor

Choose a reason for hiding this comment

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

(parametrize test?)

Copy link
Contributor

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):

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

Copy link
Contributor

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)
Copy link
Contributor

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

Copy link
Contributor

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

Copy link
Contributor

@FabioLuporini FabioLuporini left a 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):
Copy link
Contributor

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

@@ -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):
Copy link
Contributor

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 Show resolved Hide resolved
# 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
Copy link
Contributor

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.

Copy link
Contributor

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...

# For example:
# Eq(u[0, y], 1)
# Eq(u[1, y+1], u[0, 1])
elif i.is_Number and not j.is_Number:
Copy link
Contributor

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:
   ..

@FabioLuporini
Copy link
Contributor

Also: pep8 isn't honored. See failing build

Copy link
Contributor

@FabioLuporini FabioLuporini left a 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 ..."


# We are writing over an entire dimension
# but reading from one point.
# If there are overlaps between the two
Copy link
Contributor

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...")

# Eq(u[1, 1], u[0, y+1])
ret.append(S.Infinity)

# We are writing over an entire dimension
Copy link
Contributor

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

Copy link
Contributor

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"

if i.is_Number and j.is_Number:
return Vector(S.ImaginaryUnit)
else:
# If both i and j are not numbers,
Copy link
Contributor

Choose a reason for hiding this comment

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

Drop this paragraph

devito/ir/support/basic.py Show resolved Hide resolved
georgebisbas added a commit that referenced this pull request Sep 20, 2023
Co-Authored-By: AndrewCheng827 <ac1721.ac.uk>
@georgebisbas
Copy link
Contributor Author

Closing in favour of #2212

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.

Faulty Data Dependence Analysis
3 participants