-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Improve performance annotation docs #17722
Changes from 3 commits
eb010b5
b61dfc4
cbaadba
de765cb
e321636
429636b
469bd48
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1038,11 +1038,6 @@ properties. | |
**This feature is experimental** and could change or disappear in future | ||
versions of Julia. | ||
|
||
Note: While :obj:`@simd` needs to be placed directly in front of a | ||
loop, both :obj:`@inbounds` and :obj:`@fastmath` can be applied to | ||
several statements at once, e.g. using ``begin`` ... ``end``, or even | ||
to a whole function. | ||
|
||
Here is an example with both :obj:`@inbounds` and :obj:`@simd` markup:: | ||
|
||
function inner( x, y ) | ||
|
@@ -1082,6 +1077,13 @@ On a computer with a 2.4GHz Intel Core i5 processor, this produces:: | |
GFlop = 1.9467069505224963 | ||
GFlop (SIMD) = 17.578554163920018 | ||
|
||
Certain preconditions need to be met before using some of these macros. | ||
Both :obj:`@simd` and :obj:`@inbounds` do a simple rewrite of the expression | ||
and delegate the optimizations to the compiler, much like ``:meta`` expressions. | ||
This means they merely give the compiler license to optimize. Whether | ||
it actually does so depends on the compiler. How you write the expressions | ||
will have a final say on the output. | ||
|
||
The range for a ``@simd for`` loop should be a one-dimensional range. | ||
A variable used for accumulating, such as ``s`` in the example, is called | ||
a *reduction variable*. By using :obj:`@simd`, you are asserting several | ||
|
@@ -1096,10 +1098,8 @@ properties of the loop: | |
A loop containing ``break``, ``continue``, or :obj:`@goto` will cause a | ||
compile-time error. | ||
|
||
Using :obj:`@simd` merely gives the compiler license to vectorize. Whether | ||
it actually does so depends on the compiler. To actually benefit from the | ||
current implementation, your loop should have the following additional | ||
properties: | ||
To actually benefit from the current implementation of :obj:`@simd`, your loop | ||
should have the following additional properties: | ||
|
||
- The loop must be an innermost loop. | ||
- The loop body must be straight-line code. This is why :obj:`@inbounds` is | ||
|
@@ -1114,6 +1114,51 @@ properties: | |
LLVM auto-vectorization may kick in automatically, leading to no further | ||
speedup with :obj:`@simd`. | ||
|
||
While :obj:`@simd` needs to be placed in front of a loop, that is not the case | ||
for :obj:`@inbounds`. It can be placed in front of any expression as long as it | ||
is inside a function. The only place where it can be outside of a function | ||
definition is in front of a loop. | ||
:: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This double-colon is malformed RST I think, see the sphinx errors
|
||
julia> x = [1] | ||
|
||
julia> @inbounds if true | ||
x[2] | ||
end | ||
ERROR: BoundsError: attempt to access 1-element Array{Int64,1} at index [2] | ||
in getindex(::Array{Int64,1}, ::Int64) at ./array.jl:344 | ||
|
||
julia> function f(x) | ||
@inbounds if true | ||
x[2] | ||
end | ||
end | ||
|
||
julia> f(x) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems like a dangerous example since this should segfault. |
||
|
||
julia> @inbounds for i in 1:10 | ||
x[2] | ||
end | ||
|
||
Be aware that using it before a function declaration will have no effect. | ||
To use :obj:`@inbounds` on a block of code, put it before a ``begin ... end`` | ||
statement. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is correct. |
||
:: | ||
julia> @inbounds function g(x) #Won't remove bound checks nor warn you | ||
for i in 1:10 | ||
x[i] = x[i]^2 | ||
end | ||
end | ||
|
||
julia> function g(x) | ||
@inbounds begin | ||
for i in 1:10 | ||
x[i] = x[i]^2 | ||
end | ||
end | ||
end | ||
|
||
:obj:`@fastmath` can be placed in front of most expressions without any problem. | ||
|
||
Here is an example with all three kinds of markup. This program first | ||
calculates the finite difference of a one-dimensional array, and then | ||
evaluates the L2-norm of the result:: | ||
|
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 information (outside functions only in front of loops) is news to me. Does this mean that a stand-alone statement
is malformed?
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.
It is not. It just may or may not disable boundscheck depending on many other compiler heuristics.
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.
FWIW,
The only place where it can be outside of a function definition is in front of a loop
is very misleading....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 should it say? What does malformed mean in programming btw?
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.
Well, it is also just not true. At global scope it is perfectly fine to write:
But whereas without
@inbounds
this would print1
, with@inbounds
it doesn't print anything. However, I think the inbounds meta information is ignored outside of a function.I would simplify the description to say that
@inbounds
can be written in front of any expression, and in some expressions this may be useful to limit the scope of what you are declaring to be "in bounds".