Как отправить структуру новым работникам в Юлии? - PullRequest
1 голос
/ 02 апреля 2020

Я определил структуру, которая должна использоваться в качестве входных данных для разных функций, которые, в свою очередь, вызываются разными работниками. Значения полей будут изменены в функциях, поэтому я не могу построить их новыми между вызовами функций. Как я могу отправить структуру новым работникам? Я пробовал @eval @everywhere, а также sendto из пакета ParallelDataTransfer .


using Distributed
using Parameters

@with_kw struct Test
    path1::String = ""
    path2::String = ""
end

test = Test()
addprocs(2)
@eval @everywhere test = $test

Output:
ERROR: On worker 2:
UndefVarError: Test not defined

using ParallelDataTransfer
sendto(workers(), test=test)

@everywhere print(test)

Output:
ERROR: On worker 2:
UndefVarError: test not defined

Я использую Юлию 1.3.1

Ответы [ 2 ]

0 голосов
/ 02 апреля 2020

Я понимаю, что ваш вопрос о мутировании локальных struct с удаленными работниками. Вы не можете сделать это, однако вы можете отправить копию нового struct:

using Distributed
addprocs(2)
using Parameters
@everywhere using Parameters
@everywhere begin
    @with_kw mutable struct Test
        a::String = ""
        b::String = ""
    end
end

t = Test(a="some")

@everywhere function mutate(t::Test)
    t.b = "newval"
    t
end

fut = @spawnat 2 mutate(t)
newt = fetch(fut)

Теперь вы можете видеть, что newt содержит измененную копию t:

julia> dump(newt)
Test
  a: String "some"
  b: String "newval"

Однако значение t остается прежним:

julia> dump(t)
Test
  a: String "some"
  b: String ""

Однако вы можете мутировать массивы на основе битов, если рабочие находятся на одном хосте. (В этом примере предполагается, что рабочие были добавлены с использованием предыдущего кода):

using SharedArrays
@everywhere using SharedArrays

sa = SharedArray([1,2,3,4])

@everywhere function mutate(sa::SharedArray)
    sa[myid()] = myid()*100;
    return nothing
end

fetch(@spawnat 2 mutate(sa))

Теперь давайте рассмотрим массив:

julia> display(sa)
4-element SharedArray{Int64,1}:
   1
 200
   3
   4
0 голосов
/ 02 апреля 2020

Весь код, определяющий новые типы и методы, должен быть известен всем процессам (и поэтому должен быть каким-то образом включен с помощью предложения @everywhere). В противном случае другие процессы не будут знать, что означает Test.

В целом, если я правильно понимаю, чего вы пытаетесь достичь, ваш пример может выглядеть следующим образом:

julia> using Distributed

# Add new processes at first, so that they will be affected by subsequent
# @everywhere invocations
julia> addprocs(2)
2-element Array{Int64,1}:
 2
 3

# All code defining new types / methods should be evaluated in all processes
julia> @everywhere begin
           # This common code should probably live somewhere else, like in
           # another source file:
           #  include("some_file.jl")

           struct Test
               path1::String
           end

           path1(x::Test) = x.path1
       end

# Create the object in the master process
julia> x = Test("foo")
Test("foo")

# Send it to another one for processing
julia> f = @spawnat 2 path1(x)
Future(2, 1, 8, nothing)

# And get the answer back
julia> fetch(f)
"foo"

...