# @threads - control number of threads\`

**URL:** <https://discourse.julialang.org/t/threads-control-number-of-threads/128388>\
**Category:** New to Julia\
**Created:** [April 24, 2025, 10:26pm UTC](https://discourse.julialang.org/t/threads-control-number-of-threads/128388 "2025-04-24T22:26:05Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![freeman](https://avatars.discourse-cdn.com/v4/letter/f/ec9cab/32.png) [@freeman](https://discourse.julialang.org/u/freeman)\
**Post date:** [April 24, 2025, 10:26pm UTC](https://discourse.julialang.org/t/threads-control-number-of-threads/128388/1 "2025-04-24T22:26:05Z")

</div>

There’s another post with the same name [1], but I couldn’t get the answer I want out of it despite that it has something marked as “answer”

My situation is that I would like to have control over the number of threads used `Threads.@threads`. I have multiple `bigjob(arg)` that I want to run, they’re all independent of each other, they share no resources and I don’t care what order they’re ran in.

Elsewhere I have a function which contains

```julia
Threads.@threads for arg in args
    bigjob(arg)
end

```

How many threads are used here?

For my research I normally run julia from vscode with `julia -t 10` but I don’t necessarily want to use 10 threads every time I call `Threads.@threads` because I might have other stuff going on at any given time. I have some intuition, given how busy my computer is, how many concurrent `bigjobs` I can have.

Is there some syntax that allows me to have some control over this a call time? I imagine something like

```julia
Threads.@threads :njobs=4 for arg in args
    bigjob(arg)
end

```

or something? What do people do when they want to use fewer concurrent jobs than their julia was started with?

[1] [Control number of threads](https://discourse.julialang.org/t/control-number-of-threads/62887)

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [April 24, 2025, 10:40pm UTC](https://discourse.julialang.org/t/threads-control-number-of-threads/128388/2 "2025-04-24T22:40:10Z")

</div>

The `@threads` macro will spawn as many tasks as you have threads. If you use `@threads :static`, each thread processes one task. If you use `@threads :dynamic`, any available thread may process any of the tasks.

If you want to control the number of tasks more fine-grainedly, just use `Threads.@spawn` in your for-loop. That is, instead of:

```julia
Threads.@threads for i in lots_of_work
    bigjob(i)
end

```

You can do:

```julia
@sync for t in fewer_tasks
   Threads.@spawn bigjob(t)
end

```

---

<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:** [April 24, 2025, 10:53pm UTC](https://discourse.julialang.org/t/threads-control-number-of-threads/128388/3 "2025-04-24T22:53:08Z")

</div>

use OhMyThreads.jl

```julia
# Variant 2: macro API
function mc_parallel_macro(N; ntasks=nthreads())
    M = @tasks for i in 1:N
        @set begin
            reducer=+
            ntasks=ntasks
        end
        rand()^2 + rand()^2 < 1.0
    end
    pi = 4 * M / N
    return pi
end

```

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [April 24, 2025, 11:12pm UTC](https://discourse.julialang.org/t/threads-control-number-of-threads/128388/4 "2025-04-24T23:12:39Z")

</div>

ChunkSplitters.jl helps in the implementation of the above suggestions. The [example](https://juliafolds2.github.io/ChunkSplitters.jl/stable/multithreading/) in the page suggests exactly that use case.

---

<div class="post-metadata">

**Author:** ![freeman](https://avatars.discourse-cdn.com/v4/letter/f/ec9cab/32.png) [@freeman](https://discourse.julialang.org/u/freeman)\
**Post date:** [April 27, 2025, 1:57pm UTC](https://discourse.julialang.org/t/threads-control-number-of-threads/128388/5 "2025-04-27T13:57:12Z")

</div>

Correct me if I’m wrong, but @lmiq 's example the work is first chunks, and then sent to threads…? This isn’t great if the work is homogeneous in size (imigine you have some tasks that are 10x as long as others).

Doesn’t Julia have the pattern where you create N threads, have them on a loop consuming from a channel, then exist the treads built-in?

---

<div class="post-metadata">

**Author:** ![VinceNeede](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vinceneede/32/215744_2.png) [@VinceNeede](https://discourse.julialang.org/u/VinceNeede)\
**Post date:** [April 27, 2025, 3:04pm UTC](https://discourse.julialang.org/t/threads-control-number-of-threads/128388/6 "2025-04-27T15:04:58Z")

</div>

If they are all independent, then maybe Distributed is preferable [Distributed Computing · The Julia Language](https://docs.julialang.org/en/v1/stdlib/Distributed/#Distributed.pmap:)

```julia
@everywhere function bigjob(arg)
   ...
end
pmap(bigjob, args)

```

You can control the number of jobs by either initializing julia with `julia -p n_procs` or create your own `WorkerPool`

If you want to stick to threads, then you could use [`asyncmap`](https://docs.julialang.org/en/v1/base/parallel/#Base.asyncmap)  
As reported by the documentation, you can even pass a function to decide how many tasks you can run in parallel, so you can decide the load based on other factors

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [April 27, 2025, 4:14pm UTC](https://discourse.julialang.org/t/threads-control-number-of-threads/128388/7 "2025-04-27T16:14:23Z")

</div>

> [@freeman](#):
>
> Doesn’t Julia have the pattern where you create N threads, have them on a loop consuming from a channel

Starting with Julia 1.11 this is available by adding the `:greedy` switch to `@threads` as follows:

```julia
Threads.@threads :greedy for item in collection
    do_the_work(item)
end

```

However, this doesn’t let you set `N`; the number of tasks is always `Threads.threadpoolsize()`. See the documentation for details: [Multi-Threading · The Julia Language](https://docs.julialang.org/en/v1/base/multi-threading/#Base.Threads.@threads)

To control `N`, use `OhMyThreads.jl` instead. Here’s how:

```julia
using OhMyThreads

@tasks for item in collection
    @set begin
        scheduler=:greedy
        ntasks=N
    end
    do_the_work(item)
end

```

There’s also a macro-free form:

```julia
using OhMyThreads

tforeach(collection; scheduler=:greedy, ntasks=N) do item
    do_the_work(item)
end

```

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [April 27, 2025, 4:48pm UTC](https://discourse.julialang.org/t/threads-control-number-of-threads/128388/8 "2025-04-27T16:48:03Z")

</div>

You have channels ([Asynchronous Programming · The Julia Language](https://docs.julialang.org/en/v1/manual/asynchronous-programming/#Communicating-with-Channels)). You can with that deal with highly inhomogeneous tasks and control the number of processors used. I think (I might be wrong), though, that ˋOhMyThredsˋ can del with that automatically.

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [April 27, 2025, 5:00pm UTC](https://discourse.julialang.org/t/threads-control-number-of-threads/128388/9 "2025-04-27T17:00:08Z")

</div>

> [@lmiq](#):
>
> I think (I might be wrong), though, that ˋOhMyThredsˋ can del with that automatically.

Yes, that’s what the `:greedy` scheduler does, both for `Threads.@threads` and OhMyThreads.jl.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [April 27, 2025, 7:53pm UTC](https://discourse.julialang.org/t/threads-control-number-of-threads/128388/10 "2025-04-27T19:53:48Z")

</div>

> [@freeman](#):
>
> Doesn’t Julia have the pattern where you create N threads, have them on a loop consuming from a channel, then exist the treads built-in?

As mentioned, yes we do have that. With OhMyThreads and the `GreedyScheduler` you can also control the number of tasks as desired.

Keep in mind though, that this pattern of greedily fetching from a channel is in many cases pretty inefficient, and it’s often (but certainly not always!) best to just spawn more tasks and break up the work that way, unless you have an extremely extremely imbalanced workload. Julia’s scheduler has no problem with having more active tasks than threads.

You can also use the `:roundrobin` iteration order to shuffle up your data between the tasks which can also help with load balancing.

---

<div class="post-metadata">

**Author:** ![freeman](https://avatars.discourse-cdn.com/v4/letter/f/ec9cab/32.png) [@freeman](https://discourse.julialang.org/u/freeman)\
**Post date:** [April 27, 2025, 8:22pm UTC](https://discourse.julialang.org/t/threads-control-number-of-threads/128388/11 "2025-04-27T20:22:49Z")

</div>

> [@danielwe](#):
>
> `OhMyThreads`

Ok I think this is the syntax I like the most. I wish we could write something like

```julia
Threads.@threads :greedy N=3 for item in collection
...

```

On second reading I see that @jling had already mentioned this syntax, but whenever I see the word “reducer” my eyes just glaze over 😅

Thanks everyone.

---

<div class="post-metadata">

**Author:** ![sumiya11](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sumiya11/32/207147_2.png) [@sumiya11](https://discourse.julialang.org/u/sumiya11)\
**Post date:** [May 5, 2025, 3:18pm UTC](https://discourse.julialang.org/t/threads-control-number-of-threads/128388/12 "2025-05-05T15:18:06Z")

</div>

I sometimes do

```julia
njobs = 4
Threads.@threads for t in 1:njobs 
    # bigjob(...)
end

```

but then the call bigjob(…) needs to be adapted a bit.
