-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Don't ask the call site to provide @inbounds
when iterating over an array
#27384
Comments
This is quite closely related to #21402, but indeed things are different now that we only have one method — and don't need to assume that the caller did the start/next/done dance correctly. |
Slower than v0.6.x? |
65% slower on 0.7 when comparing bounds checking enabled vs disabled. Full report: > @benchmark extrema(v) setup = (v = rand(Int, 1000))
|
I have to agree with @haampie's general point here... generic code should be able to be just as fast as concretely-typed code, and the interfaces available for use by functions like Have we discussed having an |
I think we can do this without an |
I guess the idea of |
But doesn't the new iteration protocol give the iteration implementors enough information that they can safely add the The PR over at #27386 demonstrates (or hopefully will demonstrate once Nanosoldier is feeling better) that it's possible to check the entire domain of the state without incurring a performance penalty. Now, it's harder (impossible?) to check the entire domain with abstract iterator implementations, but #20469 (comment) is arguing that the iterator state is sufficiently complicated that it would require the caller to specifically craft an invalid state such that it passes the "done" check but still yields an out of bounds access. I was initially inclined to agree, but as I was writing this it dawned on me that the easiest way to mess this up would be by iterating over two arrays of different lengths at the same time and inadvertently mixing up the states. Is there another approach we could take here? I'd really love it if we could avoid either kludge (that is, either |
I did not think of that, and it looks pretty hard to avoid unfortunately. |
Exactly. AFAICT the previous policy is that if no-one calls something called I am however happy to agree to ditch that policy - but it's worth discussing. |
(To be honest the fact that |
Rather silly idea: if we simply renamed |
This issue came about when I discovered that
sort!
on a small vector of integers was slower than usual; further inspection shows thatextrema
is now 65% slower for a vector of 500 integers, and this is a result of bounds checks in each iteration.I would not dare to fix this by adding
@inbounds
to the loop ofextrema
, since the function is defined for iterators in general (why is itextrema
's responsibility to signal that the internals of the iterator will do inbounds things?). I'd say an iterator over an array should guarantee to stay inbounds and not require its call site to provide@inbounds
.But the issue is quite subtle. The function
iterate(A::Array, ::Int)
does something that comes close to bounds checkingbut it's not entirely bounds checking, because in principle
i
could overflow, so to be safe an actual check is required to guaranteei > 0
.The issue is a result of #27079 (more robust iteration over vectors), but in fact it cheats a bit by requiring the user to always provideEdit (sorry!): without inbounds@inbounds
.for x in xs
would do bounds checking already.Possible solutions:
for x in Mutable(xs)
that allows to modifyxs
on the go;for x in xs
is then immutable iteration by convention and can be fast even without@inbounds
.extrema(::AbstractArray)
that uses@inbounds
(meh)@inbounds
inextrema
and document that it does thatcheckbounds(Bool, ::AbstractArray, ::Int)
and use that rather than thei >= length(A) + 1
condition, and somehow tell the compileri
cannot overflow, so that thei > 0
check can be optimized away.Edit, seems like the new iteration protocol is enough to fix things.
The text was updated successfully, but these errors were encountered: