Julia 并行编程 - 使现有功能对所有工作人员可用

Julia parallel programming - Making existing function available to all workers

我遇到了以下问题:

我有一个名为 TrainModel 的函数,它 运行 在单个线程上运行了很长时间。当它完成计算时,它returns一个函数作为输出参数,我们称它为f。当我查询这个 f 的类型时,Julia returns:

(generic function with 1 method)

(我不确定这最后一条信息对任何阅读本文的人是否有用)

现在,在第二步中,我需要对一个非常大的值数组应用函数 f。这是一个我想并行化的步骤。使用多个进程启动 Julia,例如

julia -p 4

理想情况下,我会使用:

pmap(f, my_values)

或者也许:

aux = @parallel (hcat) for ii=1:100000000
        f(my_values[ii])
      end

不幸的是,这不起作用。朱莉娅抱怨工人不知道函数 f,即我收到一条消息:

ERROR: function f not defined on process 2

如何让函数 f 对所有工作人员可用?显然,"dirty" 解决方案是 运行 耗时的函数 TrainModel 在所有 worker 上,可能像这样:

@everywhere f = TrainModel( ... )

但是当我想要的只是结果 f 对所有工人可用时,这将是对 cpu 的浪费。

虽然我搜索了类似问题的帖子,但到目前为止我找不到答案...

提前致谢! 最好的,

N.

return 函数的方法看起来很优雅,但不幸的是,与 JavaScript 不同,Julia 在创建函数时不会解析所有变量。 从技术上讲,您的训练函数可以生成函数的源代码,其中包含所有训练参数的字面值。然后将其传递给每个工作进程,这些工作进程可以在其环境中将其解析为可调用函数。

我建议 return 一个数据结构,其中包含生成训练函数的所有信息:ANN 的权重、支持向量、决策规则...... 在工作进程上定义 "trained" 函数,以便它将使用经过训练的参数。无论如何,您可能希望能够将训练结果保存到磁盘,以便您可以轻松地重新生成您的计算。

有一个基于 PTools.jl 包 (https://github.com/amitmurthy/PTools.jl) 的仅限 Unix 的解决方案。

它依赖于通过分叉而不是 Julia 内置机制的并行性。分叉进程是在与主进程相同的工作空间中生成的,因此所有函数和变量都可以直接供工作人员使用。

这个类似于R并行包中的Fork集群,所以可以作为mclapply函数使用。

感兴趣的函数是 pfork(n::Integer, f::Function, args...) 并且与 R 中的 mclapply 的一个显着区别是函数 f 必须将函数的索引作为第一个参数工人。

一个例子:

Pkg.add("PTools")
Pkg.checkout("PTools") #to get the last version, else the package does not build at the time of writing

using PTools
f(workid,x) = x[workid] + 1
pfork(3, f, [1,2,3,4,5]) #Only the three first elements of the array will be computed

3-element Array{Any,1}:  
 2  
 3  
 4  

我希望建立一个pfork的接口,这样函数的第一个参数就不需要是worker的索引,但暂时可以用来解决问题