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

RFC: make boundscheck a value #22826

Merged
merged 3 commits into from
Aug 30, 2017
Merged

RFC: make boundscheck a value #22826

merged 3 commits into from
Aug 30, 2017

Conversation

vtjnash
Copy link
Member

@vtjnash vtjnash commented Jul 16, 2017

This PR turns the @boundscheck macro from being a special lexically scoped construct to being a normal value (Expr(:boundscheck) returns true, but can be replaced with false by inference). This lets us treat it as a normal Bool parameter during control flow, rather than requiring special handling:

 macro boundscheck(blk)
-    # hack: use this syntax since it avoids introducing line numbers
-    :($(Expr(:boundscheck,true));
-      $(esc(blk));
-      $(Expr(:boundscheck,:pop)))
+    return Expr(:if, Expr(:boundscheck), esc(blk))
 end

I'm opening this to try to get a sense for whether this seems like an improvement or not. I noticed that as we moved to a more-linear IR, we need to bracket many more statements Expr(:inbounds), so this also should makes the IR a bit more concise.

This design fixes #18261 also, since we no longer need to keep track of the lexical boundscheck scope of the callee while inlining (something that we don't do very well at now), just the inbounds scope of the caller (which was easy to add).

Indicates the beginning or end of a section of code that performs a bounds check. Like `inbounds`,
a stack is maintained, and the second argument can be one of: `true`, `false`, or `:pop`.
Has the value `false` if inlined into a section of code marked with `@inbounds`,
otherwise hase the value `true`.
Copy link
Member

Choose a reason for hiding this comment

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

hase -> has

@JeffBezanson
Copy link
Member

This seems like a really good idea (as evinced by code deletion :) ). That boundscheck meta elim code was a nightmare.
Any data on IR size, sysimg size impact?

end

"""
@inbounds(blk)

Eliminates array bounds checking within expressions.

In the example below the bound check of array A is skipped to improve performance.
In the example below the in-range check for referencing
element i of array A is skipped to improve performance.
Copy link
Contributor

Choose a reason for hiding this comment

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

should probably code highlight i and A here

@vtjnash vtjnash force-pushed the jn/boundscheck-revised branch from 377fbac to 87c8326 Compare July 21, 2017 16:04
Copy link
Contributor

@tkelman tkelman left a comment

Choose a reason for hiding this comment

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

unaddressed review above

@tkelman
Copy link
Contributor

tkelman commented Jul 21, 2017

should update devdocs. the meaning of different possible numbers of arguments here is worth documenting in comments and/or devdocs as it's not obvious

@vtjnash vtjnash force-pushed the jn/boundscheck-revised branch from 87c8326 to 12dfdc9 Compare August 3, 2017 19:18
@tkelman tkelman dismissed their stale review August 4, 2017 01:32

addressed, though there's a test/staged failure across multiple platforms, and how the variable numbers of arguments thread through src is still a little confusing

@vtjnash vtjnash force-pushed the jn/boundscheck-revised branch 2 times, most recently from 7750694 to 9d0b926 Compare August 7, 2017 16:42
@tkelman
Copy link
Contributor

tkelman commented Aug 7, 2017

@nanosoldier runbenchmarks(ALL, vs=":master")

@nanosoldier
Copy link
Collaborator

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @ararslan

@vtjnash vtjnash force-pushed the jn/boundscheck-revised branch from 9d0b926 to d001ebb Compare August 8, 2017 01:07
@vtjnash
Copy link
Member Author

vtjnash commented Aug 8, 2017

hm, looks like some optimization passes weren't working right after some small changes to the AST. Let's try that again @nanosoldier runbenchmarks(ALL, vs=":master")

@nanosoldier
Copy link
Collaborator

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @ararslan

vtjnash added a commit that referenced this pull request Aug 8, 2017
sufficient for removing dead code left over in typical boundscheck blocks
in PR #22826
vtjnash added a commit that referenced this pull request Aug 8, 2017
sufficient for removing dead code left over in typical boundscheck blocks
in PR #22826
vtjnash added a commit that referenced this pull request Aug 9, 2017
Sufficient for removing dead code left over in typical boundscheck blocks
in PR #22826 

Also reorders the meta-elimination-pass so that the later passes can be more effective
@vtjnash vtjnash force-pushed the jn/boundscheck-revised branch from d001ebb to 279eccb Compare August 9, 2017 03:05
@vtjnash
Copy link
Member Author

vtjnash commented Aug 9, 2017

Better, but still all jumbled up with the optimization change. Let's try again, now that that's on master: @nanosoldier runbenchmarks(ALL, vs=":master")

@nanosoldier
Copy link
Collaborator

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @ararslan

@vtjnash
Copy link
Member Author

vtjnash commented Aug 9, 2017

OK, I don't see anything now that doesn't appear to be noise.

@oscardssmith
Copy link
Member

You don't think the 7 ~8x slowdowns in sumcartesianrange are real?

@vtjnash
Copy link
Member Author

vtjnash commented Aug 9, 2017

No. Locally, I don't see a difference between them. However, I see it does have a run-to-run variation of up to 50x.

@tkelman
Copy link
Contributor

tkelman commented Aug 10, 2017

That's likely a variance introduced by this branch or recently on master, I haven't seen that elsewhere. That seems like an undesirable loss in performance predictability, what's the underlying cause?

@vtjnash
Copy link
Member Author

vtjnash commented Aug 10, 2017

That variance number was computed on master

@vtjnash
Copy link
Member Author

vtjnash commented Aug 10, 2017

Let's see a comparison run anyways @nanosoldier runbenchmarks(ALL, vs=":master")

@@ -696,7 +697,7 @@ end

function push!(a::Array{Any,1}, @nospecialize item)
_growend!(a, 1)
arrayset(a, item, length(a))
arrayset(true, a, item, length(a))
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 sure what exactly arrayset(true, ...) does, but isn't it safe to skip the bounds check here? The only case I can see is when _growend!() would fail to grow an empty array.

Copy link
Member Author

Choose a reason for hiding this comment

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

No, grow can also fail due to finalizers

Copy link
Contributor

Choose a reason for hiding this comment

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

The bound check doesn't really help catching that though....

@nanosoldier
Copy link
Collaborator

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @ararslan

@oscardssmith
Copy link
Member

That looks consistent to me.

@vtjnash vtjnash force-pushed the jn/boundscheck-revised branch from 279eccb to ae9cc56 Compare August 26, 2017 18:33
@vtjnash
Copy link
Member Author

vtjnash commented Aug 26, 2017

@nanosoldier runbenchmarks(ALL, vs=":master")

@nanosoldier
Copy link
Collaborator

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @ararslan

@vtjnash vtjnash force-pushed the jn/boundscheck-revised branch from ae9cc56 to 273d4ac Compare August 28, 2017 18:43
@yuyichao
Copy link
Contributor

@nanosoldier runbenchmarks(ALL, vs=":master")

it is much easier if this value gets treated as a normal parameter
as that allows all of the normal control flow logic to apply
rather than require a complete reimplementation of it
@vtjnash vtjnash force-pushed the jn/boundscheck-revised branch from 273d4ac to d9dde5d Compare August 28, 2017 21:51
@nanosoldier
Copy link
Collaborator

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @ararslan

This optimization had been occurring before, but still isn't entirely valid
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Incorrect bounds check elimination
9 participants