2
\$\begingroup\$

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
CiaPan
1,9101 gold badge12 silver badges17 bronze badges
asked Jul 18, 2021 at 11:30
\$\endgroup\$
2
  • \$\begingroup\$ There's no need to swap x and y if they're equal, so I'd prefer less-or-equal instead of less-than. \$\endgroup\$ Commented Jul 19, 2021 at 13:37
  • \$\begingroup\$ Have a look at the code in SortingNetworks.jl. They seem to be using your approach, but with a branching minmax. Probably for good reason. \$\endgroup\$ Commented Nov 9, 2021 at 9:23

2 Answers 2

1
\$\begingroup\$

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)
answered Jul 19, 2021 at 10:26
\$\endgroup\$
0
\$\begingroup\$

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).

answered Jul 23, 2021 at 12:41
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.