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?
@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.
Most helpful comment
local variables can be broadcast to remote workers by preceeding
@everywherewith an@evaland interpolating the symbol of the local variable:shall we close this issue?