# Efficient conditional in-place assignment for arrays?

**URL:** <https://discourse.julialang.org/t/efficient-conditional-in-place-assignment-for-arrays/74593>\
**Category:** Performance\
**Tags:** arrays\
**Created:** [January 14, 2022, 5:27am UTC](https://discourse.julialang.org/t/efficient-conditional-in-place-assignment-for-arrays/74593 "2022-01-14T05:27:06Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![robsmith11](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/robsmith11/32/29641_2.png) [@robsmith11](https://discourse.julialang.org/u/robsmith11)\
**Post date:** [January 14, 2022, 5:27am UTC](https://discourse.julialang.org/t/efficient-conditional-in-place-assignment-for-arrays/74593/1 "2022-01-14T05:27:06Z")

</div>

Is there any way to the get the efficient assignment of `f1` with the nicer syntax of `f2`? Something like a view or conditional SubArray?

```julia
julia> function f1!(xs)
        for i in eachindex(xs)
         if xs[i] < 0.5
          xs[i] = 0.0
         end
        end
       end
f1! (generic function with 1 method)

julia> function f2!(xs)
        xs[xs .< 0.5] .= 0.0
       end
f2! (generic function with 1 method)

julia> v = rand(100);

julia> @btime f1!($v);
  121.872 ns (0 allocations: 0 bytes)

julia> @btime f2!($v);
  659.691 ns (3 allocations: 656 bytes)

```

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [January 14, 2022, 5:30am UTC](https://discourse.julialang.org/t/efficient-conditional-in-place-assignment-for-arrays/74593/2 "2022-01-14T05:30:23Z")

</div>

```julia
julia> @btime f1!(v) setup=(v=rand(10^4))
  39.736 μs (0 allocations: 0 bytes)

julia> g!(v) = map!(v,v) do i
           ifelse(i<0.5, 0.0, i)
       end
g! (generic function with 1 method)

julia> @btime g!(v) setup=(v=rand(10^4))
  4.675 μs (0 allocations: 0 bytes)

```

---

<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:** [January 14, 2022, 7:51am UTC](https://discourse.julialang.org/t/efficient-conditional-in-place-assignment-for-arrays/74593/3 "2022-01-14T07:51:14Z")

</div>

Try `replace!`:

```julia
1.7.0> @btime g!(v) setup=(v=rand(10^4));
  6.120 μs (0 allocations: 0 bytes)

1.7.0> h!(v) = replace!(x->ifelse(x<0.5, zero(x), x), v)
h! (generic function with 1 method)

1.7.0> @btime h!(v) setup=(v=rand(10^4));
  1.190 μs (0 allocations: 0 bytes)

```

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [January 14, 2022, 10:22am UTC](https://discourse.julialang.org/t/efficient-conditional-in-place-assignment-for-arrays/74593/4 "2022-01-14T10:22:35Z")

</div>

@DNF, we are used to call `f2!()` style, MATLAB-style. Would you know if MATLAB also implements your style of solution? Thanks.

---

<div class="post-metadata">

**Author:** ![Marco\_Lombardi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marco_lombardi/32/14608_2.png) [@Marco\_Lombardi](https://discourse.julialang.org/u/Marco_Lombardi)\
**Post date:** [January 14, 2022, 11:30am UTC](https://discourse.julialang.org/t/efficient-conditional-in-place-assignment-for-arrays/74593/5 "2022-01-14T11:30:24Z")

</div>

> [@DNF](#):
>
> `@btime h!(v) setup=(v=rand(10^4));`

Try `@inbounds` and `@simd` in your original `f1!`:

```julia-repl
julia> function f1!(xs)
        @inbounds @simd for i in eachindex(xs)
         if xs[i] < 0.5
          xs[i] = 0.0
         end
        end
       end
f1! (generic function with 1 method)

julia> @btime f1!(v) setup=(v=rand(10^4))
  961.094 ns (0 allocations: 0 bytes)

```

On my computer this is equivalent to `h!` above of @DNF.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [January 14, 2022, 11:46am UTC](https://discourse.julialang.org/t/efficient-conditional-in-place-assignment-for-arrays/74593/6 "2022-01-14T11:46:52Z")

</div>

@Marco_Lombardi, `@inbounds` seems to have 40x speedup impact while `@simd` only 1%?

---

<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:** [January 14, 2022, 12:14pm UTC](https://discourse.julialang.org/t/efficient-conditional-in-place-assignment-for-arrays/74593/7 "2022-01-14T12:14:47Z")

</div>

You don’t need `@simd` to get SIMD. The compiler decided to do it on its own, enabled by `@inbounds`. The `@simd` macro is redundant here.

---

<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:** [January 14, 2022, 12:26pm UTC](https://discourse.julialang.org/t/efficient-conditional-in-place-assignment-for-arrays/74593/8 "2022-01-14T12:26:29Z")

</div>

> [@rafael.guerra](#):
>
> Would you know if MATLAB also implements your style of solution?

There is a `replace` function in Matlab, but only for strings. I don’t know of any built-in functionality like this.

But now that Matlab code is jit-compiled, one can actually write a loop and test how well it does:

Warning: Matlab code! ☠

```julia
function v = replacev(v, lim)
    for ii = 1:length(v)
        val = v(ii);
        if val < lim
            v(ii) = 0;
        end
    end
end

```

Benchmark:

```julia
>> v = rand(10000, 1);

>> timeit(@()replacev(v, 0.5))
ans =
   6.9344e-05

```

70us is roughly half the speed of `f1!` _without_ `@inbounds`. Not so bad actually, and almost as fast as the standard Matlab solution

```julia
v(v < lim) = 0;

```

which runs in 60us.
