Ruby的Parallel gem似乎非常强大,但我在使用它来构建集合时遇到了麻烦。
采用以下示例,将进程设置为0:
[174] pry(main)> @array = []
=> []
[175] pry(main)> Parallel.each(1..10, :in_processes=>0) {|x| @array.push(Random.rand(10))}
=> 1..10
[176] pry(main)> @array
=> [7, 3, 5, 6, 1, 5, 4, 4, 5, 1]
但是当我们将流程设置为2时:
[177] pry(main)> @array = []
=> []
[178] pry(main)> Parallel.each(1..10, :in_processes=>2) {|x| @array.push(Random.rand(10))}
=> 1..10
[179] pry(main)> @array
=> []
显然这甚至没有接近构建随机值数组的最佳方法,我想要的是,当有多个进程时,循环结束后附加到@array的值不存在。这是一个范围问题,还是我误解了叉子是如何工作的?
答案 0 :(得分:6)
并行的默认模式通过分支您的流程并在子流程中完成工作(这是IMO,一个巨大的黑客)而在幕后工作。子进程不会对父进程的内存具有写访问权限;儿童所做的更改不会持续存在于父母身上。
您只能通过gem的工具与您的父流程进行通信,这些工具可以捕获孩子的返回值。 Parallel.map
提供了一种机制,通过该机制,传入的数据在父节点封送,然后在子节点上解组,处理,然后结果被封送并传递回父节点,并收集到结果数组中。当分叉的孩子去世时,任何过去的东西都会被“扔掉”。
考虑使用线程(并正确地同步对共享变量的访问)。如果您需要多核并发(即,您正在进行未在IO上阻止的并行工作),您应该考虑JRuby,它没有GIL并且可以本地并行执行多个Ruby线程。