# Loop faster than \`reduce\`?

**URL:** <https://discourse.julialang.org/t/loop-faster-than-reduce/48927>\
**Category:** Performance\
**Tags:** loops\
**Created:** [October 24, 2020, 11:16am UTC](https://discourse.julialang.org/t/loop-faster-than-reduce/48927 "2020-10-24T11:16:12Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![stla](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stla/32/20382_2.png) [@stla](https://discourse.julialang.org/u/stla)\
**Post date:** [October 24, 2020, 11:16am UTC](https://discourse.julialang.org/t/loop-faster-than-reduce/48927/1 "2020-10-24T11:16:12Z")

</div>

Hello,

Is there a way to do better than such a loop:

```julia
for t in 2:n
     jarray = jack(t, jarray)
end

```

I tried `jarray = reduce((a, t) -> jack(t, a), 2:n; init = jarray)`, but this is slower than the loop.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [October 24, 2020, 12:10pm UTC](https://discourse.julialang.org/t/loop-faster-than-reduce/48927/2 "2020-10-24T12:10:18Z")

</div>

Please provide a MWE that includes all necessery code to run it. For example, what’s `jack`? What’s `jarray`?

---

<div class="post-metadata">

**Author:** ![stla](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stla/32/20382_2.png) [@stla](https://discourse.julialang.org/u/stla)\
**Post date:** [October 24, 2020, 1:04pm UTC](https://discourse.julialang.org/t/loop-faster-than-reduce/48927/3 "2020-10-24T13:04:26Z")

</div>

Hello,

The `jack` function is complex and not short. I’m afraid nobody will try to help me if I post it “as is”. I will try with a simple one to see if the behavior is the same. See you later.

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [October 24, 2020, 1:09pm UTC](https://discourse.julialang.org/t/loop-faster-than-reduce/48927/4 "2020-10-24T13:09:54Z")

</div>

I think it is a little strange that reduce is slower than the loop if `jack` is a complex function. If most of the processing was being done by `jack` calls any differences between `reduce` and the loop would be minimal.

---

<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:** [October 24, 2020, 4:32pm UTC](https://discourse.julialang.org/t/loop-faster-than-reduce/48927/5 "2020-10-24T16:32:06Z")

</div>

Let me first say that your operation looks to me more like a `foldr` than a plain `reduce` (unless there is some commutativity going on…)

As others said, both the `for` loop and the higher-order function should achieve the same kind of performance in such cases. See for example the following functions:

```julia
foo(x, y) = x=>y

function f1(n)
    res = 1
    for t in 2:n
        res = foo(t, res)
    end
    res
end

f2(n) = foldr(foo, n:-1:2, init=1)

```

which yield the same results:

```julia
julia> f1(5)
5 => (4 => (3 => (2 => 1)))

julia> f2(5)
5 => (4 => (3 => (2 => 1)))

```

and benchmark very similarly:

```julia
julia> using BenchmarkTools

julia> @benchmark f1(100)
BenchmarkTools.Trial: 
  memory estimate: 41.70 KiB
  allocs estimate: 99
  --------------
  minimum time: 15.080 μs (0.00% GC)
  median time: 16.603 μs (0.00% GC)
  mean time: 21.520 μs (5.91% GC)
  maximum time: 1.549 ms (97.01% GC)
  --------------
  samples: 10000
  evals/sample: 1

julia> @benchmark f2(100)
BenchmarkTools.Trial: 
  memory estimate: 41.70 KiB
  allocs estimate: 99
  --------------
  minimum time: 16.240 μs (0.00% GC)
  median time: 17.434 μs (0.00% GC)
  mean time: 21.865 μs (6.05% GC)
  maximum time: 1.780 ms (96.66% GC)
  --------------
  samples: 10000
  evals/sample: 1

julia> @benchmark f1(1000)
BenchmarkTools.Trial: 
  memory estimate: 3.90 MiB
  allocs estimate: 1488
  --------------
  minimum time: 1.195 ms (0.00% GC)
  median time: 1.297 ms (0.00% GC)
  mean time: 1.529 ms (12.72% GC)
  maximum time: 5.582 ms (57.30% GC)
  --------------
  samples: 3255
  evals/sample: 1

julia> @benchmark f2(1000)
BenchmarkTools.Trial: 
  memory estimate: 3.90 MiB
  allocs estimate: 1488
  --------------
  minimum time: 1.188 ms (0.00% GC)
  median time: 1.295 ms (0.00% GC)
  mean time: 1.554 ms (13.43% GC)
  maximum time: 5.287 ms (43.73% GC)
  --------------
  samples: 3206
  evals/sample: 1

```

(the same is true for even less costly operations, such as a plain floating-point sum, and should apply even more for more costly functions…)

---

<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:** [October 24, 2020, 5:07pm UTC](https://discourse.julialang.org/t/loop-faster-than-reduce/48927/6 "2020-10-24T17:07:03Z")

</div>

> [@stla](#):
>
> Is there a way to do better than such a loop:
> 
> ```julia
> for t in 2:n
> jarray = jack(t, jarray)
> end
> 
> ```

I guess this is related to the hypergeometric function you mentioned in a previous post?

You could provide a link to the repository, for those who are interested. But the best thing you could do is to try to compress the problem into a self-contained piece of code that captures the essential part of that function.

It also looks like you are passing in an array, and getting an updated version of that array out. That looks like it might have some performance issues. For example, are you updating the array in-place, or creating a new one for each iteration? How big is the array?

---

<div class="post-metadata">

**Author:** ![stla](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stla/32/20382_2.png) [@stla](https://discourse.julialang.org/u/stla)\
**Post date:** [October 31, 2020, 7:35pm UTC](https://discourse.julialang.org/t/loop-faster-than-reduce/48927/7 "2020-10-31T19:35:28Z")

</div>

Sorry there was only 10% difference actually. This could be normal fluctuations.

---

<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:** [October 31, 2020, 9:12pm UTC](https://discourse.julialang.org/t/loop-faster-than-reduce/48927/8 "2020-10-31T21:12:56Z")

</div>

I’m pretty sure you can get a significant speedup if you are willing to share a bit more about what you’re doing. I have a hunch, from looking at

```julia
for t in 2:n
     jarray = jack(t, jarray)
end

```

that it’s really inefficient.
