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

​

Reply via email to