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



Reply via email to