问题描述
我有一个 Ruby 程序可以加载两个非常大的 yaml 文件,因此我可以通过分叉一些进程来利用多个内核来提高速度.我试过寻找,但我无法弄清楚如何或什至无法在不同的进程中共享变量.
I have a Ruby program that loads up two very large yaml files, so I can get some speed-up by taking advantage of the multiple cores by forking off some processes. I've tried looking, but I'm having trouble figuring how, or even if, I can share variables in different processes.
以下代码是我目前拥有的:
The following code is what I currently have:
@proteins = ""
@decoyProteins = ""
fork do
@proteins = YAML.load_file(database)
exit
end
fork do
@decoyProteins = YAML.load_file(database)
exit
end
p @proteins["LVDK"]
P
因为 fork 显示 nil.
P
displays nil though because of the fork.
那么是否有可能让分叉进程共享变量?如果是这样,如何?
So is it possible to have the forked processes share the variables? And if so, how?
推荐答案
一个问题是你需要使用 Process.wait
来等待你的分叉进程完成.另一个是不能通过变量进行进程间通信.看到这个:
One problem is you need to use Process.wait
to wait for your forked processes to complete. The other is that you can't do interprocess communication through variables. To see this:
@one = nil
@two = nil
@hash = {}
pidA = fork do
sleep 1
@one = 1
@hash[:one] = 1
p [:one, @one, :hash, @hash] #=> [ :one, 1, :hash, { :one => 1 } ]
end
pidB = fork do
sleep 2
@two = 2
@hash[:two] = 2
p [:two, @two, :hash, @hash] #=> [ :two, 2, :hash, { :two => 2 } ]
end
Process.wait(pidB)
Process.wait(pidA)
p [:one, @one, :two, @two, :hash, @hash] #=> [ :one, nil, :two, nil, :hash, {} ]
进程间通信的一种方式是使用管道(IO::pipe
).在叉之前打开它,然后让叉的每一侧关闭管道的一端.
One way to do interprocess communication is using a pipe (IO::pipe
). Open it before you fork, then have each side of the fork close one end of the pipe.
来自 ri IO::pipe
:
rd, wr = IO.pipe
if fork
wr.close
puts "Parent got: <#{rd.read}>"
rd.close
Process.wait
else
rd.close
puts "Sending message to parent"
wr.write "Hi Dad"
wr.close
end
_produces:_
Sending message to parent
Parent got: <Hi Dad>
如果要共享变量,请使用线程:
If you want to share variables, use threads:
@one = nil
@two = nil
@hash = {}
threadA = Thread.fork do
sleep 1
@one = 1
@hash[:one] = 1
p [:one, @one, :hash, @hash] #=> [ :one, 1, :hash, { :one => 1 } ] # (usually)
end
threadB = Thread.fork do
sleep 2
@two = 2
@hash[:two] = 2
p [:two, @two, :hash, @hash] #=> [ :two, 2, :hash, { :one => 1, :two => 2 } ] # (usually)
end
threadA.join
threadB.join
p [:one, @one, :two, @two, :hash, @hash] #=> [ :one, 1, :two, 2, :hash, { :one => 1, :two => 2 } ]
但是,我不确定当您受到 IO 限制时线程处理是否会给您带来任何好处.
However, I'm not sure if threading will get you any gain when you're IO bound.