I noticed that sort!
is allocating here:
x = rand(10, 10);
@time sort!(x, dims=1);
# 0.000016 seconds (20 allocations: 960 bytes)
And I’m not sure why. Here is the investigation I’ve done:
using BenchmarkTools
function f(x::Matrix)
for i in axes(x,2)
sort!(@view x[:,i])
end
x
end
function g(x::Matrix)
sort!(x, dims=1)
end
r = rand(1000, 1000);
r2 = copy(r);
f(r) == g(r2)
@btime f(x) setup=(x=rand(1000,1000)); # 39.049 ms (0 allocations: 0 bytes)
@btime g(x) setup=(x=rand(1000,1000)); # 38.280 ms (2000 allocations: 93.75 KiB)
# and worse:
@btime f(x) setup=(x=rand(10,100_000)); # 12.799 ms (0 allocations: 0 bytes)
@btime g(x) setup=(x=rand(10,100_000)); # 16.860 ms (200000 allocations: 9.16 MiB)
Why does the builtin method allocate and what are the runtime implications?
@edit sort!(rand(1000,1000), dims=1))
reveals:
function sort!(A::AbstractArray;
dims::Integer,
alg::Algorithm=defalg(A),
lt=isless,
by=identity,
rev::Union{Bool,Nothing}=nothing,
order::Ordering=Forward)
ordr = ord(lt, by, rev, order)
nd = ndims(A)
k = dims
1 <= k <= nd || throw(ArgumentError("dimension out of range"))
remdims = ntuple(i -> i == k ? 1 : size(A, i), nd)
for idx in CartesianIndices(remdims)
Av = view(A, ntuple(i -> i == k ? Colon() : idx[i], nd)...)
sort!(Av, alg, ordr)
end
A
end