# Most performant way of updating vector values?

**URL:** <https://discourse.julialang.org/t/most-performant-way-of-updating-vector-values/103753>\
**Category:** Performance\
**Created:** [September 11, 2023, 6:39pm UTC](https://discourse.julialang.org/t/most-performant-way-of-updating-vector-values/103753 "2023-09-11T18:39:11Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![Torkel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/torkel/32/5030_2.png) [@Torkel](https://discourse.julialang.org/u/Torkel)\
**Post date:** [September 11, 2023, 6:39pm UTC](https://discourse.julialang.org/t/most-performant-way-of-updating-vector-values/103753/1 "2023-09-11T18:39:11Z")

</div>

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:

```julia
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:

```julia
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:

```julia
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

```julia
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)

---

<div class="post-metadata">

**Author:** ![martin.d.maas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/martin.d.maas/32/50964_2.png) [@martin.d.maas](https://discourse.julialang.org/u/martin.d.maas)\
**Post date:** [September 11, 2023, 6:57pm UTC](https://discourse.julialang.org/t/most-performant-way-of-updating-vector-values/103753/2 "2023-09-11T18:57:20Z")

</div>

The for loop will work without allocations, for sure.

```julia
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.

```julia
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)

```

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [September 11, 2023, 6:59pm UTC](https://discourse.julialang.org/t/most-performant-way-of-updating-vector-values/103753/3 "2023-09-11T18:59:25Z")

</div>

> [@Torkel](#):
>
> ```julia
> work_values = map(i -> new_val(i), 1:n)
> work_values = [new_val(i) for i in 1:n]
> 
> ```

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

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

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

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

```

---

<div class="post-metadata">

**Author:** ![Torkel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/torkel/32/5030_2.png) [@Torkel](https://discourse.julialang.org/u/Torkel)\
**Post date:** [September 11, 2023, 6:59pm UTC](https://discourse.julialang.org/t/most-performant-way-of-updating-vector-values/103753/4 "2023-09-11T18:59:35Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Torkel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/torkel/32/5030_2.png) [@Torkel](https://discourse.julialang.org/u/Torkel)\
**Post date:** [September 11, 2023, 7:00pm UTC](https://discourse.julialang.org/t/most-performant-way-of-updating-vector-values/103753/5 "2023-09-11T19:00:32Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [September 11, 2023, 7:03pm UTC](https://discourse.julialang.org/t/most-performant-way-of-updating-vector-values/103753/6 "2023-09-11T19:03:57Z")

</div>

`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
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)

---

<div class="post-metadata">

**Author:** ![Torkel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/torkel/32/5030_2.png) [@Torkel](https://discourse.julialang.org/u/Torkel)\
**Post date:** [September 11, 2023, 7:05pm UTC](https://discourse.julialang.org/t/most-performant-way-of-updating-vector-values/103753/7 "2023-09-11T19:05:40Z")

</div>

Got it, thanks a lot for the help 🙂

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [September 11, 2023, 7:15pm UTC](https://discourse.julialang.org/t/most-performant-way-of-updating-vector-values/103753/8 "2023-09-11T19:15:14Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Torkel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/torkel/32/5030_2.png) [@Torkel](https://discourse.julialang.org/u/Torkel)\
**Post date:** [September 11, 2023, 7:18pm UTC](https://discourse.julialang.org/t/most-performant-way-of-updating-vector-values/103753/9 "2023-09-11T19:18:34Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)\
**Post date:** [September 13, 2023, 5:39am UTC](https://discourse.julialang.org/t/most-performant-way-of-updating-vector-values/103753/10 "2023-09-13T05:39:56Z")

</div>

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.
