Julia: @inbounds and @propagate_inbounds
Explore
@inbounds
and@propagate_inbounds
in Julia.
Background
I am developing a package recently, which needs to create some custom matrices. When designing the getindex
function, I need to add code to do bounds checking and provide a way to skip bounds checking.
The official documentation discusses this topic in detail, including how to use @inbounds
and @propagate_inbounds
, but it is quite brief and does not provide example code. This article will demonstrate how to use these two macros and their performance differences.
@inbounds
When we try to access a out-of-bound index, Julia will throw a BoundsError
exception, we can use @inbounds
to skip the bounds check.
1 |
|
Add @inbounds
when calling g
to skip the bounds check.
1 |
|
Multple layers check: @propagate_inbounds
Problem
If a function has multiple layers of bounds checking, the outermost @inbounds
can only skip the outermost bounds checking, and the inner bounds checking will still be executed.
1 |
|
Classic Solution
Update the f
function, add @inbounds
in each function call to skip the bounds check.
1 |
|
In Julia official library LinearAlgebra.jl, @inbounds
is widely used, for example, the Tridiagonal matrix:
@propagate_inbounds
@propagate_inbounds
can help us solve the problem of needing to add @inbounds
to each function call in multiple layers of calls. It can be used to propagate the context of bounds checking, allowing us to skip bounds checking in multiple layers of function calls.
1 |
|
Therefor, f
can pass the information of skipping bounds checking to g
, as long as @inbounds
is added when calling f
, the inner bounds checking can be skipped.
It should be noted that @propagate_inbounds
will not be propagated indefinitely. If the g
function calls other functions with bounds checking, @propagate_inbounds
or @inbounds
should be used.
Performance Differences
Next, we will test the performance differences between @inbounds
and @propagate_inbounds
. The test code is as follows, f1
uses @inbounds
, f2
uses @propagate_inbounds
.
1 |
|
We can say that there is no performance difference between the two.
Conclusion
@inbounds
can skip the bounds check of a single layer of function calls, which can be used when calling the outermost function, helping to improve performance, but also have pay attention to the security of access.
@propagate_inbounds
can skip the bounds check of multiple layers of function calls, which is suitable for the development of packages. This macro can provide better code cleanliness, avoiding the trouble of adding @inbounds
to each layer of function calls.
Comprehensively, there is no performance difference between the two, and using @propagate_inbounds
is a better choice when developing packages.