# Comparison performance with \`any\`

**URL:** <https://discourse.julialang.org/t/comparison-performance-with-any/19478>\
**Category:** Performance\
**Created:** [January 10, 2019, 2:40pm UTC](https://discourse.julialang.org/t/comparison-performance-with-any/19478 "2019-01-10T14:40:01Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![MLackner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mlackner/32/2789_2.png) [@MLackner](https://discourse.julialang.org/u/MLackner)\
**Post date:** [January 10, 2019, 2:40pm UTC](https://discourse.julialang.org/t/comparison-performance-with-any/19478/1 "2019-01-10T14:40:01Z")

</div>

Hey!

How can I prevent this loop from allocating memory on every iteration? If I interchange `@view b[i-1:i]` with just `b` the loop does not allocate but that’s not what I want 😉.

I don’t really understand this behaviour.

```julia
using BenchmarkTools

function foo(a,b)
    t = 0.99
    for i = 2:length(b)
        if any(x -> x > t, @view b[i-1:i])
        end
    end
end

a = rand(10)
b = rand( 9)

@btime foo($a, $b)

```

gives

```julia
410.315 ns (8 allocations: 384 bytes)

```

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [January 10, 2019, 3:39pm UTC](https://discourse.julialang.org/t/comparison-performance-with-any/19478/2 "2019-01-10T15:39:19Z")

</div>

Currently, creating an array view often allocates a small object ([Want non-allocating array views · Issue #14955 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/14955)). This is not an issue for operating on large chunks of an array, but it is significant for creating many tiny views. Eventually, there will probably be a compiler optimization that eliminates this allocation.

Of course, in your case, you don’t need `@view` or `any` at all. If the code you posted is representative of what you actually want to do, then just test `if b[i-1] > t || b[i] > t`.

---

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [January 10, 2019, 10:47pm UTC](https://discourse.julialang.org/t/comparison-performance-with-any/19478/3 "2019-01-10T22:47:11Z")

</div>

In order to eliminate the need for a view, you could also use a [generator expression](https://docs.julialang.org/en/v1/manual/arrays/#Generator-Expressions-1) such as this:

```julia
any(b[j] > t for j in i-1:i)

```

or this (which I personally find slightly less easy to read but is closer to your original example):

```julia
any(x->x>t, b[j] for j in i-1:i)

```

  

Here is your full example rewritten in this way:

```julia
using BenchmarkTools

function foo(a,b)
    t = 0.99
    for i = 2:length(b)
        if any(b[j] > t for j in i-1:i)
        end
    end
end

```

```julia
julia> a = rand(10);
julia> b = rand( 9);
julia> @btime foo($a, $b)
  28.349 ns (0 allocations: 0 bytes)

```

By comparison, your original example benchmarked like this on my machine:

```julia
julia> @btime foo($a, $b)
  95.541 ns (8 allocations: 384 bytes)

```

---

<div class="post-metadata">

**Author:** ![tkoolen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkoolen/32/1603_2.png) [@tkoolen](https://discourse.julialang.org/u/tkoolen)\
**Post date:** [January 10, 2019, 11:49pm UTC](https://discourse.julialang.org/t/comparison-performance-with-any/19478/4 "2019-01-10T23:49:04Z")

</div>

You could also use `uview` from [https://github.com/oschulz/UnsafeArrays.jl](https://github.com/oschulz/UnsafeArrays.jl) to get to zero allocation. It benchmarks about 2x faster on my machine (and a little slower than @ffevotte’s solution). By the way, I’m a little worried about this benchmark setup; ideally the compiler would just optimize this whole loop away.

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [January 11, 2019, 12:41am UTC](https://discourse.julialang.org/t/comparison-performance-with-any/19478/5 "2019-01-11T00:41:14Z")

</div>

> [@ffevotte](#):
>
> ```julia
> function foo(a,b)
> t = 0.99
> for i = 2:length(b)
> if any(b[j] > t for j in i-1:i)
> end
> end
> end
> 
> ```

Alternatively, if the length is always known at code-writing-time (eg, 2):

```julia
julia> function foo2(a,b)
           t = 0.99
           @inbounds for i = 2:length(b)
               if any(x -> x > t, (b[i-1], b[i]))
               end
           end
       end
foo2 (generic function with 1 method)

julia> @btime foo2($a, $b)
  10.270 ns (0 allocations: 0 bytes)

```

Unfortunately, to make it work at compile time, you’d need generated functions because of inference failure on `ntuple`:

```julia
julia> function foo4(a,b)
           t = 0.99
           @inbounds for i = 2:length(b)
               
               if any(x -> x > t, ntuple(j -> b[i+j-2], Val(2)))
               end
           end
       end
foo4 (generic function with 1 method)

julia> @btime foo4($a, $b)
  3.181 μs (56 allocations: 1.25 KiB)

```

But if we want to take that approach, the function is simple enough for the compiler to cheat:

```julia
julia> @generated function foo5(a,b,::Val{N} = Val(2)) where N  
           quote
               t = 0.99
               @inbounds for i = 2:length(b)
                   if any((Base.Cartesian.@ntuple $N j -> b[i+j-2] > t))
                   end
               end
           end
       end
foo4 (generic function with 2 methods)

julia> @btime foo5($a, $b)
  1.202 ns (0 allocations: 0 bytes)

julia> @btime foo4($a, $b)
  1.482 ns (0 allocations: 0 bytes)

julia> a = rand(10^6);

julia> b = rand( 10^6 - 1);

julia> @btime foo5($a, $b)
  1.482 ns (0 allocations: 0 bytes)

```

because now the compiler realizes the code isn’t actually doing anything.

---

<div class="post-metadata">

**Author:** ![MLackner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mlackner/32/2789_2.png) [@MLackner](https://discourse.julialang.org/u/MLackner)\
**Post date:** [January 11, 2019, 11:20am UTC](https://discourse.julialang.org/t/comparison-performance-with-any/19478/6 "2019-01-11T11:20:43Z")

</div>

Thanks to everyone for the great advice! It really helped a lot 🙂
