# Simplest way to parallelize a while loop

**URL:** <https://discourse.julialang.org/t/simplest-way-to-parallelize-a-while-loop/22600>\
**Category:** General Usage\
**Created:** [April 1, 2019, 2:59pm UTC](https://discourse.julialang.org/t/simplest-way-to-parallelize-a-while-loop/22600 "2019-04-01T14:59:38Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Adrien](https://avatars.discourse-cdn.com/v4/letter/a/ea666f/32.png) [@Adrien](https://discourse.julialang.org/u/Adrien)\
**Post date:** [April 1, 2019, 2:59pm UTC](https://discourse.julialang.org/t/simplest-way-to-parallelize-a-while-loop/22600/1 "2019-04-01T14:59:38Z")

</div>

I’m wondering what’s the easiest way to multi-thread a code of the following form:

```julia
L=[someStuff]
while !isempty(L)
    current=pop!(L)
    #do some computations involving current
    if someConditionDependingOnThoseComputations
        push!(L, anArrayOfStuffs...)
    end
end

```

So roughly I’d like something like the Threads.@threads macro but for while loops (using locks before pop!-ing and push!-ing of course). In fact there’s an obvious way of doing what I want just by using this macro and doing a for loop on the number of threads and so on, I’m just wondering if there’s a better/cleaner way to do it.

I’ve had a quick look at the code of this macro, and the key seems to be

```julia
ccall(:jl_threading_run, Ref{Cvoid}, (Any,), someFunction)

```

But I haven’t found any documentation on how to properly use that, and of course there might be a better way ! Any suggestion welcome.

---

<div class="post-metadata">

**Author:** ![favba](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/favba/32/2735_2.png) [@favba](https://discourse.julialang.org/u/favba)\
**Post date:** [April 2, 2019, 5:04pm UTC](https://discourse.julialang.org/t/simplest-way-to-parallelize-a-while-loop/22600/2 "2019-04-02T17:04:13Z")

</div>

> [@Adrien](#):
>
> In fact there’s an obvious way of doing what I want just by using this macro and doing a for loop on the number of threads and so on

Currently, I think that is indeed the most straightforward way.  
If that is something you do very often you can create your own macro. Something like the **pseudocode** below

```julia
macro threadit(b)
    quote
       Threads.@threads for _ in Base.OneTo(Threads.nthreads())
            $b
        end
    end
end

```

---

<div class="post-metadata">

**Author:** ![Adrien](https://avatars.discourse-cdn.com/v4/letter/a/ea666f/32.png) [@Adrien](https://discourse.julialang.org/u/Adrien)\
**Post date:** [April 2, 2019, 7:09pm UTC](https://discourse.julialang.org/t/simplest-way-to-parallelize-a-while-loop/22600/3 "2019-04-02T19:09:24Z")

</div>

RIght, unfortunately it’s not that easy, the threads need to keep looping while there’s work to be done, and sometimes they have to wait while L is empty but other threads are running. I’ve tried writing down a dummy version of what I want, but the result is not super elegant, and on Julia 1.0 it keeps provoking a segfault although there are locks everywhere… On 1.1 it works sometimes, throw somewhat random errors some other times, and segfault every once in a while.

```julia
function test(n::Real) #try test(100.0)
    a=Threads.Mutex()
    c=Threads.Condition()
    atwork=Threads.Atomic{Int}(0)
    L=[n]
    Threads.@threads for i in 1:Threads.nthreads()
        while true
            lock(a)
            while isempty(L) && atwork[] >0 #we wait while L is empty but other threads are working
                unlock(a)
                wait(c)
                lock(a)
            end
            if isempty(L) && atwork[]==0 #if nobody's working and L is empty the work is done !
                unlock(a)
                break
              end
            Threads.atomic_add!(atwork,1) #we are starting to do stuff
            x=pop!(L) #take the next task
            unlock(a)
            for j=1:100
                x^10 #useless computation
            end
            if abs(x)>1
                lock(a)
                append!(L,[x/2,x/2]) #push something into L
                unlock(a)
            end
            Threads.atomic_sub!(atwork,1) #not doing stuffs anymore
            notify(c) #tell people waiting they need to go on and check L again
        end
    end
end

```
