# Conditional Multithreading

**URL:** <https://discourse.julialang.org/t/conditional-multithreading/32421>\
**Category:** General Usage\
**Tags:** multithreading\
**Created:** [December 18, 2019, 2:55am UTC](https://discourse.julialang.org/t/conditional-multithreading/32421 "2019-12-18T02:55:14Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![bjack205](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bjack205/32/7294_2.png) [@bjack205](https://discourse.julialang.org/u/bjack205)\
**Post date:** [December 18, 2019, 2:55am UTC](https://discourse.julialang.org/t/conditional-multithreading/32421/1 "2019-12-18T02:55:15Z")

</div>

Is there a way to enable/disable calls to Threads.@threads?

I’m developing an optimization solver, and when the problem is sufficiently small, using multi-threading hurts performance, and incurs allocations (my code doesn’t make any allocations until I wrap it in @threads). However, when the problem size grows and the individual operations being threaded become more computationally intensive (booting the arithmetic intensity) I get some good performance increases.

I’d like to be able to enable/disable multi-threading as a user-specified option. I can’t just restart Julia with JULIA\_NUM\_THREADS=1, since @threads still allocates memory and is slower than had I left it out. Can I do this using metaprogramming?

I know I can obviously just create duplicates of my functions and wrap some with @threads, but I’d rather avoid this if possible.

FYI: nearly all of my functions are trivially parallelizable, like this

```julia
function foo(vals, vars)
    for k in eachindex(vals)
        vals[k] = somefunction(vars[k])
    end
end

```

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [December 18, 2019, 3:03am UTC](https://discourse.julialang.org/t/conditional-multithreading/32421/2 "2019-12-18T03:03:05Z")

</div>

There was a PR to remove the overhead of threads when a single thread is used, but it was closed  
[https://github.com/JuliaLang/julia/pull/32181](https://github.com/JuliaLang/julia/pull/32181)  
see also  
[https://github.com/JuliaLang/julia/pull/33964](https://github.com/JuliaLang/julia/pull/33964)

---

<div class="post-metadata">

**Author:** ![bjack205](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bjack205/32/7294_2.png) [@bjack205](https://discourse.julialang.org/u/bjack205)\
**Post date:** [December 18, 2019, 10:25pm UTC](https://discourse.julialang.org/t/conditional-multithreading/32421/3 "2019-12-18T22:25:53Z")

</div>

Awesome, thanks for linking those.

So, to be clear, is there not an easy way to do this at run-time?

For example, I can do this:

```julia
function run_kernel(vals,A,b,parallel=true)
    if parallel
        Threads.@threads for k in eachindex(vals)
            vals[k] = mykernel(A,b)
        end
    else
        for k in eachindex(vals)
            vals[k] = mykernel(A,b)
        end   
    end
end

```

Is there not a way to do this without copying the code like that?

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [December 19, 2019, 12:03am UTC](https://discourse.julialang.org/t/conditional-multithreading/32421/4 "2019-12-19T00:03:23Z")

</div>

> [@bjack205](#):
>
> when the problem is sufficiently small, using multi-threading hurts performance

This sounds like it’d be better to dispatch on the problem size than `nthreads() == 1`. If that’s the case, it’s better to use threaded map that supports specifying base case size. It’s kind of a plug, but [Transducers.jl has it](https://tkf.github.io/Transducers.jl/dev/manual/#Base.reduce). It would be something like:

```julia
xf = Map() do k
    vals[k] = mykernel(A, vars[k])
    nothing
end

foldl(right, xf, eachindex(vals)) # sequential
reduce(right, xf, eachindex(vals)) # parallel
reduce(right, xf, eachindex(vals), basesize=10) # parallelize if length(vals) > 10

```

(I used side-effect in `Map` which is a bit nasty. It’d be better to use `collect` and `tcollect` but they allocates.)

---

<div class="post-metadata">

**Author:** ![oschulz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oschulz/32/2998_2.png) [@oschulz](https://discourse.julialang.org/u/oschulz)\
**Post date:** [December 19, 2019, 12:25pm UTC](https://discourse.julialang.org/t/conditional-multithreading/32421/5 "2019-12-19T12:25:08Z")

</div>

> Is there not a way to do this without copying the code like that?

I have an `@onthreads` macro in [ParallelProcessingTools.j](https://oschulz.github.io/ParallelProcessingTools.j) that does this for you. It also pins the tasks to threads though, legacy from pre-partr times (I’ll change that in the future, or make it more flexible at least). One of the motivations for `@onthreads` was easy testing of thread-scaling of code.

---

<div class="post-metadata">

**Author:** ![Ahmed\_Salih](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ahmed_salih/32/206579_2.png) [@Ahmed\_Salih](https://discourse.julialang.org/u/Ahmed_Salih)\
**Post date:** [March 6, 2024, 7:42am UTC](https://discourse.julialang.org/t/conditional-multithreading/32421/6 "2024-03-06T07:42:42Z")

</div>

Is there no easy way to do this now?

Perhaps having a tag parsing into `@threads enable/disable` ?

Kind regards

---

<div class="post-metadata">

**Author:** ![scheidan1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scheidan1/32/24771_2.png) [@scheidan1](https://discourse.julialang.org/u/scheidan1)\
**Post date:** [March 6, 2024, 8:19am UTC](https://discourse.julialang.org/t/conditional-multithreading/32421/7 "2024-03-06T08:19:20Z")

</div>

I you could use FLoops.jl and swap between the sequential and parallel executor, see [here](https://juliafolds.github.io/FLoops.jl/stable/tutorials/parallel/#tutorials-executor).

---

<div class="post-metadata">

**Author:** ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)\
**Post date:** [March 6, 2024, 8:30am UTC](https://discourse.julialang.org/t/conditional-multithreading/32421/8 "2024-03-06T08:30:54Z")

</div>

The basic `Threads.@threads` is too simple for that. However if you are a bit more serious about multi-threading, you likely use something anyways.  
If you do the chunking yourself (e.g. via ChunkSplitters.jl or OhMyThreads.jl) you can just use a single chunk to effectively disable multi-threading.

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [March 6, 2024, 9:17am UTC](https://discourse.julialang.org/t/conditional-multithreading/32421/9 "2024-03-06T09:17:59Z")

</div>

Beyond using a single chunk, we’ll try to add dedicated support for this to OhMyThreads.jl ([issue](https://github.com/JuliaFolds2/OhMyThreads.jl/issues/69)).

---

<div class="post-metadata">

**Author:** ![MilesCranmer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milescranmer/32/21070_2.png) [@MilesCranmer](https://discourse.julialang.org/u/MilesCranmer)\
**Post date:** [March 6, 2024, 9:29am UTC](https://discourse.julialang.org/t/conditional-multithreading/32421/10 "2024-03-06T09:29:00Z")

</div>

I don’t see the need to depending on different packages, you can just create an internal macro to turn on/off the `@threads`, no? It’s just an if statement inside a macro if that’s all you want.

I’ve done this to switch between parallelism in SymbolicRegression, including distributed mode:

> <https://github.com/MilesCranmer/SymbolicRegression.jl/blob/master/src/SearchUtils.jl#L46-L66>

Which you can then use like

```julia
out = @sr_spawner(
    do_stuff(),
    parallelism=:multithreading, #runtime value
    worker_idx=i, #worker index (or unused)
)

```

Pretty simple and gets the job done.

This is for manual spawning tasks but you could do the same with the loop-wrapping macro.

---

<div class="post-metadata">

**Author:** ![Ahmed\_Salih](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ahmed_salih/32/206579_2.png) [@Ahmed\_Salih](https://discourse.julialang.org/u/Ahmed_Salih)\
**Post date:** [March 8, 2024, 9:13am UTC](https://discourse.julialang.org/t/conditional-multithreading/32421/11 "2024-03-08T09:13:43Z")

</div>

Thank you all for the answers above.

@abraemer I am using ChunkSplitters.jl and while I agree that using nchunks=1 is practically setting it to single threaded, then unfortunately it does not deactivate `@threads`. I am developing an algorithm and make to sure my code does not allocate, but can also be run in parallel in needed, which is why I need such an option for `@threads`.

What @carstenbauer and @scheidan1 mention seem promising.

@MilesCranmer I think I will investigate what you mention, I should be able to make a copy of `@threads` taking in an extra argument like `execute` which can be eitehr true or false - this seems quite valid?

Kind regards

---

<div class="post-metadata">

**Author:** ![MilesCranmer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milescranmer/32/21070_2.png) [@MilesCranmer](https://discourse.julialang.org/u/MilesCranmer)\
**Post date:** [March 9, 2024, 4:25pm UTC](https://discourse.julialang.org/t/conditional-multithreading/32421/12 "2024-03-09T16:25:46Z")

</div>

If all you want to do is conditional multithreading, you can just do this –

```julia
macro maybe_threads(flag, expr)
    quote
        if $(flag)
            Threads.@threads $expr
        else
            $expr
        end
    end |> esc
end

```

then you can use it like

```julia
julia> @maybe_threads flag for i in eachindex(x)
           x[i] = x[i] ^ 2
           @show i
       end
i = 3
i = 1
i = 2

```

for some `flag = true` or `false`.

---

<div class="post-metadata">

**Author:** ![jgreener64](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jgreener64/32/2483_2.png) [@jgreener64](https://discourse.julialang.org/u/jgreener64)\
**Post date:** [March 12, 2025, 11:50am UTC](https://discourse.julialang.org/t/conditional-multithreading/32421/13 "2025-03-12T11:50:04Z")

</div>

This is a useful snippet, thanks.
