# Speed up for-loop with multithreading

**URL:** <https://discourse.julialang.org/t/speed-up-for-loop-with-multithreading/79823>\
**Category:** Performance\
**Tags:** question, multithreading\
**Created:** [April 22, 2022, 9:11am UTC](https://discourse.julialang.org/t/speed-up-for-loop-with-multithreading/79823 "2022-04-22T09:11:46Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Himbeersternchen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/himbeersternchen/32/19078_2.png) [@Himbeersternchen](https://discourse.julialang.org/u/Himbeersternchen)\
**Post date:** [April 22, 2022, 9:11am UTC](https://discourse.julialang.org/t/speed-up-for-loop-with-multithreading/79823/1 "2022-04-22T09:11:47Z")

</div>

Hi Guys,

I’m trying to speed up my for-loop with multithreading like following (test3.jl code):

```julia
time0 = @elapsed begin
    n = 250
    a1 = Array{Array{Float64, 1}, 1}(undef, n)
    Threads.@threads for i in 1:n 
        a1[i] = [i+0.12345, 0]
        # push!(a1, [i+0.12345, 0])
    end
end

# without multithreading
time = @elapsed try
    a2 = Array{Array{Float64, 1}, 1}()
    for row in a1 
    tmp = [round(x * 0.00001, digits=5) for x in row]
    push!(a2, tmp)
end
catch
end

# with multithreading
time2 = @elapsed try
    a3 = Array{Array{Float64, 1}, 1}(undef, n)
    Threads.@threads for i in 1:n 
    tmp = [round(x * 0.00001, digits=5) for x in a1[i]]
    a3[i] = tmp
end
catch
end

println("time0=$time0, time=$time, time2=$time2")

```

and i run:

```julia
julia> include("test/test3.jl")
time0=0.072520981, time=0.020055303, time2=0.070619797

```

I have set Number of Threads = 4

I know, time2 \> time because of overhead, which means, starting 4 Threads costs more time than directly running it without parallelism. But i still want to ask, is there any chance to speed up this for-loop? Maybe i should write more efficient codes? But how to do it?

Best Regards

---

<div class="post-metadata">

**Author:** ![goerch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerch/32/29122_2.png) [@goerch](https://discourse.julialang.org/u/goerch)\
**Post date:** [April 22, 2022, 9:18am UTC](https://discourse.julialang.org/t/speed-up-for-loop-with-multithreading/79823/2 "2022-04-22T09:18:37Z")

</div>

Hi, it would be nice if you could edit your post to markdown the code in triple back ticks. That way it would be easier for us to copy and paste it. Thanks!

---

<div class="post-metadata">

**Author:** ![Himbeersternchen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/himbeersternchen/32/19078_2.png) [@Himbeersternchen](https://discourse.julialang.org/u/Himbeersternchen)\
**Post date:** [April 22, 2022, 9:27am UTC](https://discourse.julialang.org/t/speed-up-for-loop-with-multithreading/79823/3 "2022-04-22T09:27:42Z")

</div>

Thanks for your hint! I’ve done it!

---

<div class="post-metadata">

**Author:** ![goerch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerch/32/29122_2.png) [@goerch](https://discourse.julialang.org/u/goerch)\
**Post date:** [April 22, 2022, 9:51am UTC](https://discourse.julialang.org/t/speed-up-for-loop-with-multithreading/79823/4 "2022-04-22T09:51:57Z")

</div>

> [@Himbeersternchen](#):
>
> I know, time2 \> time because of overhead, which means, starting 4 Threads costs more time than directly running it without parallelism.

Correct, here is what I see using `@btime`:

```julia
  27.400 μs (1023 allocations: 43.67 KiB)
  5.283 μs (2 allocations: 64 bytes)
  5.267 μs (1 allocation: 16 bytes)

```

> [@Himbeersternchen](#):
>
> But i still want to ask, is there any chance to speed up this for-loop? Maybe i should write more efficient codes?

If you need more speed, this MWE doesn’t seem to be representative for your real problem? I can’t estimate if your problem size is bigger or if this represents a hot loop, which is executed a lot of times?

---

<div class="post-metadata">

**Author:** ![Himbeersternchen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/himbeersternchen/32/19078_2.png) [@Himbeersternchen](https://discourse.julialang.org/u/Himbeersternchen)\
**Post date:** [April 22, 2022, 10:19am UTC](https://discourse.julialang.org/t/speed-up-for-loop-with-multithreading/79823/5 "2022-04-22T10:19:53Z")

</div>

Thanks for your answer! This is only a part of the function (f1). In f1 exists only one loop with 250 iterations. I want to speed up f1 with speeding up this loop with multithreading. But it seems not to work.  
The whole Program is very big, and there are many different functions. My final goal is to speed up the whole program. And speeding up f1 is only my first trying step. Maybe i should move on and try to speed up other functions.

---

<div class="post-metadata">

**Author:** ![goerch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerch/32/29122_2.png) [@goerch](https://discourse.julialang.org/u/goerch)\
**Post date:** [April 22, 2022, 10:22am UTC](https://discourse.julialang.org/t/speed-up-for-loop-with-multithreading/79823/6 "2022-04-22T10:22:54Z")

</div>

> [@Himbeersternchen](#):
>
> I want to speed up f1 with speeding up this loop with multithreading. But it seems not to work.  
> The whole Program is very big, and there are many different functions. My final goal is to speed up the whole program.

That is what I suspected. Did you try to [profile](https://docs.julialang.org/en/v1/manual/profile/) your program? I’d recommend to use a visual profiler in VSCode or Atom/Juno(which I still slightly prefer).

Edit: another idea. If your MWE is representative for your problem, allocations could be part of the problem. I’d see some room for improvement there.

---

<div class="post-metadata">

**Author:** ![Himbeersternchen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/himbeersternchen/32/19078_2.png) [@Himbeersternchen](https://discourse.julialang.org/u/Himbeersternchen)\
**Post date:** [April 22, 2022, 10:44am UTC](https://discourse.julialang.org/t/speed-up-for-loop-with-multithreading/79823/7 "2022-04-22T10:44:42Z")

</div>

I don’t know about profile yet. I 'll read the docu :).

---

<div class="post-metadata">

**Author:** ![goerch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerch/32/29122_2.png) [@goerch](https://discourse.julialang.org/u/goerch)\
**Post date:** [April 22, 2022, 11:25am UTC](https://discourse.julialang.org/t/speed-up-for-loop-with-multithreading/79823/8 "2022-04-22T11:25:12Z")

</div>

> [@goerch](#):
>
> Correct, here is what I see using `@btime` :
> 
> ```julia
> 27.400 μs (1023 allocations: 43.67 KiB)
> 5.283 μs (2 allocations: 64 bytes)
> 5.267 μs (1 allocation: 16 bytes)
> 
> ```

But the original benchmark is problematic: the `try`-`catch` blocks mask that `a1` is not defined. Corrected benchmark

```julia
using BenchmarkTools 

init() = begin
    n = 250
    a1 = Vector{Vector{Float64}}(undef, n)
    for i in 1:n 
        a1[i] = [rand(), rand()]
    end
    a1
end

# without multithreading
round_serial(a1) = begin
    n = length(a1)
    a2 = Vector{Vector{Float64}}(undef, n)
    for i in 1:n 
        a2[i] = [round(x, digits=5) for x in a1[i]]
    end
    a2
end

# with multithreading
round_parallel(a1) = begin
    n = length(a1)
    a3 = Vector{Vector{Float64}}(undef, n)
    Threads.@threads for i in 1:n 
        a3[i] = [round(x, digits=5) for x in a1[i]]
    end
    a3
end

a1 = init()
a2 = @btime round_serial($a1)
a3 = @btime round_parallel($a1)
@assert isapprox(a3, a2)

```

shows some speedup for me

```julia
  29.100 μs (251 allocations: 21.59 KiB)
  10.500 μs (270 allocations: 24.00 KiB)

```

---

<div class="post-metadata">

**Author:** ![Himbeersternchen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/himbeersternchen/32/19078_2.png) [@Himbeersternchen](https://discourse.julialang.org/u/Himbeersternchen)\
**Post date:** [April 22, 2022, 12:51pm UTC](https://discourse.julialang.org/t/speed-up-for-loop-with-multithreading/79823/9 "2022-04-22T12:51:47Z")

</div>

Ok. Thanks for your check! I until there i still used @elapsed, because i need the returned time variable and the total run time is relevant for me.  
I have read docu about profile. But i really don’t understand good, how can i understand the output of

```julia
ProfileView.@profview

```

Code for visualizing profile:

```julia
using ProfileView

time0 = @elapsed begin
    n = 250
    a1 = Array{Array{Float64, 1}, 1}(undef, n)
    Threads.@threads for i in 1:n 
        a1[i] = [i+0.12345, 0]
        # push!(a1, [i+0.12345, 0])
    end
end

# without multithreading
time1 = @elapsed @profview begin
    a2 = Array{Array{Float64, 1}, 1}()
    for row in a1 
        tmp = [round(x * 0.00001, digits=5) for x in row]
        push!(a2, tmp)
    end
end

# with multithreading
time2 = @elapsed @profview begin
    
    a3 = Array{Array{Float64, 1}, 1}(undef, n)
    Threads.@threads for i in 1:n 
        tmp = [round(x * 0.00001, digits=5) for x in a1[i]]
        a3[i] = tmp
    end

end

println("time0=$time0, time1=$time1, time2=$time2")

```

 ![without_multithreading](https://global.discourse-cdn.com/julialang/original/3X/a/e/aeb1f9ffa705dec99f730407bbc5e2c91b950302.png)

 ![with_multithreading](https://global.discourse-cdn.com/julialang/original/3X/0/8/08712ab13b8818d3134c0a3ffda5e64201e2c68a.png)

There’s not something in this picture that I’m familiar with. What is the crucial info of those plots i should extract?

---

<div class="post-metadata">

**Author:** ![goerch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerch/32/29122_2.png) [@goerch](https://discourse.julialang.org/u/goerch)\
**Post date:** [April 22, 2022, 1:24pm UTC](https://discourse.julialang.org/t/speed-up-for-loop-with-multithreading/79823/10 "2022-04-22T13:24:37Z")

</div>

Using

```julia
using Profile
Profile.clear()
a1 = init()
round_serial(a1)
@profile for i in 1:1000; round_serial(a1); end
Juno.profiler()

```

for my example I see in Juno/Atom something like this

 ![image](https://global.discourse-cdn.com/julialang/original/3X/a/f/afa7cad096d18598b2008badeae8a940c8eeb9e8.png)

where you can navigate from the profile pane to the source code. In the source code pane bigger bars mean larger part of the runtime. Read color indicates part of the program which allocate, yellow color indicates dynamic dispatch.

---

<div class="post-metadata">

**Author:** ![Himbeersternchen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/himbeersternchen/32/19078_2.png) [@Himbeersternchen](https://discourse.julialang.org/u/Himbeersternchen)\
**Post date:** [April 22, 2022, 1:32pm UTC](https://discourse.julialang.org/t/speed-up-for-loop-with-multithreading/79823/11 "2022-04-22T13:32:50Z")

</div>

Cool for you 😛

> [@goerch](#):
>
> `Juno.profiler()`

I m using IDE VSCode, Juno is not set up and installed by me. Hmm Maybe i should start a new topic in discourse?
