The Union array is going to be slower, since it’s heterogeneous, so if you can do with what hcat gave you I would consider it. You might want to look into a Dataframe, it’s a kind of Matrix structure, where each column has its own type.
I did try to make a fully heterogeneous array (but failed), just to find out how I would do it:
That, I believe, would by as slow as the Any array had I succeeded (i.e. with Any instead of Real there). I’m not sure if the Union array will be slightly faster, likely, since with Real is a bit more general.
By the way @Raymond, it appears you are timing the creation of dataset, whereas I believe @Palli was talking about how fast methods that operate on dataset would be.
EDIT: I’m referring to this quote:
EDIT: Here’s an illustration.
julia> A = randn(1000, 100); typeof(A)
Matrix{Float64} (alias for Array{Float64, 2})
julia> B = Matrix{Union{Int,Float64}}(A); typeof(B)
Matrix{Union{Float64, Int64}} (alias for Array{Union{Float64, Int64}, 2})
julia> C = Matrix{Real}(A); typeof(C)
Matrix{Real} (alias for Array{Real, 2})
julia> D = Matrix{Any}(A); typeof(D)
Matrix{Any} (alias for Array{Any, 2})
julia> A == B == C == D
true
julia> function f(mat)
map(mat) do x
x^2 + sin(13 * x)
end
end
f (generic function with 1 method)
julia> using BenchmarkTools
julia> X1 = @btime f($A);
1.678 ms (2 allocations: 781.30 KiB)
julia> X2 = @btime f($B);
1.798 ms (2 allocations: 781.30 KiB)
julia> X3 = @btime f($C);
3.503 ms (100005 allocations: 2.29 MiB)
julia> X4 = @btime f($D);
3.487 ms (100005 allocations: 2.29 MiB)
julia> X1 == X2 == X3 == X4
true
So, f is faster when using Matrix{Float64} or Matrix{Union{Int,Float64}} inputs but slower when using Matrix{Real} or Matrix{Any} inputs.
EDIT (this will be the last one!): If I use a for loop instead of map, the timing of f(C) and f(D) is about 3 times worse, and if I use broadcasting instead of a loop the timing of f(C) and f(D) is an additional 2 times worse! Meanwhile, f(A) and f(B) take approximately the same amount of time in each case. My guess as to why using map is faster for f(C) and f(D) is because I am introducing a function barrier, though I’m not entirely sure that’s the reason.