Have you tried macroexpanding the expression? Doing so yields

julia> macroexpand(:( for i = 1:N 
                          @sync @parallel for j = (i + 1):N  
                              tmp[j] = i * j  
                          end 
                      end )) 

:(for i = 1:N # line 2: 
        begin  # task.jl, line 342: 
            Base.sync_begin() # line 343: 
            #6#v = begin  # multi.jl, line 1487: 
                    Base.pfor($(Expr(:localize, :(()->begin  # expr.jl, 
line 113: 
            begin  # multi.jl, line 1460: 
                function (#7#lo::Base.Int,#8#hi::Base.Int) # multi.jl, line 
1461: 
                    for j = (i + 1:N)[#7#lo:#8#hi] # line 1462: 
                        begin  # line 3: 
                            tmp[j] = i * j 
                        end 
                    end 
                end 
            end 
        end))),Base.length(i + 1:N)) 
                end # line 344: 
            Base.sync_end() # line 345: 
            #6#v 
        end 
    end)


 It looks like @parallel does the work of setting up a properly formatted 
call to Base.pfor. In particular, it builds an Expr object with head 
:localize and argument a zero-arg anonymous function, and then passes the 
interpolation of that expression along with `Base.length(i + 1:N)` to 
Base.pfor. The body of the anonymous function declares another function 
with arguments `#7#lo`, `#8#hi`. The latter variables somehow annotate the 
delimiters of your inner loop, which gets reproduced inside the body of the 
declared function. I'm *guessing* that the anonymous function is used as a 
vehicle to pass the code of the annotated inner loop to Base.pfor without 
executing it beforehand. But I could be wrong.


Then @sync just wraps all the above between calls to `Base.sync_begin` and 
`Base.sync_end`.


I also should note I have zero experience with Julia's parallel machinery 
and am entirely unfamiliar with the internals of Base.pfor. I just enjoy 
trying to figure out macros.

On Wednesday, June 17, 2015 at 5:49:58 AM UTC-4, Daniel Carrera wrote:
>
>
> On Wednesday, 17 June 2015 10:28:37 UTC+2, Nils Gudat wrote:
>>
>> I haven't used @everywhere in combination with begin..end blocks, I 
>> usually pair @sync with @parallel - see an example here 
>> <https://github.com/nilshg/LearningModels/blob/master/NHL/NHL_6_Bellman.jl>, 
>> where I've parallelized the entire nested loop ranging from lines 25 to 47. 
>>
>
>
> Aha! Thanks. Copying your example I was able to produce this:
>
>     N = 5
>     tmp = SharedArray(Int, (N))
>     
>     for i = 1:N
>         # Compute tmp in parallel #
>         @sync @parallel for j = (i + 1):N
>             tmp[j] = i * j
>         end
>         
>         # Consume tmp in serial #
>         for j = (i + 1):N
>             println(tmp[j])
>         end
>     end
>
>
> This seems to work correctly and gives the same answer as the serial code. 
> Can you help me understand how it works? What does "@sync @parallel" do? I 
> feel like I half-understand it, but the concept is not clear in my head.
>
> Thanks.
>
> Daniel.
>

Reply via email to