我正在尝试将一个数组传递给一个函数,并且并行地对着数组的每个成员运行该函数,而不是迭代成员。完成此任务的最佳方法是什么?我成功使用了process.spawn,但这需要打开一个新的shell。有什么想法吗?
谢谢!
答案 0 :(得分:0)
您可以使用Thread
(请参阅https://ruby-doc.org/core-2.4.0/Thread.html)
例如:
threads = []
your_array.each do |item|
threads << Thread.new do
# do operation on item. Each one is handled in a new thread
end
end
threads.map(&:join) # wait for all threads to finish
值得注意的是产生新线程的开销。如果您的数组非常大,那么最好一次使用 n 项目(例如使用each_cons
。请参阅https://ruby-doc.org/core-2.4.0/Enumerable.html#method-i-each_cons),并让每个线程处理一个小的批次,而不是单个项目。
答案 1 :(得分:0)
你可以成为spawnling红宝石的宝石。这为 fork (对多个进程)或线程(对多个线程)任务提供了选项。
如果你想用线程实现并行执行,那么使用(我们可以打开的数字线程受rails应用程序可用的连接限制):
threads = []
your_array.each do |item|
Spawnling.new(:method => :thread) do
#something
end
end
否则使用多个进程实现并行执行然后使用(我们可以打开的数字分叉受限于运行应用程序的服务中可用的资源):
threads = []
your_array.each do |item|
Spawnling.new(:method => :fork) do
#something
end
end
gem的文档是here
答案 2 :(得分:0)
我不会为每个数组创建一个新线程。我会为系统上的每个处理器创建一个(或者如果你想要好的话,可能会更少),然后在它们之间分配工作。
number_of_threads = 4
items_per_thread = work_items_array.length.fdiv(number_of_threads).ceil
work_items.each_slice(items_per_thread) do |items|
Thread.new do
items.each do |item|
process_item(item)
end
end
end
如果项目都接近同一时间执行,这种方法很有效。如果他们没有,那么你可以在一个线程在另一个线程之前完成很长时间的情况下着陆。在这种情况下,您可能希望创建一个项目队列,并让每个线程从队列中拉出一个项目来处理。您将需要一个线程安全的Queue实现,例如Ruby提供的实现。
类似的东西:
queue = Queue.new
work_items.each { |item| queue << item }
number_of_threads.times do |i|
Thread.new do
begin
while item=queue.pop(true) do
process_item(item)
end
rescue ThreadError
# thread is empty
end
end
end
这样做的另一个好处是,您可以在处理开始后将项目添加到队列中。