# How to enforce spawned tasks to be run on different threads?

**URL:** https://discourse.julialang.org/t/how-to-enforce-spawned-tasks-to-be-run-on-different-threads/67496
**Category:** General Usage
**Created:** [September 1, 2021, 11:58am UTC](https://discourse.julialang.org/t/how-to-enforce-spawned-tasks-to-be-run-on-different-threads/67496 "2021-09-01T11:58:46Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![erwanlecarpentier](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/erwanlecarpentier/32/23448_2.png) [@erwanlecarpentier](https://discourse.julialang.org/u/erwanlecarpentier)
#### Post date: [September 1, 2021, 11:58am UTC](https://discourse.julialang.org/t/how-to-enforce-spawned-tasks-to-be-run-on-different-threads/67496/1 "2021-09-01T11:58:46Z")

</div>

Hey!  
I would like to run a job several times in parallel (as many times as the number of available threads), and I would like to do this several times in a row. MWE:

```julia
function mytask() # The task to be parallelized
    println(Threads.threadid())
    x = 1.0
    for _ in 1:1e9
        x += rand()
    end
end

for i in 1:2 # Say we do two iterations
    println("Iteration $i")
    @sync for _ in 1:Threads.nthreads()
        Threads.@spawn begin
            mytask()
        end
    end
end

```

Unfortunately, when I do this, say with 4 threads, the first iteration is perfectly parallelized and starting from the second iteration one thread will run the task several times **sequentially** , yielding the following output:

```julia
Iteration 1
1
3
2
4
Iteration 2
1
3
1
1

```

Thus, iteration 2 takes three times as much time as iteration 1 to be completed. If I draw a sketch of the execution of threads vs time, this can be seen as the following (colored cell means thread is running):

 ![wrong](https://global.discourse-cdn.com/julialang/original/3X/6/4/6436b63315cfe229916061dc718c529a1c32fe2d.png)

How can I enforce the task to be run in different threads in parallel for the 2nd iteration (and the next ones)?

Thanks for reading!

---

<div class="post-metadata">

### Author: ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)
#### Post date: [September 1, 2021, 12:02pm UTC](https://discourse.julialang.org/t/how-to-enforce-spawned-tasks-to-be-run-on-different-threads/67496/2 "2021-09-01T12:02:38Z")

</div>

> [@erwanlecarpentier](#):
>
> `@sync for _ in 1:Threads.nthreads()`

what is this for? I get you want two iterations but is your real task number depend on number of threads? are you studying something related to threading?

btw it just does whatever scheduler thinks is the best:

```julia
julia> for i in 1:2 # Say we do two iterations
           println("Iteration $i")
           @sync for _ in 1:Threads.nthreads()
               Threads.@spawn begin
                   mytask()
               end
           end
       end
Iteration 1
1
4
3
2
Iteration 2
1
4
2
3

```

unless you’re seeing specific issues with this (e.g. if you have thread-local cache), I’d say this is fine

---

<div class="post-metadata">

### Author: ![erwanlecarpentier](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/erwanlecarpentier/32/23448_2.png) [@erwanlecarpentier](https://discourse.julialang.org/u/erwanlecarpentier)
#### Post date: [September 1, 2021, 12:11pm UTC](https://discourse.julialang.org/t/how-to-enforce-spawned-tasks-to-be-run-on-different-threads/67496/3 "2021-09-01T12:11:17Z")

</div>

> [@jling](#):
>
> what is this for? I get you want two iterations but is your real task number depend on number of threads? are you studying something related to threading?

My real task number does not depend on the number of threads. I am working on Machine Learning and the task is actually some kind of Monte Carlo simulation. In my real application I should run 25 tasks in parallel and I have up to 36 available threads on a remote machine.

Notice that the parallelized tasks are embarrassingly parallel computing: they **do not share any memory / data**.

> [@jling](#):
>
> btw it just does whatever scheduler thinks is the best

You mean that there is some kind of optimization behind? Any idea how to be 100% sure to reproduce the same “perfect parallelization” of iteration 1 in iteration 2?

---

<div class="post-metadata">

### Author: ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)
#### Post date: [September 1, 2021, 12:17pm UTC](https://discourse.julialang.org/t/how-to-enforce-spawned-tasks-to-be-run-on-different-threads/67496/4 "2021-09-01T12:17:19Z")

</div>

if your real task is slow enough such that by the time next `@spawn` starts non of the previous threads have finished, it should already be doing that.

Basically, if by the time you’re spawning your 24th task, the 1st thread is available again, why don’t you want the 1st thread to work?

> [@erwanlecarpentier](#):
>
> 100% sure to reproduce the same “perfect parallelization”

```julia
ThreadPools.tmap
#or
ThreadPools.tforeach

```

maybe

---

<div class="post-metadata">

### Author: ![erwanlecarpentier](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/erwanlecarpentier/32/23448_2.png) [@erwanlecarpentier](https://discourse.julialang.org/u/erwanlecarpentier)
#### Post date: [September 1, 2021, 1:48pm UTC](https://discourse.julialang.org/t/how-to-enforce-spawned-tasks-to-be-run-on-different-threads/67496/5 "2021-09-01T13:48:22Z")

</div>

I could not achieve full parallelism with `ThreadPools.tmap` or `ThreadPools.tforeach`, though I succeeded using `Threads.@threads for` (see below).

```julia
for i in 1:2 # Say we do two iterations
    println("Iteration $i")
    Threads.@threads for _ in 1:4
        mytask()
    end
end

```

However, this forces the user to have a single outer `for` loop encompassing the multithreaded code. Less convenient than `@spawn` IMO. This would be a problem with nested multithreaded `for` loops for instance. I’d be interested in achieving fully parallelized code using something like `@spawn`. I remember being able to do that with [apply\_async](https://docs.python.org/3/library/multiprocessing.html#multiprocessing.pool.Pool.apply_async) in python, by creating a pool of jobs wherever I wanted in nested for loops and “getting” them afterwards (executing the threads and fetching the results).

> [@jling](#):
>
> Basically, if by the time you’re spawning your 24th task, the 1st thread is available again, why don’t you want the 1st thread to work?

Yes I would like this! However my tasks are pretty long and of similar length. I’d be happy just to be able to run the 25 threads in parallel.
