# Most performant way of updating vector values?

Several times in my code, I will update the values of a vector. I want to avoid allocations and other stuff, and make it as performant as possible. At the beginning the vector is preallocated with `n` dummy values, and then I will update it. What is the best way?

E.g, I have:

``````n = 100
work_values = zeros(n)
function new_val(i)
return 2i+5
end
``````

and I now want to set each of the `n` values to the value according to `i`. Doing either:

``````work_values = map(i -> new_val(i), 1:n)
work_values = [new_val(i) for i in 1:n]
work_values .= new_val.(1:n)
``````

I am afraid might cause some problem due to allocation/reallocation, but I am really not very certain about this. Alternatively, I could try:

``````foreach(i -> work_values[i] = new_val(i), 1:n)
``````

but at some point, someone told me that `foreach` could cause problems with performance. Finally, maybe

``````for i in 1:n
work_values[i] = new_val(i)
end
``````

would be the best, but putting in a full `for` loop also feels a bit excessive.

(after creating the initial `work_values` vector, I will update its content many times, each time with different values, not just with what `new_val` gives n this example)

1 Like

The for loop will work without allocations, for sure.

``````work_values .= new_val.(1:n)
``````

Are you sure this pattern allocates? Note that if you have something more complex than `1:n` that could be triggering allocations, and not the broadcasted equal sign.

``````using BenchmarkTools

function set_values!(a,b)
b .= a
end

a = LinRange(0,1,100)
b = zeros(100)

@btime set_values!(a,b)
128.973 ns (0 allocations: 0 bytes)
``````
1 Like

Note that these two are not updating the values, but creating new arrays. In the case of mapping, you want to use `map!`:

``````julia> x = [1,2,3];

julia> map!(i -> 2i, x, 1:3);

julia> x
3-element Vector{Int64}:
2
4
6
``````
1 Like

I had someone cautioning me on using broadcasting, but again, it might be dependent on the setting and fine in general. if it work, something like the `work_values .= new_val.(1:n)` seems good.

Get it, so using `map!` might be good? Or would I have the same problems as I (might) have when using an anonymous function in the `foreach` loop?

`map!` is fine. The broadcasing is also fine. The `foreach` can be problematic in the global scope, because then you are modifying a global variable, but within a function it is also fine:

``````julia> updatex(f,x,r) = foreach(i -> x[i] = f(i), r)
updatex (generic function with 1 method)

julia> x = [1,2,3];

julia> @btime updatex(i -> 2i, \$x, 1:3)
1.847 ns (0 allocations: 0 bytes)

julia> x
3-element Vector{Int64}:
2
4
6
``````

(but `map!` and the broadcasting are by far more idiomatic for this)

1 Like

Got it, thanks a lot for the help

Another vote for broadcasting here. Itâ€™s both performant and the most elegant and idiomatic. I wonder why someone cautioned you against it.

1 Like

I think it might have been something else in the situation that made broadcasting problematic, and I erroneously overinterpreted it as to be generally cautious.

1 Like

Maybe itâ€™s because the left-most â€ś.â€ť (in `.=`) is doing a lot of heavy lifting here but is very inconspicuous. Omission leads to identical results just with allocation, which might be the reason people think broadcasting leads to allocation. FWIW, I remember 2 topics here on discourse where someone forgot/didnâ€™t think about that dot and asked for performance help.

1 Like