Yes, there are a few problems here. First, a little note on workers: It’s easier to think of the workers as independent Julia processes, infact each worker is simply a Julia instance with the --worker
command line argument (so addprocs
literally launches n julia --worker
processes and connects them together). Point is that each worker is a fresh instance with no variables/modules/functions defined (except the standard library ones). Note that if you launch a fresh Julia instance, and just type in runfunction()
or A
, you will get not defined
error. You are seeing similar problems here.
Lets go through your code.
You’ve correctly defined the module testmoda
in all workers. But how exactly do you use a module in Julia? By the using
statement! so indeed, running
julia> @everywhere using .testmoda
will bring all exported functions of that module, including getmyA
in scope. Mind the .
notation here since it’s a locally defined module. Now that your function is imported, we can run
julia> @fetchfrom 2 getmyA()
ERROR: On worker 2:
UndefVarError: A not defined
ta-da! it works (although it does produce another error). Alternatively, if you don’t run using testmoda
, you can also just directly scope into the module… i.e. @fetchfrom 2 testmoda.getmyA()
, but it’s just easier to do a using
statement if you have a lot of exported functions.
The function runs, but now produces a second UndefVarError
. It’s complaining that A
isn’t defined, even though you have run @everywhere A = [1:nworkers();]
. This expression indeed defines a global variable in all workers, however it defines it under the default module Main
. You can see this by executing
julia> @fetchfrom 2 (@which A)
Main
which asks where A
is defined on worker 2 (and you see its defined in Main
). So when running getmyA()
it’s looking for a variable A
inside the module testmoda
, which dosn’t exist. If you really want to define a global variable inside the module testmoda
, you have to use eval
. So something like
julia> @everywhere @eval testmoda (A = [9, 10, 11])
which runs the @eval testmoda (A = [9, 10, 11])
command on all workers. The @eval
macro itself requires two arguments. The first testmoda
says in which module to execute the statement, and the second argument (A = [9, 10, 11])
is the statement to be executed.
Now A
is defined in testmoda
(infact, if you havn’t reset your session, its also defined in Main
). But everything should work:
julia> @everywhere @eval testmoda (A = [9, 10, 11])
julia> @fetchfrom 2 getmyA()
10
Ofcourse, this is all for learning purposes. Using global variables like this and the use of @eval
is not really meant for production level code unless you absolutely know what you are doing. If you just want to define a global variable, just do it in the module directly. i.e.
using Distributed,Test
addprocs(3)
@everywhere module testmoda
using Distributed
A = zeros(Float64, 3) ## define global variable in `testmoda`
function getmyA()
global A
A[myid()]
end
export getmyA
end