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的索引,但暂时可以用来解决问题
我遇到了以下问题:
我有一个名为 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的索引,但暂时可以用来解决问题