Skip to content
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

Bounds-checking overhead for an IdOffsetRange #214

Closed
jishnub opened this issue Mar 1, 2021 · 0 comments · Fixed by #215
Closed

Bounds-checking overhead for an IdOffsetRange #214

jishnub opened this issue Mar 1, 2021 · 0 comments · Fixed by #215

Comments

@jishnub
Copy link
Member

jishnub commented Mar 1, 2021

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant