我遇到了以下问题:
我有一个名为 TrainModel 的函数,它在单个线程上运行很长时间。当它完成计算时,它返回一个函数作为输出参数,我们称之为 f 。当我查询此 f 的类型时,Julia会返回:
(1种方法的通用功能)
(我不确定这最后一条信息是否对阅读此内容的人有用)
现在,在第二步中,我需要在非常大的值数组上应用函数 f 。这是我想要并行化的一个步骤。已经开始使用多个流程的Julia,例如
julia -p 4
理想情况下,我会使用:
pmap(f, my_values)
或者也许:
aux = @parallel (hcat) for ii=1:100000000
f(my_values[ii])
end
不幸的是,这不起作用。朱莉娅抱怨工人们不知道 f 的功能,即我得到了一个消息:
错误:过程2未定义函数f
如何为所有员工提供 f 功能?显然,一个“肮脏”的解决方案是对所有工人运行耗时的函数 TrainModel ,或许这样:
@everywhere f = TrainModel( ... )
但是当我想要的只是结果 f 可供所有工作人员使用时,这将浪费cpu。
虽然我搜索了类似问题的帖子,但到目前为止我找不到答案......
提前致谢! 最好,
<磷>氮答案 0 :(得分:3)
返回函数的方法似乎很优雅,但不幸的是,与JavaScript不同,Julia在创建函数时不解析所有变量。 从技术上讲,您的训练函数可以生成函数的源代码,其中包含所有训练参数的文字值。然后将其传递给每个工作进程,这些进程可以在其环境中将其解析为可调用函数。
我建议返回一个包含所有信息的数据结构,以产生训练过的函数:ANN的权重,支持向量,决策规则...... 在工人流程上定义“训练”的功能,以便它将使用训练的参数。您可能希望能够将训练结果保存到磁盘,以便您可以轻松地重新生成计算。
答案 1 :(得分:0)
有一个基于Unix的解决方案,基于PTools.jl包(https://github.com/amitmurthy/PTools.jl)。
它依赖于通过分叉的并行性而不是Julia内置机制。生成的fork进程与主进程具有相同的工作空间,因此所有函数和变量都可直接供工作人员使用。
这类似于R parallel包中的Fork簇,因此它可以用作mclapply函数。
感兴趣的函数是pfork(n :: Integer,f :: Function,args ...),与R中mclapply的一个显着区别是函数f必须将第一个参数作为worker的索引。 / p>
一个例子:
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的索引,但暂时可以用它来解决问题