How to make use of Threads optional in a Julia function
Asked Answered
A

2

6

I have a function that optionally uses threads for its main loop, doing so when an argument usingthreads is true. At the moment, the code looks like this:

function dosomething(usingthreads::Bool)
    n = 1000
    if usingthreads
        Threads.@threads for i = 1:n
            #20 lines of code here
        end
    else
        for i = 1:n
            #same 20 lines of code repeated here
        end
    end
end

Less nasty than the above would be to put the "20 lines" in a separate function. Is there another way?

Avidity answered 27/10, 2019 at 14:48 Comment(3)
what version of Julia? Julia 1.3 significantly enhances threading, and would make some of this easierTarbox
I haven't yet experimented with 1.3, still on 1.2Avidity
For this specific usecase I think the method you've described works fine. However, if you want to incorporate thread-specific optimizations, you might want to do something like this: julia function dosomething(::Val{false}) # nonthreaded case # implementation here end function dosomething(::Val{true}) # nonthreaded case # threaded implementation here end dosomething(usethreads::Bool) = dosomething(Val(usethreads)) Would this be good style?Ekaterinoslav
R
4

You could use a macro that changes its behavior depending on the result of Threads.nthreads():

macro maybe_threaded(ex)
    if Threads.nthreads() == 1
        return esc(ex)
    else
        return esc(:(Threads.@threads $ex))
    end
end

Without threading, this macro will be a no-op:

julia> @macroexpand @maybe_threaded for i in 1:5
           print(i)
       end
:(for i = 1:5
      #= REPL[2]:2 =#
      print(i)
  end)

But when threading is enabled and e.g. JULIA_NUM_THREADS=4 it will expand to the threaded version:

julia>  @maybe_threaded for i in 1:5
           print(i)
       end
41325

Edit: Upon rereading the question, I realize this doesn't really answer it but it might be useful anyway.

Rift answered 27/10, 2019 at 16:43 Comment(2)
You're doubly correct: a) it doesn't (quite) answer my question, b) I might well find it useful, particularly as I've not yet written any macros.Avidity
Why doesn't the @threads macro work like that by default, BTW? I have the impression that threading carries some overhead that could be avoided like this.Jacquelynejacquelynn
A
1

You can use ThreadsX as suggested in this discourse link.

The answer from the thread (all credit to oxinabox):

using ThreadsX

function foo(multi_thread=true)
    _foreach = multi_thread ? ThreadsX.foreach : Base.foreach
    _foreach(1:10) do ii
        @show ii
    end
end
Audraaudras answered 2/6, 2022 at 6:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.