-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Suboptimal performance for tuples of small unions #57054
Comments
Take a look at this thread and, in particular, Jameson's comment at the end. I guess inference could be better, but it is difficult (not saying that the issue should be closed :)). |
This is precisely the perf issue that plagued InvertedIndices for so long (cf InvertedIndices.jl#39). I see it more as a general performance optimization than a specific inference problem — it'd generally be very nice if tuples of small unions could themselves optimize as though the elements weren't in a tuple. The trouble of course is that there can easily be a combinatorial explosion beyond what counts as a small union, but even just supporting |
I think it's not just tuples. For example, struct Foo{T,V}
x::T
n::V
end
bar(A) = A.n < 0 ? Foo(inv(A.x), inv(A.n)^2) : Foo(A.x, A.n^2)
baz(A) = Foo(inv(A.x), inv(A.n))
function bar2(A)
B = A.n < 0 ? baz(A) : A
return Foo(B.x, B.n^2)
end |
I think that's a very subtly different problem — in that case, Julia hit too many possibilities and gave up. The difference between tuples and structs becomes more obvious with a simpler example, wherein only one field is unstable. julia> struct Foo{T,V}
x::T
n::V
end
julia> function bar2(x, n)
y, k = n < 0 ? (inv(x), inv(n)) : (x, n)
return (y, k)
end
bar2 (generic function with 1 method)
julia> function bar3(x, n)
y, k = n < 0 ? (inv(x), inv(n)) : (x, n)
return Foo(y, k)
end
bar3 (generic function with 1 method)
julia> @code_warntype bar2(1, 2.)
# ...
Body::Tuple{Union{Float64, Int64}, Float64}
julia> @code_warntype bar3(1, 2.)
# ...
Body::Union{Foo{Float64, Float64}, Foo{Int64, Float64}} |
You're right, these are slightly different. I was actually dealing with structs when I encountered these difficulties, so I simplified the code to make a MWE with some tuples, not realizing the differences. It would be nice if this just worked for a small number of combinations, however, for a bigger value of small. I encountered this here In the case that |
For example, these two functions look like they should be equivalent, but the inferred return type of the first is a small union, as desired, while the other one isn't. Using (parametric) structs instead of tuples gives similar results.
With the return type of
bar2
in red,bar
in yellowThe text was updated successfully, but these errors were encountered: