So, I wrote this function to sort three numbers in Julia. Any feedback on readability, performance, and Julian-ness would be appreciated.
function sort_asc(a, b, c)
# defined in function so as not to overwrite Base.minmax
minmax(x, y) = ifelse(x < y, (x, y), (y, x))
l1, h1 = minmax(a, b)
lo, h2 = minmax(l1, c)
md, hi = minmax(h1, h2)
return lo, md, hi
end
2 Answers 2
As it turns out
function sort_asc(a, b, c)
l1, h1 = minmax(a, b)
lo, h2 = minmax(l1, c)
md, hi = minmax(h1, h2)
return lo, md, hi
end
results in the exact same native assembly instructions on my machine (compared to the branchless version). So, given its greater simplicity, I think this is the best version so far.
Here are comparisons to other implementations
function sort3(a, b, c)
l1, h1 = minmax(a, b)
lo, h2 = minmax(l1, c)
md, hi = minmax(h1, h2)
return lo, md, hi
end
@inline minmax_nb(x, y) = ifelse(isless(x, y), (x, y), (y, x))
function sort3_nb(a, b, c)
l1, h1 = minmax_nb(a, b)
lo, h2 = minmax_nb(l1, c)
md, hi = minmax_nb(h1, h2)
return lo, md, hi
end
function sort3_koen(a, b, c)
lo, md = minmax(a, b)
if md > c
hi = md
lo, md = minmax(lo, c)
else
hi = c
end
return lo, md, hi
end
Here is the benchmark code
using BenchmarkTools
function map_sort3!(f::F, out, data) where F
@inbounds for i in eachindex(out, data)
a, b, c = data[i]
out[i] = f(a, b, c)
end
end
for f in [sort3, sort3_nb, sort3_koen]
print(rpad(f, 12), ":")
@btime map_sort3!($f, out, data) setup=begin
data = [ntuple(i -> rand(Int), 3) for _ in 1:10_000]
out = similar(data)
end evals=1
end
And here are the results on my machine:
sort3 : 17.286 μs (0 allocations: 0 bytes)
sort3_nb : 17.624 μs (0 allocations: 0 bytes)
sort3_koen : 21.776 μs (0 allocations: 0 bytes)
I'd expect this to be marginally faster:
(lo,md) = minmax(a,b)
if md > c
hi = md
(lo,md) = minmax(lo,c)
else
hi = c
I don't know where this sits in the scale of Julianesquinness since I'm not familiar with Julia (not even sure if my "if-else" adheres to its syntax, but the intention should be clear).
x
andy
if they're equal, so I'd prefer less-or-equal instead of less-than. \$\endgroup\$minmax
. Probably for good reason. \$\endgroup\$