Ruby 并发 I/O

标签 ruby multithreading io

接着, Ruby thread limit - Also for any language

我想了解为什么我的线程不工作。 一些答案非常明确,例如:

“..使用 fork 创建 4 个子进程将利用您的 4 个核心” 这将是我的 final方法,因为线程在我的情况下似乎不起作用。

还有这个:

"..Ruby MRI 线程本身不会充分利用运行 Ruby 代码的多核 CPU。但这对您来说是否是个问题取决于线程在做什么。如果他们对同一台机器上的其他进程进行长时间运行的 I/O 调用,您将在不需要单独进程的情况下看到好处。线程和多处理作为主题可以变得相当复杂,即使是简单的事情。大多数语言会在开箱即用的简单和困难方面做出一些妥协......”

考虑到第二个,我已经从我的代码中删除了所有处理,只留下了 I/O。

这里是:

beginning_time = Time.now
img_processor.load_image(frames_dir+"/frame_0001.png")
img_processor.load_image(frames_dir+"/frame_0002.png")
end_time = Time.now
puts "Time elapsed #{(end_time - beginning_time)*1000} milliseconds"

beginning_time = Time.now
for frame_index in 1..2
    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)
    }
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"

我得到的是这个......

对于第一个非线程的情况:

Time elapsed 15561.358 milliseconds

对于第二种线程情况:

Time elapsed 15442.401 milliseconds

好的,性能提升在哪里?我错过了什么吗? 硬盘是否阻塞? 我真的需要生成进程才能在 ruby​​ 中看到真正的并行性吗?

最佳答案

Do I really need to spawn processes to see real parallelism in ruby?

是的,我想是的:

require 'timeout'
require 'digest'
require 'benchmark'

def do_stuff
  Digest::SHA256.new.digest "a" * 100_000_000
end

N = 10
Benchmark.bm(10) do |x|

  x.report("sequential") do
    N.times do
      do_stuff
    end
  end

  x.report("subprocess") do
    N.times do
      fork { do_stuff }
    end
    Process.waitall
  end

  x.report("thread") do
    threads = []
    N.times do
      threads << Thread.new { do_stuff }
    end
    threads.each(&:join)
  end

end

MRI 2.0.0 的结果:

                 user     system      total        real
sequential   3.200000   0.180000   3.380000 (  3.383322)
subprocess   0.000000   0.000000   6.600000 (  1.068517)
thread       3.290000   0.210000   3.500000 (  3.496207)

第一个 block (顺序)运行 do_stuff 4 次,一个接一个,第二个 block (子进程)在 4 个内核上运行,而第三个 block (线程)在一个内核上运行。


如果将 do_stuff 更改为:

def do_stuff
  sleep(1)
end

结果不同:

                 user     system      total        real
sequential   0.000000   0.000000   0.000000 ( 10.021893)
subprocess   0.000000   0.010000   0.080000 (  1.013693)
thread       0.000000   0.000000   0.000000 (  1.003463)

关于Ruby 并发 I/O,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17191072/

相关文章:

r - 在 R 中将前 X 行从一个文件复制到另一个文件的最快方法? (跨平台)

ruby - 方法闭包似乎在 therubyracer 中不起作用

Ruby TZInfo 和 ActiveSupport::TimeZone 无法识别大多数时区缩写

c# - Interlocked.Increment 一个整数数组

C++ 返回函数 lock_guard

java - 读取文件并将数据计数插入JTable

ruby - 如何清除 Ruby 控制台实用程序中的终端?

ruby-on-rails - rails i18n 日期问题

multithreading - 在unity3d中创建后台线程

java - 扫描仪在使用 next() 或 nextFoo() 后跳过 nextLine()?