# Optionally multi threaded for loop

**URL:** <https://discourse.julialang.org/t/optionally-multi-threaded-for-loop/81902>\
**Category:** Performance\
**Tags:** question\
**Created:** [May 30, 2022, 7:51am UTC](https://discourse.julialang.org/t/optionally-multi-threaded-for-loop/81902 "2022-05-30T07:51:19Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![this\_josh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/this_josh/32/42679_2.png) [@this\_josh](https://discourse.julialang.org/u/this_josh)\
**Post date:** [May 30, 2022, 7:51am UTC](https://discourse.julialang.org/t/optionally-multi-threaded-for-loop/81902/1 "2022-05-30T07:51:19Z")

</div>

I have a function which contains a loop which should normally be run multi threaded using `Threads.@threads`, but sometimes I want to run it single threaded.

```julia
function foo(multi_thread=true)
    mt = multi_thread ? Threads.@threads : nothing
    mt for ii in 1:10
        @show ii
    end
end

```

It is valid for `mt` to be nothing here, but an error occurs when trying to set `mt=Threads.@threads`.

How can I elegantly implement this functionality?

---

<div class="post-metadata">

**Author:** ![skleinbo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skleinbo/32/36080_2.png) [@skleinbo](https://discourse.julialang.org/u/skleinbo)\
**Post date:** [May 30, 2022, 8:19am UTC](https://discourse.julialang.org/t/optionally-multi-threaded-for-loop/81902/2 "2022-05-30T08:19:34Z")

</div>

This is not going to work, because the `@threads` macro expands at parse time.

~~You can however define a custom _macro_~~ **This is mostly useless, because the value of flag `mt` must be known at parse time too.**

```julia
julia> macro withthreads(mt::Bool, ex)
         if mt
           return esc(:(Threads.@threads $ex))
         else
           return esc(ex)
         end
       end
@withthreads (macro with 1 method)

julia> @withthreads true for i in 1:5
        println(Threads.threadid())
        end
1
1
2
4
3

julia> @withthreads false for i in 1:5
        println(Threads.threadid())
        end
1
1
1
1
1

```

---

<div class="post-metadata">

**Author:** ![this\_josh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/this_josh/32/42679_2.png) [@this\_josh](https://discourse.julialang.org/u/this_josh)\
**Post date:** [May 30, 2022, 8:29am UTC](https://discourse.julialang.org/t/optionally-multi-threaded-for-loop/81902/3 "2022-05-30T08:29:58Z")

</div>

I figured it must be something like that as it gave an error about passing `:` as an arg.

Thanks for your solution, defining a custom macro seems somewhat unnecessary and potentially confusing to users. It’s a shame there isn’t a way of having a short if statement in the function `foo`

---

<div class="post-metadata">

**Author:** ![skleinbo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skleinbo/32/36080_2.png) [@skleinbo](https://discourse.julialang.org/u/skleinbo)\
**Post date:** [May 30, 2022, 8:42am UTC](https://discourse.julialang.org/t/optionally-multi-threaded-for-loop/81902/4 "2022-05-30T08:42:56Z")

</div>

It’s also not a solution come to think of it.

Since macros are expanded at parse time, you can’t write something like `@withthreads mt [...]` where `mt` is only known at run time.

Actual solution: Write an inner function `_foo(i)` and branch

```julia
function foo(mt)
  if mt
     @threads for i [...]
        _foo(i)
      end
   else for i [...]
       _foo(i)
   end
end

```

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [May 30, 2022, 9:28am UTC](https://discourse.julialang.org/t/optionally-multi-threaded-for-loop/81902/5 "2022-05-30T09:28:09Z")

</div>

Basically instead of OP’s `foo(multi_thread=true)` attempting to modify its own code at runtime (impossible with a macro), `foo(mt)` created both versions of the code at parse-time and selects the branch at runtime. Turning a single-threaded version into `foo(mt)` could also be done with a macro, but it would only save effort if this pattern needs to be applied to several methods.

My only other thought is that dispatch can be leveraged if this was split into two different methods instead of two branches; one method could have an extra singleton argument e.g. `foo(...)` vs `foo(::OneThread, ...)`. This dispatch could happen at runtime as designed, but it could also happen at compile-time if there were a chain of single-or-multi-threaded functions calling one another. But I don’t think there would be any significant gain because the `multi_thread`/`mt` check is cheap and outside of multithread-able loops (you want each iteration to be its own thread, so no need to check).

---

<div class="post-metadata">

**Author:** ![this\_josh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/this_josh/32/42679_2.png) [@this\_josh](https://discourse.julialang.org/u/this_josh)\
**Post date:** [May 30, 2022, 10:59am UTC](https://discourse.julialang.org/t/optionally-multi-threaded-for-loop/81902/6 "2022-05-30T10:59:26Z")

</div>

I’d rather avoid multiple dispatch as the contents of the for loop is identical, so this would lead to code duplication. If I make the entire for loop contents a function there would still be a few lines duplicated and in my case the readability of the code would be impacted.

@skleinbo Thanks for your answer. As suggested above `_foo` hurts code readability and we have some duplicated lines here. Perhaps Julia isn’t able to get around these shortcomings in this instance though.  
If no one else suggests an idea which overcomes this, I’ll select your solution 🙂

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [May 30, 2022, 5:56pm UTC](https://discourse.julialang.org/t/optionally-multi-threaded-for-loop/81902/7 "2022-05-30T17:56:51Z")

</div>

Your concern about code duplication is valid, but there’s a bit of nuance here. Single-threaded and multi-threaded loops work very differently, so the code has to be different on some level. `@threads` is easy to type in front of a loop, but it’s doing a lot to the loop’s code at parse-time, just dig into its source code and see. The source code however remains the same to you, and you maintain it the same way as if it weren’t multithreaded.

Similarly, you could accomplish `@skleinbo` did with `foo(mt)` but by applying a macro to a loop, looking something like:

```julia
function foo(multi_thread=true)
  @multi_single_branch for ii in 1:10
    @show ii
  end
end

```

This way, you can have your branched code at parse-time but don’t need to maintain duplicated code in the source.  
You are probably right about eschewing multimethods; besides there being little gain, it seems like it’ll need a more complicated macro than making a loop.

---

<div class="post-metadata">

**Author:** ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)\
**Post date:** [May 30, 2022, 6:36pm UTC](https://discourse.julialang.org/t/optionally-multi-threaded-for-loop/81902/8 "2022-05-30T18:36:44Z")

</div>

I suggest that it is probably worth using one of the packages that provide more detailed threading functionality, and expose it as functions. Such as [ThreadsX.jl](https://github.com/tkf/ThreadsX.jl)  
The `@threads` macro in particular is kind of a legacy from before Julia had first class, user extensible, threading.  
It has some advantages but not a lot.  
(Julia, like LaTeX and unlike say C# or Python; is absolutely not batteries included. Many of the best things live in packages. But julia’s package manager makes it easy to install packages and makes their compat safe.)

With ThreadX.jl you can do:

```julia
using ThreadsX

function foo(multi_thread=true)
    _foreach = multi_thread ? ThreadsX.foreach : Base.foreach
    _foreach(1:10) do ii
        @show ii
    end
end

```

which works:

```julia
julia> foo(false)
ii = 1
ii = 2
ii = 3
ii = 4
ii = 5
ii = 6
ii = 7
ii = 8
ii = 9
ii = 10

julia> foo(true)
ii = 1
ii = 9
ii = 6
ii = 3
ii = 7
ii = 8
ii = 10
ii = 5
ii = 2
ii = 4

```

---

<div class="post-metadata">

**Author:** ![this\_josh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/this_josh/32/42679_2.png) [@this\_josh](https://discourse.julialang.org/u/this_josh)\
**Post date:** [May 31, 2022, 7:00am UTC](https://discourse.julialang.org/t/optionally-multi-threaded-for-loop/81902/9 "2022-05-31T07:00:02Z")

</div>

Thanks, this is exactly what I was looking for, it allows for the implementation without code duplication and doesn’t make the code much more complex to follow. I’ll use `ThreadsX` and the related [FLoops.jl](https://github.com/JuliaFolds/FLoops.jl) from now on.

---

<div class="post-metadata">

**Author:** ![Bruno\_Amorim](https://avatars.discourse-cdn.com/v4/letter/b/f6c823/32.png) [@Bruno\_Amorim](https://discourse.julialang.org/u/Bruno_Amorim)\
**Post date:** [May 31, 2022, 10:14am UTC](https://discourse.julialang.org/t/optionally-multi-threaded-for-loop/81902/10 "2022-05-31T10:14:32Z")

</div>

With `FLoops.jl` you can pass differente “executors” as arguments that control if the code if run serially of in parallel. More details here: [Parallel loops · FLoops](https://juliafolds.github.io/FLoops.jl/dev/tutorials/parallel/#tutorials-executor)
