并发Rails迭代/操作

时间:2013-09-26 17:16:15

标签: ruby-on-rails ruby

通常我们逐个迭代一个数组:

a = [1, 2, 3, 4]
b = []

a.each do |x|
  b << x * 5
end

b = [5, 10, 15, 20]

如果我不关心数组中内容的顺序,但想通过同时运行乘法运算来提高迭代速度,该怎么办?例如,这样的结果是可以接受的:

b = [15, 10, 5, 20] # or
b = [5, 20, 15, 10] # or
b = [20, 15, 5, 10]

我该怎么做?

1 个答案:

答案 0 :(得分:4)

由于GIL,MRI不能实现真正的多核并行性;线程实际上并没有让您在CPU绑定任务上获得性能提升(尽管它肯定会在IO绑定任务上实现);你需要运行JRuby或Rubinius来获得CPU绑定任务的并行性,因为它们实际上可以同时在多个内核之间分配工作。

也就是说,假设您正在运行提供真正并行性的VM:

b = a.map {|x|
  Thread.new {
    Thread.current[:out] = x * 5
  }
}.map {|t| t.join; t[:out] }

(这段代码非常难看,应该根据实际用途进行重构。它还会按照创建线程的顺序返回结果,同时仍然可以并行化任务。)

这里的要点是1)在线程局部变量中传播返回值(因此您不必对共享值执行possibly-unatomic operation;如果您想这样做,则需要引入一个Mutex),以及2)在创建的每个线程上调用#join,以便我们确保创建的每个线程都已完成运行。