# Strange summation timings

**URL:** https://discourse.julialang.org/t/strange-summation-timings/13638
**Category:** General Usage
**Created:** [August 17, 2018, 7:56pm UTC](https://discourse.julialang.org/t/strange-summation-timings/13638 "2018-08-17T19:56:56Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![NiclasMattsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/niclasmattsson/32/21988_2.png) [@NiclasMattsson](https://discourse.julialang.org/u/NiclasMattsson)
#### Post date: [August 17, 2018, 7:56pm UTC](https://discourse.julialang.org/t/strange-summation-timings/13638/1 "2018-08-17T19:56:57Z")

</div>

I wanted to test different ways of writing a simple summation, here’s the code:

```julia
# series with slow convergence to pi
function pisumloop(n)
    s = 0.0
    for k = 1:n
        s += 1 / k^2
    end
    return sqrt(6*s)
end

# vectorization + broadcasting
pisumvec(n) = sqrt(6*sum(1 ./ (1:n).^2))

# array comprehension
pisumcomp(n) = sqrt(6*sum([1/k^2 for k=1:n]))

# generator expression
pisumgen(n) = sqrt(6*sum(1/k^2 for k=1:n))

```

As you can see from the following benchmark results on Julia 0.6.4, `pisumvec` and `pisumcomp` are a bit slower, presumably because they allocate temporary arrays. This is pretty much what I expected, although I thought the difference would be a bit larger.

```julia
julia> using BenchmarkTools

julia> @btime pisumloop(10^4);
  37.752 μs (0 allocations: 0 bytes)

julia> @btime pisumvec(10^4);
  40.094 μs (2 allocations: 78.20 KiB)

julia> @btime pisumcomp(10^4);
  40.094 μs (2 allocations: 78.20 KiB)

julia> @btime pisumgen(10^4);
  37.752 μs (4 allocations: 96 bytes)

```

But here’s what I get on Julia 1.0:

```julia
julia> @btime pisumloop(10^4);
  37.752 μs (0 allocations: 0 bytes)

julia> @btime pisumvec(10^4);
  20.778 μs (3 allocations: 78.23 KiB)

julia> @btime pisumcomp(10^4);
  20.778 μs (2 allocations: 78.20 KiB)

julia> @btime pisumgen(10^4);
  37.752 μs (0 allocations: 0 bytes)

```

What’s going on here? How did `pisumvec` and `pisumcomp` become twice as fast in 1.0? And how can they stomp all over `pisumloop` and `pisumgen`, which (I thought) should be better?

Another weird thing. All the timings above were done on an old Core i7-4770K, a 4 core machine running at 3.5 GHz. When I tried the same code on an i7-8700K (6 cores at 3.7 GHz, or a single core at 4.7 GHz), all benchmarks finished in only **7-8 μs**. Why is there such a huge difference between these machines? From the difference in single core clock speeds I expected the newer machine to be only 25% faster.

---

<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: [August 17, 2018, 8:54pm UTC](https://discourse.julialang.org/t/strange-summation-timings/13638/2 "2018-08-17T20:54:47Z")

</div>

> [@NiclasMattsson](#):
>
> And how can they stomp all over `pisumloop`

Change `for` to `@simd for` to turn on SIMD optimization for that loop.

> [@NiclasMattsson](#):
>
> From the difference in single core clock speeds I expected the newer machine to be only 25% faster.

Clock speeds have been the least important thing about the CPU for decades now.

---

<div class="post-metadata">

### Author: ![Seif\_Shebl](https://avatars.discourse-cdn.com/v4/letter/s/eada6e/32.png) [@Seif\_Shebl](https://discourse.julialang.org/u/Seif_Shebl)
#### Post date: [August 17, 2018, 9:37pm UTC](https://discourse.julialang.org/t/strange-summation-timings/13638/3 "2018-08-17T21:37:12Z")

</div>

Turn on optimization options `-O3 --math-mode=fast` for the automatic SIMD vectorization to kick in, then the results should be like this:

```julia
julia> @btime pisumloop(10^4);
  17.448 μs (0 allocations: 0 bytes)

julia> @btime pisumvec(10^4);
  19.501 μs (3 allocations: 78.23 KiB)

julia> @btime pisumcomp(10^4);
  19.244 μs (2 allocations: 78.20 KiB)

julia> @btime pisumgen(10^4);
  17.448 μs (0 allocations: 0 bytes)

```

---

<div class="post-metadata">

### Author: ![NiclasMattsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/niclasmattsson/32/21988_2.png) [@NiclasMattsson](https://discourse.julialang.org/u/NiclasMattsson)
#### Post date: [August 17, 2018, 9:50pm UTC](https://discourse.julialang.org/t/strange-summation-timings/13638/4 "2018-08-17T21:50:32Z")

</div>

> [@stevengj](#):
>
> Clock speeds have been the least important thing about the CPU for decades now.

Not for pure single core floating point benchmarks, which my code examples should be. For example, my old machine completes a 2M Superpi 1.5 benchmark in 22.2 seconds and the new one in 16.9 seconds, which is very close to the 25% speedup I expected from raw clock speeds - despite the 5 years and several processor generations between these chips.

But thanks for the SIMD suggestions, I’ll try them out. I still find the (untweaked) difference between array comprehensions and generator expressions unintuitive though. They seem so similar to me.
