Thanks for the analysis. My understanding is about the same as yours.
But, as I described earlier, speed drops (after this initialization
section) if I use 0.0 at the first element. That is what puzzles me.
On 2014年08月26日 21:30, Tomas Lycken wrote:
Looking at those statements with the |@time| macro will give you some
useful information. I did the following:
|julia> cl = rand(485)
485-element Array{Float64,1}:
0.186576
⋮
0.299499
julia> lagcl_precompilation_1 = [0, cl[1:end-1]]
julia> lagcl_precompilation_2 = [0.0, cl[1:end-1]]
julia> @time lagcl1 = [0, cl[1:end-1]]
elapsed time: 0.000862835 seconds (23496 bytes allocated)
julia> @time lagcl2 = [0.0, cl[1:end-1]]
elapsed time: 6.5775e-5 seconds (9696 bytes allocated)
|
As you can see, a lot more memory was allocated when using |0| for the
first element rather than |0.0|. The reason for this is that when you
use |0.0|, all elements are the same type (|Float64|) so Julia only
needs to allocate memory for the output once. I’m not 100% sure on
exactly which approach is actually taken for the other case, but I can
imagine it would be something like
1) allocate an array for |Int64|s, since the first element is |Int64|
2) notice that the second element is not an |Int64|, so allocate an
array of |Any| instead (i.e. an array of pointers to the actual elements)
3) fill the |Any| array with the data from input
4) check the type of all elements, and realize that the array type can
be tightened to |Float64|
5) Allocate space for a |Float64| array, copy all data to it and return it
Julia is probably slightly smarter than this, so don’t take the above
description as a definitive description of how the language actually
works. However, just by looking at the first two steps you can see
that if the type of the first element is the same as the type of all
other elements, we’ll be able to skip a bunch of intermediate steps
and still get the same result: an array of |Float64|s. Of course, if
we only allocate and copy once, everything is going to be much faster.
Type stability
<http://docs.julialang.org/en/latest/manual/performance-tips/#write-type-stable-functions>
is one of the things that many new Julians struggle with in the
beginning, so it’s really worth reading up on. Writing type stable
code is really key to utilize all the good things about Julia’s
performance.
// T
On Tuesday, August 26, 2014 3:14:54 PM UTC+2, K leo wrote:
julia> cl
485-element Array{Float64,1}:
4555.0
4601.0
4693.0
4678.0
⋮
5821.0
5854.0
5828.0
julia> lagcl = [0, cl[1:end-1]]
485-element Array{Float64,1}:
0.0
4555.0
4601.0
4693.0
⋮
5842.0
5821.0
5854.0
Then thinking to make the types of elements to be the same, I changed
the above to the following (notice it is 0.0 instead of 0 at the
first
element). lagcl is only a temp array in a function that is called
only
at initialization time and lagcl[1] is actually not referenced at
all.
But the speed of my app after the initialization dropped to half.
Nothing else was changed, and I verified it by changing 0.0 back
to 0 at
the first element. Could anyone explain?
julia> lagcl = [0.0, cl[1:end-1]]
485-element Array{Float64,1}:
0.0
4555.0
4601.0
4693.0
⋮
5842.0
5821.0
5854.0