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的实例时,边界检查也被省略。