Julia @在茱莉亚的边界上传播
考虑以下情况:Julia @在茱莉亚的边界上传播,julia,bounds-checker,Julia,Bounds Checker,考虑以下情况: struct A <: AbstractArray{Int, 2} N::Int end struct B <: AbstractArray{Int, 2} A::A Func end ... @inline Base.getindex(A::A, i::Int, j::Int) = begin @boundscheck (1 <= i <= A.N && 1 <= j <= A.N) || t
struct A <: AbstractArray{Int, 2}
N::Int
end
struct B <: AbstractArray{Int, 2}
A::A
Func
end
...
@inline Base.getindex(A::A, i::Int, j::Int) = begin
@boundscheck (1 <= i <= A.N && 1 <= j <= A.N) || throw(BoundsError())
i - j
end
Base.@propagate_inbounds Base.getindex(B::B, i::Int, j::Int) = begin
B.Func(B.A[i, j])
end
struct A我只需要使用您的定义即可:
julia> f1(x, i, j) = return x[i,j]
f2(x, i, j) = @inbounds return x[i,j]
julia> f1(A(5), 123, 123)
ERROR: BoundsError
Stacktrace:
[1] getindex at ./REPL[3]:2 [inlined]
[2] f1(::A, ::Int64, ::Int64) at ./REPL[4]:1
julia> f2(A(5), 123, 123)
0
julia> f1(B(A(5), identity), 123, 123)
ERROR: BoundsError
Stacktrace:
[1] getindex at ./REPL[3]:2 [inlined]
[2] getindex at ./REPL[3]:6 [inlined]
[3] f1(::B, ::Int64, ::Int64) at ./REPL[4]:1
julia> f2(B(A(5), identity), 123, 123)
0
正如我在评论中提到的,@inbounds
只有在类型稳定的函数中才起作用。在全局范围(如REPL)或类型不稳定的函数(如引用非常量全局或抽象类型字段或数组的函数)中测试它不会删除这些边界检查
请注意,您对B
的定义可能会导致类型不稳定,因为Julia无法知道它存储的是什么函数。它们在您发布的最小示例中并不明显,但这可能是您更复杂的原始问题的根本原因。更好的定义是:
struct B{F} <: AbstractArray{Int, 2}
A::A
Func::F
end
struct B{F}我只需要使用您的定义即可:
julia> f1(x, i, j) = return x[i,j]
f2(x, i, j) = @inbounds return x[i,j]
julia> f1(A(5), 123, 123)
ERROR: BoundsError
Stacktrace:
[1] getindex at ./REPL[3]:2 [inlined]
[2] f1(::A, ::Int64, ::Int64) at ./REPL[4]:1
julia> f2(A(5), 123, 123)
0
julia> f1(B(A(5), identity), 123, 123)
ERROR: BoundsError
Stacktrace:
[1] getindex at ./REPL[3]:2 [inlined]
[2] getindex at ./REPL[3]:6 [inlined]
[3] f1(::B, ::Int64, ::Int64) at ./REPL[4]:1
julia> f2(B(A(5), identity), 123, 123)
0
正如我在评论中提到的,@inbounds
只有在类型稳定的函数中才起作用。在全局范围(如REPL)或类型不稳定的函数(如引用非常量全局或抽象类型字段或数组的函数)中测试它不会删除这些边界检查
请注意,您对B
的定义可能会导致类型不稳定,因为Julia无法知道它存储的是什么函数。它们在您发布的最小示例中并不明显,但这可能是您更复杂的原始问题的根本原因。更好的定义是:
struct B{F} <: AbstractArray{Int, 2}
A::A
Func::F
end
structb{F}您是如何测试它的?在全局范围内或存在任何类型的不稳定性时,边界检查不会被忽略。您的示例还缺少那些getindex
方法上的类型批注。@MattB。哦我更新了代码。当我使用类型A的实例时,边界检查也被省略。你是如何测试它的?在全局范围内或存在任何类型的不稳定性时,边界检查不会被忽略。您的示例还缺少那些getindex
方法上的类型批注。@MattB。哦我更新了代码。当我使用类型A的实例时,边界检查也被省略。