-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Open
Labels
docsThis change adds or pertains to documentationThis change adds or pertains to documentationsortingPut things in orderPut things in order
Description
Hi!
Full thread here:
https://discourse.julialang.org/t/why-does-sortperm-allocate-here/112028/3
Doing a small example it is easy to see that sortperm! will allocate:
function main()
Cartesians = Vector{CartesianIndex{2}}(undef, 100)
SortedIndices = collect(LinearIndices(Cartesians))
# Fill the array with random CartesianIndex{2} values
for i in 1:100
# Assuming you want indices in the range 1:10 for both dimensions
Cartesians[i] = CartesianIndex(rand(1:10), rand(1:10))
end
for iter = 1:5
b = @allocated sortperm!(SortedIndices, Cartesians)
println("Iteration ", iter, " : ", b , " allocated bytes")
end
end
main()
Iteration 1 : 896 allocated bytes
Iteration 2 : 896 allocated bytes
Iteration 3 : 896 allocated bytes
Iteration 4 : 896 allocated bytes
Iteration 5 : 896 allocated bytes
This is because a scratch-space has not been preallocated. Dan kindly provided the following code which fixes the issue:
function main()
Cartesians = Vector{CartesianIndex{2}}(undef, 10000)
SortedIndices = collect(LinearIndices(Cartesians))
_, t = Base.Sort.make_scratch(nothing, eltype(SortedIndices), length(Cartesians))
# Fill the array with random CartesianIndex{2} values
for i in 1:100
# Assuming you want indices in the range 1:10 for both dimensions
Cartesians[i] = CartesianIndex(rand(1:10), rand(1:10))
end
for iter = 1:5
b = @allocated sortperm!(SortedIndices, Cartesians; scratch=t)
println("Iteration ", iter, " : ", b , " allocated bytes")
end
end
I would not have been able to discover this without help since the ? sortperm!
returns:
sortperm!(ix, A; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward, [dims::Integer])
Like sortperm, but accepts a preallocated index vector or array ix with the same axes as A. ix is initialized to contain the values LinearIndices(A).
│ Warning
│
│ Behavior can be unexpected when any mutated argument shares memory with any other argument.
│ Julia 1.9
│
│ The method accepting dims requires at least Julia 1.9.
Examples
≡≡≡≡≡≡≡≡
julia> v = [3, 1, 2]; p = zeros(Int, 3);
julia> sortperm!(p, v); p
3-element Vector{Int64}:
2
3
1
julia> v[p]
3-element Vector{Int64}:
1
2
3
julia> A = [8 7; 5 6]; p = zeros(Int,2, 2);
julia> sortperm!(p, A; dims=1); p
2×2 Matrix{Int64}:
2 4
1 3
julia> sortperm!(p, A; dims=2); p
2×2 Matrix{Int64}:
3 1
2 4
With no mention of scratch-space.
I believe that any !
function is assumed to be non-allocating, and that this goes against this.
I went to check help for sort!
too and did not find any mention of scratch space either.
### Tasks
Metadata
Metadata
Assignees
Labels
docsThis change adds or pertains to documentationThis change adds or pertains to documentationsortingPut things in orderPut things in order