Hello all,
I’m working on some code where each remote worker needs to compute an array by accumulating values, and the arrays then need to be summed. Below is an absolute minimum working example to demonstrate the problem I’m encountering.
Obviously, the code below (lines 5 and 6) will not work because I did not use @everywhere
when defining q
. In my program though, “q
” is the result of many functions and other variables, so I’m hoping there is another way to copy q
to all workers without needing to use @everywhere
in front of every one of q
’s dependencies.
Any guidance or suggestions would be much appreciated. Thanks!
using Distributed
addprocs(2)
q = reshape(rand(9), 3, 3)
@everywhere nrow = eval(size(q, 1))
@everywhere ncol = eval(size(q, 2))
for i in workers()
@spawnat i eval(:(a = fill(0, nrow, ncol)))
end
1 Like
In fact, I believe using @everywhere
on all preceding variables will not work in my program because workers are created after some variables have already been defined.
After some random trial and error, this appears to work, but I’m not exactly sure why.
using Distributed
addprocs(2)
q = fill(rand(9), 3, 3)
@everywhere nrows = @eval size($q, 1)
@everywhere ncols = @eval size($q, 2)
for i in workers()
@spawnat i eval(:(a = fill(0, nrows, ncols)))
end
You can avoid the @eval
and just interpolate the sizes into @everywhere:
@everywhere nrows = $(size(q, 1))
@everywhere ncols = $(size(q, 2))
2 Likes
The solutions posted do work in the MWE, but for some reason they don’t work in my Julia package. Could it be something to do with function dependencies? Here’s the code that is encountering the problem. This is all inside a function, by the way, and parse_cfg
and read_ascii
are both functions in my package. FWIW, all of the code is available on GitHub here.
cfg = parse_cfg(path)
calc_flow_potential = cfg["calc_flow_potential"] == "true"
parallelize = cfg["parallelize"] == "true"
n_workers = parse(Int64, cfg["max_parallel"])
sources_raw = float(read_ascii("$(cfg["source_file"])"))
if parallelize
println("Starting up Omniscape to use $(n_workers) processes in parallel")
myaddprocs(n_workers)
@everywhere nrows_remote = $(size(sources_raw, 1))
@everywhere ncols_remote = $(size(sources_raw, 2))
for i in workers()
@spawnat i eval(:(cum_currmap = fill(0.,
nrows_remote,
ncols_remote)))
end
if calc_flow_potential
for i in workers()
@spawnat i eval(:(fp_cum_currmap = fill(0.,
nrows_remote,
ncols_remote)))
end
end
end
myaddprocs(n)
is simply addprocs(n)
then @everywhere Core.eval(Main, :(import Omniscape))
EDIT
I did get everything sorted by using remotefetch()
instead, FWIW!
I found a super hacky workaround using pmap
to effectively copy the variables to remote workers using the following: (this is clearly not an ideal solution)
function copyvars(i, array)
global nrows_remote = size(array, 1)
global ncols_remote = size(array, 2)
end
pmap(x -> copyvars(x, sources_raw), 1:50)
Any reason why this works while the script in the post just above doesn’t? Thanks again for any insight!
1 Like