# How to early return from inside a @threads loop

**URL:** <https://discourse.julialang.org/t/how-to-early-return-from-inside-a-threads-loop/97457>\
**Category:** General Usage\
**Tags:** question, parallel, multithreading, threads\
**Created:** [April 14, 2023, 7:39am UTC](https://discourse.julialang.org/t/how-to-early-return-from-inside-a-threads-loop/97457 "2023-04-14T07:39:01Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![sylvaticus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sylvaticus/32/203883_2.png) [@sylvaticus](https://discourse.julialang.org/u/sylvaticus)\
**Post date:** [April 14, 2023, 7:39am UTC](https://discourse.julialang.org/t/how-to-early-return-from-inside-a-threads-loop/97457/1 "2023-04-14T07:39:01Z")

</div>

Normally you are thought to avoid thread race in parallel programming, but in certain conditions you would want a sort of thread race.  
I need to compute some expensive computation and return the function the first time I find some condition, doesn’t matter if this happens on the 2nd or the 200th element of the data:

```julia
test = rand(1:10,1000)
function foo(data)
    Threads.@threads for i in 1:length(data)
        # complex computation here
        if data[i] == 10 # first thread that finds a specific condition "wins" and returns
            return (i, data[i])
        end
    end
end
a = foo(test) # this doesn't work

```

Which is the “correct” programming pattern for these situations? Clearly not the one above 🙂

---

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [April 14, 2023, 8:39am UTC](https://discourse.julialang.org/t/how-to-early-return-from-inside-a-threads-loop/97457/2 "2023-04-14T08:39:22Z")

</div>

I’m not sure what “ **the** correct™ programming pattern” would be, but I think something like this should work:

```julia
function findany(pred, data)
    # Hand-written chunk definition, you can use ChunkSplitter.jl instead
    nchunks = Threads.nthreads()
    bounds = round.(Int, LinRange(firstindex(data), lastindex(data)+1, nchunks+1))
    chunks = [bounds[i]:bounds[i+1]-1 for i in 1:nchunks]

    # A Channel to synchronize tasks
    c = Channel{Int}(1)

    # One task per chunk
    tasks = map(chunks) do chunk
        Threads.@spawn begin
            for i in chunk
                # If the Channel is closed, some other task must have found something
                # => return early
                isopen(c) || break

                if pred(data[i])
                    # If an element matching the predicate is found, try putting in in the Channel
                    try
                        put!(c, i)
                    catch e
                        # Gracefully handle cases when the Channel has been closed
                        # since the last time we checked
                        e isa InvalidStateException || rethrow()
                    end
                    break
                end
            end
        end
    end

    # Wait for a result to be put into the Channel
    idx = take!(c)
    # ... and close it to notify all other tasks that they should stop looking
    close(c)

    # Wait for all tasks to terminate
    foreach(wait, tasks)

    return (idx, data[idx])
end

test = rand(1:10, 1000);
function pred(x) # an expensive predicate
    sleep(0.1)
    x == 10
end
findany(pred, test)

```

---

<div class="post-metadata">

**Author:** ![sylvaticus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sylvaticus/32/203883_2.png) [@sylvaticus](https://discourse.julialang.org/u/sylvaticus)\
**Post date:** [April 14, 2023, 8:51am UTC](https://discourse.julialang.org/t/how-to-early-return-from-inside-a-threads-loop/97457/3 "2023-04-14T08:51:48Z")

</div>

Thanks™.

See also this previous …[thread](https://discourse.julialang.org/t/is-there-a-way-to-return-from-a-function-from-within-a-thread/35656/7)…

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [April 14, 2023, 11:52am UTC](https://discourse.julialang.org/t/how-to-early-return-from-inside-a-threads-loop/97457/4 "2023-04-14T11:52:55Z")

</div>

> [@sylvaticus](#):
>
> Normally you are thought to avoid thread race in parallel programming, but in certain conditions you would want a sort of thread race.

Note that this isn’t true: in Julia, like in most other languages, a data race is always a serious user error, see the “Data-race freedom” subsection in the Manual: [Multi-Threading · The Julia Language](https://docs.julialang.org/en/v1/manual/multi-threading/#Data-race-freedom)

---

<div class="post-metadata">

**Author:** ![sylvaticus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sylvaticus/32/203883_2.png) [@sylvaticus](https://discourse.julialang.org/u/sylvaticus)\
**Post date:** [April 14, 2023, 12:03pm UTC](https://discourse.julialang.org/t/how-to-early-return-from-inside-a-threads-loop/97457/5 "2023-04-14T12:03:01Z")

</div>

yes, sure… this is why I used “a sort of”… but yes, the word is not fortunate…

---

<div class="post-metadata">

**Author:** ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)\
**Post date:** [April 14, 2023, 12:14pm UTC](https://discourse.julialang.org/t/how-to-early-return-from-inside-a-threads-loop/97457/6 "2023-04-14T12:14:05Z")

</div>

The thread name is not really describing the problem: It’s easy to make a data race that won’t solve the problem here. Maybe you will get better answers if you rename the thread to “How to return from inside a @threads loop” or something like that?

---

<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 14, 2023, 12:17pm UTC](https://discourse.julialang.org/t/how-to-early-return-from-inside-a-threads-loop/97457/7 "2023-04-14T12:17:01Z")

</div>

Another way, which is safe, is to use a lock:

```julia
julia> using ChunkSplitters
       function foo(data; nchunks=Threads.nthreads())
           lk = ReentrantLock()
           iwin, datawin = nothing, nothing
           Threads.@threads for (i_range, _) in chunks(data, nchunks)
               for i in i_range
                   if !isnothing(iwin)
                       break
                   end
                   # complex computation here
                   lock(lk) do 
                       if isnothing(iwin)
                           if data[i] == 10
                               iwin, datawin = i, data[i]
                           end
                       end
                   end
               end
           end
           return iwin, datawin
       end
foo (generic function with 1 method)

julia> a = foo(test)
(29, 10)

```
