Hello,
I ran into this today, if you have a module with a mutable struct:
module container2
export cont2
mutable struct cont2
a
end
end
When the fields of the mutable struct are changed on the master node, this change is not detected on the other procs:
addprocs(3)
3-element Array{Int64,1}:
2
3
4
using container2
bla=cont2((0.,0.))
container2.cont2((0.0, 0.0))

@sync for ip in procs()
@spawnat ip @show bla.a
end
bla.a = (0.0, 0.0)
From worker 2: bla.a = (0.0, 0.0)
From worker 4: bla.a = (0.0, 0.0)
From worker 3: bla.a = (0.0, 0.0)
bla.a=((1.,1.))
@sync for ip in procs()
@spawnat ip @show bla.a
end
bla.a = (1.0, 1.0)
From worker 2: bla.a = (0.0, 0.0)
From worker 4: bla.a = (0.0, 0.0)
From worker 3: bla.a = (0.0, 0.0)
That was surprising behavior to me, and it can lead to bugs. Is this expected behavior?
Thank you
How should the remote processes know that the value has been updated? Use @everywhere
:
julia> bla = container2.cont2((0., 0.))
container2.cont2((0.0, 0.0))
julia> @sync for ip in procs()
@spawnat ip @show bla.a
end
bla.a = (0.0, 0.0)
From worker 2: bla.a = (0.0, 0.0)
From worker 3: bla.a = (0.0, 0.0)
From worker 4: bla.a = (0.0, 0.0)
julia> bla.a = ((1., 1.))
(1.0, 1.0)
julia> @sync for ip in procs()
@spawnat ip @show bla.a
end
bla.a = (1.0, 1.0)
From worker 2: bla.a = (0.0, 0.0)
From worker 4: bla.a = (0.0, 0.0)
From worker 3: bla.a = (0.0, 0.0)
julia> @everywhere bla.a = ((2., 2.))
julia> @sync for ip in procs()
@spawnat ip @show bla.a
end
bla.a = (2.0, 2.0)
From worker 2: bla.a = (2.0, 2.0)
From worker 4: bla.a = (2.0, 2.0)
From worker 3: bla.a = (2.0, 2.0)
The point is that @spawnat
interpolates the variables from Main
to the other processes (@everywhere
does not for example). So the first call defines bla
everywhere, by “sending” bla
from the master.
In subsequent calls, @spawnat
checks, if bla
has changed (if the variable was rebound, for example), it re-interpolates the new variable. But if only the contents have mutated, the change is not detected and the variable is not re-interpolated (for efficiency reasons I am guessing). I found it surprising, I thought it was always synchronizing the variable. Is that documented?