【问题标题】:How to send a struct to new workers in Julia?如何向 Julia 中的新工作人员发送结构?
【发布时间】:2020-04-02 20:02:44
【问题描述】:

我已经定义了一个结构,它应该用作不同函数的输入,而这些函数又被不同的工作人员调用。字段值将在函数中更改,因此我无法在函数调用之间构造它们。如何将结构发送给新员工?我试过@eval @everywheresendto 来自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

我使用 Julia 1.3.1

【问题讨论】:

    标签: struct parallel-processing julia distributed-computing


    【解决方案1】:

    所有定义新类型和方法的代码都应该为所有进程所知(因此使用@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"
    
    

    【讨论】:

      【解决方案2】:

      我了解您的问题是关于使用远程工作人员对本地 structs 进行变异。 你不能这样做,但是你可以发送一份新的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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-11-12
        • 1970-01-01
        • 2011-06-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-06
        • 1970-01-01
        相关资源
        最近更新 更多