Julia: @everywhere for broadcasting variables

Created on 23 Nov 2014  路  12Comments  路  Source: JuliaLang/julia

addprocs(1)
foo=1
@everywhere bar=foo

results in

julia> @everywhere bar=foo
exception on 2: ERROR: foo not defined
 in eval at /home/tan/julia/julia/base/sysimg.jl:7

While

@spawnat 2 global bar=foo
remotecall_fetch(2, ()->bar)

works perfectly fine.

Shouldn't @everywhere which runs in the scope of Main be a perfectly appropriate method to broadcast variables?

parallel

Most helpful comment

local variables can be broadcast to remote workers by preceeding @everywhere with an @eval and interpolating the symbol of the local variable:

julia> addprocs(1)
1-element Array{Int64,1}:
 2

julia> foo=1
1

julia> @eval @everywhere bar=$foo

julia> remotecall_fetch(()->bar,2)
1

julia> bar
1

shall we close this issue?

All 12 comments

@everwhere global bar=foo works, and seems to be clearer to read.

No, it doesn't.....I think you did not do an addprocs....or foo was already defined.

$ julia -p 1
               _
   _       _ _(_)_     |  A fresh approach to technical computing
  (_)     | (_) (_)    |  Documentation: http://docs.julialang.org
   _ _   _| |_  __ _   |  Type "help()" for help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 0.4.0-dev+1762 (2014-11-22 22:37 UTC)
 _/ |\__'_|_|_|\__'_|  |  Commit 7d41d6e (0 days old master)
|__/                   |  x86_64-linux-gnu

julia> foo=1
1

julia> @everywhere bar=foo
exception on 2: ERROR: foo not defined
 in eval at /home/tan/julia/julia/base/sysimg.jl:7
 in anonymous at multi.jl:1395
 in anonymous at multi.jl:820
 in run_work_thunk at multi.jl:593
 in run_work_thunk at multi.jl:602
 in anonymous at task.jl:6

julia> @everywhere global bar=foo
exception on 2: ERROR: foo not defined
 in eval at /home/tan/julia/julia/base/sysimg.jl:7
 in anonymous at multi.jl:1395
 in anonymous at multi.jl:820
 in run_work_thunk at multi.jl:593
 in run_work_thunk at multi.jl:602
 in anonymous at task.jl:6

I did do addprocs, but I may have set the variable everywhere and not needing a broadcast. The point here that you are making is that @everywhere should broadcast things that are only on the client. The current reason for @everywhere , as I understand, is to just execute the same code everywhere. Automatically broadcasting seems a bit too magical, especially if some variables were local and others were broadcasted as part of an expression.

Perhaps we should have explicit broadcasting:

@everywhere bar=bcast(foo)

Well, from a user point of view why should the behavior be different between

@spawnat p expr which runs expr on process p and
@everywhere which runs expr on all processes under _Main_

That is a reasonable point. I have usually always thought of @spawnat taking local data and executing it on a different processor, and @everywhere to simply execute a piece of code on all processors without specific reference to any particular environment. It doesn't have to be that way. Perhaps @everywhere could be instead called @spawnall with the same behaviour as @spawnat.

We need to preserve some syntax for evaluation in the remote context. i.e. we still need an equivalent of

@everywhere println(myid())

that returns the local ID on each process. That said, this problem has definitely caused me grief before, and it currently takes too much effort to broadcast a variable.

note that amit's @spawnat trick to broadcast variables to other processes does not work for ARGS:

test.jl:

addprocs(1)

@spawnat 2 global bar = ARGS[1]
println(remotecall_fetch(2,()->bar))

tmp = "foo"
@spawnat 2 global bar = tmp
println(remotecall_fetch(2,()->bar))

tmp = ARGS[1]
@spawnat 2 global bar = tmp
println(remotecall_fetch(2,()->bar))

on the unix command line:

$ julia test.jl pooh
--bind-to
foo
pooh

not sure whether to consider this a bug or feature but it took me long enough to figure out a work around that i thought i'd post the solution.

note also that the remote variable name has to be different than the local:

julia> addprocs(1)
1-element Array{Any,1}:
 2

julia> bar = "bar"
"bar"

julia> @spawnat 2 global bar = bar
RemoteRef(exception on 2: 2,1,3)

julia> println(remotecall_fetch(2,()->bar))
ERROR: bar not defined
 in anonymous at multi.jl:1533
 in anonymous at multi.jl:844
 in run_work_thunk at multi.jl:603
 in run_work_thunk at multi.jl:612
 in anonymous at task.jl:6
exception on 2: ERROR: bar not defined
 in anonymous at none:1
 in anonymous at multi.jl:852
 in run_work_thunk at multi.jl:603
 in anonymous at task.jl:852
UndefVarError(:bar)

how about adding something like this to Base?

macro constant(varname, varvalue)
  tmp = eval(varvalue)
  quote
    for i in procs()
      @spawnat i global const $varname = $tmp
    end
  end
end

one could then simply broadcast a global const as follows:

addprocs(1)

@constant tmp1 "pooh"

foo = "fooval"
@constant tmp2 foo

@constant tmp3 ARGS[1]

A simple function to broadcast vars to all cores would be great!
Someone wrote a sol'n here too http://stackoverflow.com/questions/27677399/julia-how-to-copy-data-to-another-processor-in-julia/27724240#27724240

local variables can be broadcast to remote workers by preceeding @everywhere with an @eval and interpolating the symbol of the local variable:

julia> addprocs(1)
1-element Array{Int64,1}:
 2

julia> foo=1
1

julia> @eval @everywhere bar=$foo

julia> remotecall_fetch(()->bar,2)
1

julia> bar
1

shall we close this issue?

Lets document this and then close the issue. The difference in behavior between @spawnat and @everywhere is because @spawnat creates a closure that is then executed remotely while @everywhere ships the expression as is.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

TotalVerb picture TotalVerb  路  3Comments

m-j-w picture m-j-w  路  3Comments

tkoolen picture tkoolen  路  3Comments

manor picture manor  路  3Comments

StefanKarpinski picture StefanKarpinski  路  3Comments