# I cannot get close to full speed up in parallel

**URL:** https://discourse.julialang.org/t/i-cannot-get-close-to-full-speed-up-in-parallel/53751
**Category:** Performance
**Tags:** parallel
**Created:** [January 21, 2021, 11:34pm UTC](https://discourse.julialang.org/t/i-cannot-get-close-to-full-speed-up-in-parallel/53751 "2021-01-21T23:34:24Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![Noel\_Araujo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/noel_araujo/32/4862_2.png) [@Noel\_Araujo](https://discourse.julialang.org/u/Noel_Araujo)
#### Post date: [January 21, 2021, 11:34pm UTC](https://discourse.julialang.org/t/i-cannot-get-close-to-full-speed-up-in-parallel/53751/1 "2021-01-21T23:34:24Z")

</div>

I have a code that is embarrassingly parallel, but I cannot get full its speed up.  
The dummy code is here:

```julia
function points_on_sphere_surface(num_pts=100, R=2) 
    indices = 1:num_pts .+ 0.5

    ϕ = acos.(1 .- 2*indices/num_pts)
    θ = π*(1 + sqrt(5)).*indices

    x, y, z = R.*cos.(θ).*sin.(ϕ), R.*sin.(θ).*sin.(ϕ), R.*cos.(ϕ)
    return [x y z]
end

function original_foo(sphere, r, β)
    N = length(β)
    nx = sphere[1]
    ny = sphere[2]
    nz = sphere[3]
    intensity = zeros(N, N)
    for n=1:N
         for m=1:N 
            rx = r[1,n] - r[1, m]
            ry = r[2,n] - r[2, m]
            rz = r[3,n] - r[3, m]
    
            dot_n_r = nx*rx + ny*ry + nz*rz
            intensity[n,m] = real(conj(β[n])*β[m]*exp(im*dot_n_r)) # I need to define a matrix 
        end
    end
    return sum(intensity)
end

N = 500
r = rand(3, N)
β = rand(ComplexF64, N)
sphere = points_on_sphere_surface(200, 10)

time_sequencial = @elapsed begin
    x = zeros(200)
    for i = 1:200
        point_in_sphere = sphere[i,:]
        x[i] = original_foo(point_in_sphere, r, β)
    end
end

time_parallel = @elapsed begin
    x = []
    for i = 1:200
        point_in_sphere = sphere[i,:]
        push!(x, Threads.@spawn original_foo(point_in_sphere, r, β))
    end
    y = fetch.(x);
end

speedup = time_sequencial/time_parallel

```

My notebook has 4cores/8threads. and I initiate Julia with 8 threads.  
However, my best case scenario I have around 4 times speed up.

Is there any limitation in my code that sets this upper boundary ?

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [January 22, 2021, 12:47am UTC](https://discourse.julialang.org/t/i-cannot-get-close-to-full-speed-up-in-parallel/53751/2 "2021-01-22T00:47:41Z")

</div>

The main problem here is that with 4 cores, 4x speedup is all you should expect.

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [January 22, 2021, 2:11am UTC](https://discourse.julialang.org/t/i-cannot-get-close-to-full-speed-up-in-parallel/53751/4 "2021-01-22T02:11:59Z")

</div>

So what’s happening here is that `sleep` suspends the thread if you are `@spawn`ing things, so when you have the version with `sleep`, the only thing that is happening that’s more “parallel” is that when 1 thread is sleeping, another is running the computation. The way computers have more threads than cores is a technique called hyper-threading (with AMD processors it’s called SMT). What this does is allows 1 core to operate 2 programs at once, but it doesn’t actually add extra capability per core. That means that if your program is making full use of the CPU, hyperthreading provides essentially no speedup in most cases.

---

<div class="post-metadata">

### Author: ![Noel\_Araujo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/noel_araujo/32/4862_2.png) [@Noel\_Araujo](https://discourse.julialang.org/u/Noel_Araujo)
#### Post date: [January 22, 2021, 2:49am UTC](https://discourse.julialang.org/t/i-cannot-get-close-to-full-speed-up-in-parallel/53751/5 "2021-01-22T02:49:38Z")

</div>

Indeed, the` sleep` function led me to misleading conclusiosn. I just had to change `sleep(0.4)` for `inv(rand(1800,1800))` to see that the real speed up was around 2 times.

---

<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 22, 2021, 3:37am UTC](https://discourse.julialang.org/t/i-cannot-get-close-to-full-speed-up-in-parallel/53751/6 "2021-01-22T03:37:29Z")

</div>

> [@Noel\_Araujo](#):
>
> ```julia
> intensity = zeros(N, N)
> ...
> return sum(intensity)
> 
> ```

Note that you are allocating an array just to sum it. Much better to simply accumulate the sum directly and never allocate the array. (If in your real application you need the `intensity` matrix, note that your `for n=1:N; for m=1:N` loops are [in the wrong order](https://docs.julialang.org/en/v1/manual/performance-tips/#man-performance-column-major) for spatial locality.)

(The code would probably be somewhat cleaner, and at least as fast, if you used [StaticArrays.jl](https://github.com/JuliaArrays/StaticArrays.jl) for storing and computing with 3-component coordinate vectors — this is what StaticArrays are perfect for.)

PS. There is a function `cis(φ)` that more efficiently computes `exp(im*φ)`.
