Hi all
I have got some questions about array construction JIT speed.
abstract Aimmutable B <: A endimmutable C <: A end
b = B()
c = C()
@time getindex(B, b, b)
@time Base.vect(b, b);
0.006129 seconds (6.03 k allocations: 276.191 KB)
0.005339 seconds (3.43 k allocations: 175.144 KB)
Restart the kernel and change the order of statments:
b = B()
c = C()
@time Base.vect(b, b)
@time getindex(B, b, b);
0.009543 seconds (7.02 k allocations: 328.819 KB)
0.006245 seconds (2.44 k allocations: 128.672 KB)
According to source code, vect{T}(X::T...) = T[ X[i] for i=1:length(X) ]
So I would expect when calling vect, the JIT for vect & getindex would both get
done.
However the test showed that Julia still need to do an extra JIT for getindex?
Why is that?
In the source code, I see 2 methods are implemented for getindex
# T[x...] constructs Array{T,1}function getindex(T::Type, vals...)
a = Array(T,length(vals))
@inbounds for i = 1:length(vals)
a[i] = vals[i]
end
return aend
function getindex(::Type{Any}, vals::ANY...)
a = Array(Any,length(vals))
@inbounds for i = 1:length(vals)
a[i] = vals[i]
end
return aend
Why is the second one required? I have read the performance-tips, but in this
case type of a is stable: always T.
In one of my application, I have to store elements of different subtypes in the
array and I got big hit by the JIT performance.
Below is a minimal example.
Restart the kernel and run the following:
b = B()
c = C()
@time getindex(A, b, b)
@time getindex(A, b, c)
@time getindex(A, c, c)
@time getindex(A, c, b)
@time getindex(A, b, c, b)
@time getindex(A, b, c, c);
0.007756 seconds (6.03 k allocations: 276.426 KB)
0.007878 seconds (5.01 k allocations: 223.087 KB)
0.005175 seconds (2.44 k allocations: 128.773 KB)
0.004276 seconds (2.42 k allocations: 127.546 KB)
0.004107 seconds (2.45 k allocations: 129.983 KB)
0.004090 seconds (2.45 k allocations: 129.983 KB)
As you see, each time I construct the array for different combination of
elements, it has to do a JIT.
I also tried [...] instead of T[...], it appeared worse.
Restart the kernel and run the following:
b = B()
c = C()
@time Base.vect(b, b)
@time Base.vect(b, c)
@time Base.vect(c, c)
@time Base.vect(c, b)
@time Base.vect(b, c, b)
@time Base.vect(b, c, c);
0.008252 seconds (6.87 k allocations: 312.395 KB)
0.149397 seconds (229.26 k allocations: 12.251 MB)
0.006778 seconds (6.86 k allocations: 312.270 KB)
0.113640 seconds (178.26 k allocations: 9.132 MB, 3.04% gc time)
0.050561 seconds (99.19 k allocations: 5.194 MB)
0.031053 seconds (72.50 k allocations: 3.661 MB)
In my application I face a lot of different subtypes: each element is of type
NTuple{N, A} where N can change. So in the end the application was stuck in JIT.
What's the best way to get around it? The only way I can think of is to create
a wrapper, say W, and box all my element into W before entering the array.
immutable W
value::NTupleend