Julia:在函数中分配数组时,函数内部的变量名称需要匹配函数外部的名称吗?

时间:2016-08-25 20:43:12

标签: parallel-processing julia symbols

我有以下Julia函数,它接受一个输入数组并将其分配给可用的worker。

function DistributeArray(IN::Array,IN_symb::Symbol;mod=Main)    # Distributes an array among workers
    dim = length(size(IN))
    size_per_worker = floor(Int,size(IN,1) / nworkers())
    StartIdx = 1
    EndIdx = size_per_worker
    for (idx, pid) in enumerate(workers())
        if idx == nworkers()
            EndIdx = size(IN,1)
        end
        if dim == 3
            @spawnat(pid, eval(mod, Expr(:(=), IN_symb, IN[StartIdx:EndIdx,:,:])))
        elseif dim == 2
            @spawnat(pid, eval(mod, Expr(:(=), IN_symb, IN[StartIdx:EndIdx,:])))
        elseif dim == 1
            @spawnat(pid, eval(mod, Expr(:(=), IN_symb, IN[StartIdx:EndIdx])))
        else 
            error("Invalid dimensions for input array.")
        end
        StartIdx = EndIdx + 1
        EndIdx = EndIdx + size_per_worker - 1
    end
end

我在其他一些函数中调用此函数来分发数组。例如,这是一个测试函数:

function test(IN::Array,IN_symb::Symbol)   
    DistributeArray(IN,IN_symb)
    @everywhere begin
        if myid() != 1
            println(size(IN))
        end
    end
end

我希望此功能可以使用' IN'在所有可用的worker中分配并分配它,然后打印分配给每个worker的大小。以下命令集(其中输入的名称与函数内使用的名称匹配)可正常工作:

addprocs(3)
IN = rand(27,33)
IN_symb = :IN
test(IN,IN_symb)

# From worker 2:    (9,33)
# From worker 3:    (8,33)
# From worker 4:    (10,33)

但是,当我更改输入的名称以使它们与函数中使用的名称不同时,我收到错误(在运行follow命令之前启动新的julia会话):

addprocs(3)
a = rand(27,33)
a_symb = :a
test(a,a_symb)

ERROR: On worker 2:
UndefVarError: IN not defined
 in eval at ./sysimg.jl:14
 in anonymous at multi.jl:1378
 in anonymous at multi.jl:907
 in run_work_thunk at multi.jl:645
 [inlined code] from multi.jl:907
 in anonymous at task.jl:63
 in remotecall_fetch at multi.jl:731
 in remotecall_fetch at multi.jl:734
 in anonymous at multi.jl:1380

...and 3 other exceptions.

 in sync_end at ./task.jl:413
 [inlined code] from multi.jl:1389
 in test at none:2

我不明白导致此错误的原因。在我看来,函数没有使用我给他们的输入?

1 个答案:

答案 0 :(得分:1)

在您的test()函数中,您正在运行println(size(IN))。因此,您正在查找名为IN的特定对象的每个进程。但是,在第二个示例中,您要命名对象a而不是IN(因为您提供的符号是:a)。您提供给DistributeArray()函数的符号定义了对象在worker上的名称,因此这是您将来用于引用这些对象的名称。

您可以通过略微修改test()功能来获得我认为您正在寻找的结果:

function test(IN::Array,IN_symb::Symbol)   
    DistributeArray(IN,IN_symb)
    for (idx, pid) in enumerate(workers())
        @spawnat pid println(size(eval(IN_symb)))
    end
end

在我看来,@spawnat有时可以更灵活一些,让您更好地指定您想要评估的表达式。