-
Notifications
You must be signed in to change notification settings - Fork 37
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
Implement all_assigned
#362
base: master
Are you sure you want to change the base?
Conversation
`all_assigned(x)` performs `isassigned(x, i)` at each index for `x`. This implementation is very simple but may not be immediately obvious because it requires iterating over the indices _not_ the values.
Codecov Report
@@ Coverage Diff @@
## master #362 +/- ##
=======================================
Coverage 90.27% 90.27%
=======================================
Files 9 9
Lines 1337 1337
=======================================
Hits 1207 1207
Misses 130 130 📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
What needs to extend this? |
My current use case is supporting the unsafe_getindex1(x, i::Int) = @inbounds(x[i])
Base.@assume_effects :nothrow unsafe_getindex2(x, i::Int) = @inbounds(x[i]) In case like julia> Core.Compiler.infer_effects(unsafe_getindex1, Tuple{Vector{Int},Int})
(?c,+e,?n,+t)
julia> Core.Compiler.infer_effects(unsafe_getindex2, Tuple{Vector{Int},Int})
(?c,+e,+n,+t) But even cases where we can't have an undefined error and in bounds should be sufficient, the compiler still doesn't know there won't be an error. julia> Core.Compiler.infer_effects(unsafe_getindex1, Tuple{Tuple{Int},Int})
(?c,+e,?n,+t)
julia> Core.Compiler.infer_effects(unsafe_getindex2, Tuple{Tuple{Int},Int})
(?c,+e,+n,+t) So any array whose inbound elements are guaranteed to be assigned could benefit from extending this. |
I don't quite understand why that would need an interface function? Your example doesn't use |
The previous example was just demonstrating that even if we know something is inbounds the compiler often can't ensure an error isn't going to be thrown. Assuring that all indices are defined allows us to make some assumptions that can speed things up sometimes function find_first1(v, x)
@assert ArrayInterfaceCore.all_assigned(x)
i = unsafe_find_first(v, x)
i === 0 ? nothing : i
end
Base.@assume_effects :terminates_locally :nothrow function unsafe_find_first(v, x)
for i in eachindex(x)
isequal(@inbounds(x[i]), v) && return i
end
return 0
end
function find_first2(v, x)
for i in eachindex(x)
isequal(@inbounds(x[i]), v) && return i
end
return 0
end In this case we get a small performance boost julia> let x = rand(100);
@btime find_first1($(x[end]), $x)
@btime find_first2($(x[end]), $x)
end
121.440 ns (0 allocations: 0 bytes)
155.948 ns (0 allocations: 0 bytes) I can see how the utility of this may not be readily apparent. Maybe this sort of example needs to be in an extended help section for |
Update to the latest version? |
all_assigned(x)
performsisassigned(x, i)
at each index forx
. This implementation is very simple but may not be immediately obvious because it requires iterating over the indices not the values.