2

我正在尝试使用 Ruby 尽可能快地处理 1000 帧。所以我目前启动了 1000 个线程(每帧一个)。结果很糟糕。它使用大量内存并且速度很慢。我的 CPU 是这个http://ark.intel.com/products/67355/ 它说它支持 4 个线程。(我猜每个 CPU 2 个?)。因此,如果我一次启动 4 个 Ruby 线程,等到它们完成,然后再启动 4 个等,等等,将需要 250 个“步骤”来完成处理,而不是 1000 个?

编辑:我现在的代码:

beginning_time = Time.now
    limit=1
for frame_index in 1..limit
    greyscale_frames_threads << Thread.new(frame_index) { |frame_number| 
        puts "Loading Image #{frame_number}"
        img_processor.load_image(frames_dir+"/frame_%04d.png"%+frame_number)
        img_processor.greyscale_image
        img_processor.save_image_in_dir(output_dir,"frame_%04d"%+frame_number)
        puts "Greyscaled Image #{frame_number}"
    }
end

puts "Joining Threads"
greyscale_frames_threads.each { |thread| thread.join } #this blocks the main thread
end_time = Time.now
puts "Time elapsed #{(end_time - beginning_time)*1000} milliseconds"

现在对于 limit=1 这就是我得到的:

经过的时间 23504.805999999997 毫秒

现在对于 limit=2 这就是我得到的:

经过的时间 53465.676 毫秒

对于 limit=2 我期待 23504.805999999997 毫秒。

这意味着我的代码只是失败了。在这里,线程没有意义。为什么?有人可以向我解释一下吗?

4

2 回答 2

5

例如,您可以使用此类来创建线程池并安排您的工作:

class Pool
  def initialize(size)
    @size = size
    @jobs = Queue.new
    @pool = Array.new(@size) do |i|
      Thread.new do
        Thread.current[:id] = i
        catch(:exit) do
          loop do
            job, args = @jobs.pop
            job.call(*args)
          end
        end
      end
    end
  end

  def schedule(*args, &block)
    @jobs << [block, args]
  end

  def shutdown
    @size.times do
      schedule { throw :exit }
    end
    @pool.map(&:join)
  end
end

然后你可以做pool = Pool.new(32),然后安排这样的事情:

pool.schedule do 
  # do your stuff
end

所以这意味着(在这个例子中)最多有 32 个线程,每个线程都会弹出一些您安排的工作。

于 2013-06-19T10:04:21.370 回答
3

在标准的 ruby​​ 解释器中,一次只运行一个线程,因此如果您受计算限制,则添加线程无济于事。如果你搜索 GIL 或 GVL(全局解释器锁),你会发现很多关于这个主题的文章。如果您受 IO 限制,那么等待 IO 的线程将放弃控制,因此在这种情况下线程仍然有用。

C 扩展也可以放弃 GVL,因此有多个线程并行运行,但这仅在 ruby​​ 1.9.3+ 上才有可能,并且需要在编写 C 扩展时考虑到这一点。

如果计算并行性对您很重要,您可能需要查看 jruby 或 rubinius,它们都没有 GVL。两者之中,jruby更为成熟。

最后,为每个任务创建 1 个线程是浪费 - 涉及一定数量的开销,因此正常模式是拥有一个可重用的工作线程池。

于 2013-06-19T10:25:32.193 回答