-
Notifications
You must be signed in to change notification settings - Fork 5
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
Sorting across different datatypes #17
Conversation
How does this behave with respect to inference? I guess it is stil fine for the homogeneous case, but I assume the output type of the inhomogeneous case cannot be inferred? |
Codecov Report
@@ Coverage Diff @@
## master #17 +/- ##
==========================================
+ Coverage 87.73% 88.39% +0.65%
==========================================
Files 1 1
Lines 106 112 +6
==========================================
+ Hits 93 99 +6
Misses 13 13
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
I've updated the tests. The inhomogeneous case does cost significantly more. |
It is indeed nontrivial to benchmark these methods, without the compiler not completely expanding the operation. The current benchmarks are also not the proper way of doing it, as you now rely on global variables, leading to allocations even in the homogeneous case (which should not be there). |
Do you have an idea how to benchmark properly? |
For type inference julia> @code_warntype TupleTools.sort((a,b,c))
MethodInstance for TupleTools.sort(::Tuple{Int64, Int64, Float64})
from sort(t::Tuple; lt, by, rev) @ TupleTools C:\Users\pty\.julia\dev\TupleTools\src\TupleTools.jl:243
Arguments
#self#::Core.Const(TupleTools.sort)
t::Tuple{Int64, Int64, Float64}
Body::Union{Tuple{Float64, Int64, Int64}, Tuple{Int64, Float64, Int64}, Tuple{Int64, Int64, Float64}}
1 ─ %1 = TupleTools.:(var"#sort#3")(TupleTools.isless, TupleTools.identity, false, #self#, t)::Union{Tuple{Float64, Int64, Int64}, Tuple{Int64, Float64, Int64}, Tuple{Int64, Int64, Float64}}
└── return %1
julia> @code_warntype TupleTools.sort((float(a),float(b),c))
MethodInstance for TupleTools.sort(::Tuple{Float64, Float64, Float64})
from sort(t::Tuple; lt, by, rev) @ TupleTools C:\Users\pty\.julia\dev\TupleTools\src\TupleTools.jl:243
Arguments
#self#::Core.Const(TupleTools.sort)
t::Tuple{Float64, Float64, Float64}
Body::Tuple{Float64, Float64, Float64}
1 ─ %1 = TupleTools.:(var"#sort#3")(TupleTools.isless, TupleTools.identity, false, #self#, t)::Tuple{Float64, Float64, Float64}
└── return %1 |
It also took me a while to figure out, but I think this is one (probably there are other) correct way: julia> function f(t)
@btime TupleTools.sort($t)
end
f (generic function with 1 method)
julia> f((1,2,3))
3.030 ns (0 allocations: 0 bytes)
(1, 2, 3)
julia> f((1,2,3,4))
4.924 ns (0 allocations: 0 bytes)
(1, 2, 3, 4)
julia> f((1,2,3,4,5,6,7,8))
14.466 ns (0 allocations: 0 bytes)
(1, 2, 3, 4, 5, 6, 7, 8) |
seems like these are the same julia> d=(a,b,c)
(2, 1, 3.0)
julia> @btime TupleTools.sort(d)
484.118 ns (4 allocations: 96 bytes)
(1, 2, 3.0)
julia> f((2,1,3.0))
420.930 ns (4 allocations: 96 bytes)
(1, 2, 3.0) Edit: no. your attempt seems more correct julia> e=(float(a),float(b),float(c))
(2.0, 1.0, 3.0)
julia> @btime TupleTools.sort(e)
87.097 ns (1 allocation: 32 bytes)
(1.0, 2.0, 3.0)
julia> f((2.0,1.0,3.0))
10.511 ns (0 allocations: 0 bytes)
(1.0, 2.0, 3.0) |
Ok, if it does not change the efficiency of the homogeneous case, I am willing to accept this change. Out of curiosity, where do you need this? I mostly had homogeneous tuples in mind (in particular things like multidimensional indices, sizes, ranges, … ) when developing this package. |
just an example (not exactly my application but similar idea). In some cases we want to sort the arguments before further processing. Converting to a vector hurts performance too much. julia> TupleTools.sort((zeros(3),zeros(3,3)),by=ndims)
ERROR: MethodError: no method matching _split(::Tuple{Vector{Float64}, Matrix{Float64}})
Closest candidates are:
_split(::Tuple{Vararg{T, N}} where T) where N
@ TupleTools C:\Users\pty\.julia\dev\TupleTools\src\TupleTools.jl:253
Stacktrace:
[1] _sort
@ C:\Users\pty\.julia\packages\TupleTools\ecrzx\src\TupleTools.jl:245 [inlined]
[2] sort(t::Tuple{Vector{Float64}, Matrix{Float64}}; lt::Function, by::Function, rev::Bool)
@ TupleTools C:\Users\pty\.julia\dev\TupleTools\src\TupleTools.jl:243
[3] top-level scope
@ REPL[86]:1
julia> isa((zeros(3),zeros(3,3)),NTuple)
false |
if you are still curious 👀 |
Ok looks good. I'll merge and tag a new version. |
Ok, v1.4 will soon be in the General Registry. |
Before this PR:
After this PR: