2

What's the best way to build a Julia array element by element when I am not sure of the final array size? In my problem, I am building the array in a single for loop.

So far, I have figured out I can either push into the array or index into a pre-allocated array:

using BenchmarkTools

function push_to_array!(array, N)
    for i in 1:N
        # some computation
        push!(array, rand(Int64))
    end
end

function fill_array!(array, N)
    for i in 1:N
        # some computation
        array[i]=rand(Int64)
    end
end

N = 100_000_000 # unknown in the real problem

empty = Vector{Int64}()
preallocated = Vector{Int64}(undef, 2*N) # 2*N represents some upper bound on N

@btime push_to_array!(empty, N)
#  28.272 s (6 allocations: 0 bytes)
@btime fill_array!(preallocated, N)
#  2.449 s (0 allocations: 0 bytes)

So filling a pre-allocated array is a lot faster than pushing, however, it's a bit cumbersome as I need to trim the output with correct_size = preallocated[1:N].

Is there a faster/better way of doing this?

1
  • 1
    If you have a rough idea of the final size, you can use sizehint! on the output array before you start pushing. Commented Apr 13, 2021 at 18:33

1 Answer 1

5

In Julia you have views - no trimming required. Simply do:

correct_size = @view preallocated[1:1_000_000]

or

correct_size = view(preallocated, 1:1_000_000)

Now this operation is very cheap (BTW note also that you are not bencharking correctly as @time measures both compile time and execution time):

julia> using BenchmarkTools

julia> @btime correct_size = @view $preallocated[1:1_000_000];
  1.800 ns (0 allocations: 0 bytes)

In conclusion making a view is basically free.

Finally, note that you can just resize! the array (the time cost is the same as in case of a @view):

resize!(preallocated, 1_000_000)
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the tips, I have updated the question with @btime timings. So I take it that the best way to build the array is by preallocating or using sizehint! and then using @view or resize!.
Btw, what's the dollarsign for in @view $preallocated? I couldn't find it in manual.
The dollar sign $ is understood by the @btime macro - it makes the global variable type stable otherwise we would be measuring unboxing time of it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.