-
Notifications
You must be signed in to change notification settings - Fork 44
Closed
Description
Bounds-checking is currently considerably more expensive with an IdOffsetRange
than with a Base.OneTo
. For example, depending on how we define setindex!
:
julia> x = zeros(Int, 10_000);
julia> y = OffsetVector(x, 0);
julia> fill1d(x) = for i in axes(x,1); x[i] = i; end
julia> @btime fill1d($x);
10.634 μs (0 allocations: 0 bytes)
# Current definition
@inline function Base.setindex!(A::OffsetVector, val, i::Int)
@boundscheck checkbounds(A, i)
@inbounds parent(A)[parentindex(Base.axes1(A), i)] = val
A
end
julia> @btime fill1d($y);
16.032 μs (0 allocations: 0 bytes)
# Alternate definition where bounds checking is forwarded to the parent
@propagate_inbounds function Base.setindex!(A::OffsetVector, val, i::Int)
parent(A)[parentindex(Base.axes1(A), i)] = val
A
end
julia> @btime fill1d($y);
12.505 μs (0 allocations: 0 bytes)
The present definition was only introduced to perform bounds-checking at the top level so that error messages reflect the indices of the OffsetArray
and not that of the parent. However this appears to come with a significant performance penalty.
The trend also persists with larger arrays.
julia> x = zeros(Int, 10_000_000);
julia> y = OffsetVector(x, 0);
julia> @btime fill1d($x);
11.920 ms (0 allocations: 0 bytes)
julia> @btime fill1d($y); # present definition
17.342 ms (0 allocations: 0 bytes)
julia> @btime fill1d($y); # forward bounds checking to the parent
13.341 ms (0 allocations: 0 bytes)
Also: why is bounds-checking so expensive? Is it being performed per element? Should it not be possible to perform a bounds-check for the axis in one-go, and not per element?
Metadata
Metadata
Assignees
Labels
No labels