Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@everywhere for broadcasting variables #9118

Closed
amitmurthy opened this issue Nov 23, 2014 · 12 comments · Fixed by #15960
Closed

@everywhere for broadcasting variables #9118

amitmurthy opened this issue Nov 23, 2014 · 12 comments · Fixed by #15960
Labels
parallelism Parallel or distributed computation

Comments

@amitmurthy
Copy link
Contributor

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?

@ViralBShah ViralBShah added the parallelism Parallel or distributed computation label Nov 23, 2014
@ViralBShah
Copy link
Member

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

@amitmurthy
Copy link
Contributor Author

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

@ViralBShah
Copy link
Member

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)

@amitmurthy
Copy link
Contributor Author

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

@ViralBShah
Copy link
Member

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.

@blakejohnson
Copy link
Contributor

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.

@bjarthur
Copy link
Contributor

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.

@bjarthur
Copy link
Contributor

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)

@bjarthur
Copy link
Contributor

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]

@CorySimon
Copy link

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

@bjarthur
Copy link
Contributor

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?

@amitmurthy
Copy link
Contributor Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
parallelism Parallel or distributed computation
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants