Julia: @inbounds 和 @propagate_inbounds
探究 Julia 的
@inbounds和@propagate_inbounds。
背景
近期在开发一个软件包,需要创建一些自定义矩阵,在设计 getindex 方法时,需要加入检查索引边界的代码,并且提供跳过边界检查的方式。
官方文档 详细讨论了这个主题,包括 @inbounds 和 @propagate_inbounds 的使用方式,但是较为简略,且没有提供示例代码,下文将演示这两个宏的使用方式,以及它们的性能差异。
@inbounds
当我们尝试访问不存在的索引时,Julia 会抛出 BoundsError 异常,我们可以通过 @inbounds 来跳过边界检查。
1 | |
只需要在调用 g 时加入 @inbounds 即可跳过边界检查。
1 | |
多层检查:@propagate_inbounds
问题
如果函数有多层的边界检查,最外层的 @inbounds 只能跳过最外层的边界检查,内层的边界检查仍然会被执行。
1 | |
经典解决方案
修改 f 函数,在每一层函数调用,加入 @inbounds,可以跳过边界检查。
1 | |
在 Julia 官方库 LinearAlgebra.jl 中,广泛使用了 @inbounds,例如 Tridiagonal 矩阵:

@propagate_inbounds
@propagate_inbounds 可以帮我们解决在多层调用时,需要为每一层函数调用加入 @inbounds 的问题。它可以用来传播边界检查的上下文,允许我们在多层函数调用时跳过边界检查。
1 | |
这样, f 就可以把边界检查的忽略信息传递给 g,只要调用 f 时加上 @inbounds,就可以跳过内部的边界检查。
需要注意 @propagate_inbounds 并不会无限传递下去,如果 g 函数内部调用了其他有边界检查的函数,需要使用 @propagate_inbounds 或 @inbounds。
性能差异
下面我们来测试 @inbounds 和 @propagate_inbounds 的性能差异,测试代码如下,f1 使用 @inbounds,f2 使用 @propagate_inbounds。
1 | |
可以认为两者没有性能差异。

结论
@inbounds 可以跳过单层函数调用的边界检查,在最外调用函数的时候可以使用,有助于提高性能,但也要注意访问的安全性。
@propagate_inbounds 可以跳过多层函数调用的边界检查,适用于多层函数调用的场景,例如开发软件包。这个宏能够提供更好的代码整洁性,避免了在每一层函数调用都加入 @inbounds 的麻烦。
综合来看,两者并没有性能差异,在开发软件包时使用 @propagate_inbounds 是更好的选择。