Julia:如何将数据复制到Julia中的另一个处理器

时间:2014-12-28 14:39:59

标签: parallel-processing julia

如何在julia中将数据从一个处理器移动到另一个处理器?

说我有一个数组

a = [1:10]

或其他一些数据结构。将它放在所有其他可用处理器上的正确方法是什么,以便它们可以作为相同的变量名在这些处理器上使用?

4 个答案:

答案 0 :(得分:34)

我起初并不知道该怎么做,所以我花了一些时间搞清楚。

以下是我为传递对象而编写的一些函数:

sendto

向指定的进程发送任意数量的变量。

在指定进程的Main模块中创建新变量。该 name将是关键字参数的关键,值将是 相关价值。

function sendto(p::Int; args...)
    for (nm, val) in args
        @spawnat(p, eval(Main, Expr(:(=), nm, val)))
    end
end


function sendto(ps::Vector{Int}; args...)
    for p in ps
        sendto(p; args...)
    end
end

实施例

# creates an integer x and Matrix y on processes 1 and 2
sendto([1, 2], x=100, y=rand(2, 3))

# create a variable here, then send it everywhere else
z = randn(10, 10); sendto(workers(), z=z)

getfrom

检索任意模块中任意模块中定义的对象 处理。默认为主模块。

要检索的对象的名称应为符号。

getfrom(p::Int, nm::Symbol; mod=Main) = fetch(@spawnat(p, getfield(mod, nm)))

实施例

# get an object from named x from Main module on process 2. Name it x
x = getfrom(2, :x)

passobj

将任意数量的对象从一个进程传递给任意进程 流程。必须在from_mod模块中定义变量 src进程并将以相同的名称复制到to_mod 每个目标进程的模块。

function passobj(src::Int, target::Vector{Int}, nm::Symbol;
                 from_mod=Main, to_mod=Main)
    r = RemoteRef(src)
    @spawnat(src, put!(r, getfield(from_mod, nm)))
    for to in target
        @spawnat(to, eval(to_mod, Expr(:(=), nm, fetch(r))))
    end
    nothing
end


function passobj(src::Int, target::Int, nm::Symbol; from_mod=Main, to_mod=Main)
    passobj(src, [target], nm; from_mod=from_mod, to_mod=to_mod)
end


function passobj(src::Int, target, nms::Vector{Symbol};
                 from_mod=Main, to_mod=Main)
    for nm in nms
        passobj(src, target, nm; from_mod=from_mod, to_mod=to_mod)
    end
end

实施例

# pass variable named x from process 2 to all other processes
passobj(2, filter(x->x!=2, procs()), :x)

# pass variables t, u, v from process 3 to process 1
passobj(3, 1, [:t, :u, :v])

# Pass a variable from the `Foo` module on process 1 to Main on workers
passobj(1, workers(), [:foo]; from_mod=Foo)

答案 1 :(得分:10)

正如大家都知道的那样,我将这些想法放在一个ParallelDataTransfer.jl包中。所以你只需要做

using ParallelDataTransfer

(安装后)以使用此处答案中提到的功能。为什么?这些功能非常有用!我添加了一些测试,一些新的宏,并稍微更新了它们(它们传递到v0.5,在v0.4.x上失败)。随意提出拉动请求来编辑这些并添加更多。

答案 2 :(得分:9)

使用@eval @everywhere...并转义局部变量。像这样:

julia> a=collect(1:3)
3-element Array{Int64,1}:
  1
  2
  3

julia> addprocs(1)
1-element Array{Int64,1}:
 2

julia> @eval @everywhere a=$a

julia> @fetchfrom 2 a
3-element Array{Int64,1}:
 1
 2
 3

答案 3 :(得分:2)

要补充@ spencerlyon2的答案,这里有一些宏:

function sendtosimple(p::Int, nm, val)
    ref = @spawnat(p, eval(Main, Expr(:(=), nm, val)))
end 

macro sendto(p, nm, val)
    return :( sendtosimple($p, $nm, $val) )
end

macro broadcast(nm, val)
    quote
    @sync for p in workers()
        @async sendtosimple(p, $nm, $val)
    end
    end
end

@spawnat宏将值绑定到特定进程上的符号

julia> @sendto 2 :bip pi/3
RemoteRef{Channel{Any}}(9,1,5340)

julia> @fetchfrom 2 bip
1.0471975511965976

@broadcast宏将值绑定到除1之外的所有进程中的符号(正如我发现的那样,使用名称复制来自进程1的版本的未来表达式)

julia> @broadcast :bozo 5

julia> @fetchfrom 2 bozo
5

julia> bozo
ERROR: UndefVarError: bozo not defined

julia> bozo = 3             #these three lines are why I exclude pid 1
3

julia> @fetchfrom 7 bozo
3

julia> @fetchfrom 7 Main.bozo
5