-
Notifications
You must be signed in to change notification settings - Fork 9
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
delay setindex! inbounds check indexlinear #40
Conversation
# delay the boundscheck in the IndexCartesian version and not set @inbounds meta here | ||
setindex!(A, v, Base._to_subscript_indices(A, i...)...) | ||
end | ||
|
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.
The weird thing here is that even if this is not added, the test still passes with pkg> test
but not with pkg> include("test/runtest.jl")
. Either I'm using @boundscheck
wrongly or there's some bug upstream...
Edit: might be related to JuliaLang/Pkg.jl#2109
Hmm, that "fallback" may date from the days where Julia supported partial linear indexing. What circumstances does it come up in? Generally iteration should automatically use the "correct" scheme. |
This is the current behavior in master: julia> using PaddedViews
julia> A = reshape(collect(1:6), 2, 3);
julia> Ap = PaddedView(missing, A, (0:4, 0:4));
julia> Ap[1] = 0 # this is dangerous
0
julia> Ap
5×5 PaddedView(missing, ::Array{Int64,2}, (0:4, 0:4)) with eltype Union{Missing, Int64} with indices 0:4×0:4:
missing missing missing missing missing
missing 1 3 5 missing
missing 2 4 6 missing
missing missing missing missing missing
missing missing missing missing missing The bounds check is incomplete because of the julia> Ap[1] = 0
ERROR: ArgumentError: PaddedViews do not support (re)setting the padding value. Consider making a copy of the array first.
Stacktrace:
[1] (::PaddedViews.var"#_throw_argument_error#3")() at /Users/jc/Documents/Julia/PaddedViews.jl/src/PaddedViews.jl:175
[2] setindex! at /Users/jc/Documents/Julia/PaddedViews.jl/src/PaddedViews.jl:179 [inlined]
[3] setindex!(::PaddedView{Union{Missing, Int64},2,Tuple{UnitRange{Int64},UnitRange{Int64}},Array{Int64,2}}, ::Int64, ::Int64) at /Users/jc/Documents/Julia/PaddedViews.jl/src/PaddedViews.jl:191
[4] top-level scope at REPL[5]:1 |
Sorry, what I meant was "should we delete that |
Hmmm, the indexing implementation is still opaque to me. Looks like is still needed. If I remove that method, then it goes to and then errors julia> Ap[1] = 1
ERROR: ArgumentError: indexed assignment with a single value to many locations is not supported; perhaps use broadcasting `.=` instead?
Stacktrace:
[1] setindex_shape_check(::Int64, ::Int64)
@ Base ./indices.jl:258
[2] _unsafe_setindex!(#unused#::IndexCartesian, A::Base.ReshapedArray{Union{Missing, Int64}, 1, PaddedView{Union{Missing, Int64}, 2, Tuple{UnitRange{Int64}, UnitRange{Int64}}, Matrix{Int64}}, Tuple{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64}}}, x::Int64, I::Int64)
@ Base ~/Documents/Julia/julia/base/multidimensional.jl:886
[3] _setindex!
@ ~/Documents/Julia/julia/base/multidimensional.jl:877 [inlined]
[4] setindex!(A::PaddedView{Union{Missing, Int64}, 2, Tuple{UnitRange{Int64}, UnitRange{Int64}}, Matrix{Int64}}, v::Int64, I::Int64)
@ Base ~/Documents/Julia/julia/base/abstractarray.jl:1217
[5] top-level scope
@ REPL[6]:1 |
Things like this works, though. I guess this is something you expected? (I didn't do # https://github.com/JuliaLang/julia/blob/c24a93253db45131983c665373d17759f9d4b758/base/multidimensional.jl#L874-L898
function _setindex!(l::IndexStyle, A::AbstractArray, x, I::Union{Real, AbstractArray}...)
@_inline_meta
@boundscheck checkbounds(A, I...)
_unsafe_setindex!(l, _maybe_ind2sub(_maybe_reshape(l, A, I...)), x, I...)
A
end
_maybe_ind2sub(l, A, I) = I
_maybe_ind2sub(::IndexCartesian, A, I) = _unsafe_ind2sub(size(A), I...) |
Key design principle: Base has lots of unspecific methods that convert all of Julia's fancy indexing into either linear index calls
Avoid creating such methods if at all possible. If you have them, you're essentially signing up to support the entire gamut of indexing methods, and that's basically a nightmare to support. Let Base do the work. OK, now I see the problem: This seems to be an argument to remove the bounds-checking from the Alternatively we could implement a custom |
|
It is in the paddedview bounds, but not in the parent data array bounds. The bounds check here is actually doing some eager bounds check for the parent data array, so I think that still lies in the concept of bounds check :P. |
But you can access it at that location, right? So it's inbounds for
That's circular. It's only eagerly doing the bounds check for you because you've currently implemented the test/error in a |
This is a hard truth and a valid mental model. I'm not sure if this fits the PaddedViews case, because it can also be weird that |
Personally, I would say the only valid way of eliminating the overhead of the "interior check" (I'm going to stop referring to this as a "bounds check" because as @mbauman says, it isn't) is to write code that directly reaches in to the private implementation of I think this is one of those "just live with the performance overhead" cases. |
This is needed to bypass the
@inbounds
check in the fallback implementation, and use our own bounds checking, otherwise,setindex!
for indexlinear will always be set with@inbounds
mode.I'm not very sure if this is the right fix, perhaps I've used
@boundscheck
wronglyPaddedViews.jl/src/PaddedViews.jl
Lines 172 to 187 in ff689b1