在此之后, Ruby thread limit - Also for any language
我试图理解为什么我的线程无效。 一些答案非常清楚:
“..用fork创建4个子进程将利用你的4个核心” 这将是我最后的方法,因为线程在我的情况下似乎不起作用。
也是这样:
“.. 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"
我得到的就是这个...
对于第一个非线程案例:
时间已过去15561.358毫秒
对于第二个线程案例:
时间已过去15442.401毫秒
好的,性能提升在哪里?我错过了什么吗? 硬盘阻塞了吗? 我是否真的需要生成进程才能在ruby中看到真正的并行性?
答案 0 :(得分:7)
我是否真的需要生成进程才能在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)
第一个块(顺序)运行do_stuff
4次,一个接一个,第二个块(子进程)在4个核心上运行,而第三个块(线程)在1个核心上运行。
如果您将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)