问题 Ruby进程中的共享变量


我有一个Ruby程序,可以加载两个非常大的yaml文件,所以我可以通过分离一些进程来利用多个核心来获得一些加速。我试过看,但是我无法弄清楚如何,或者即使我可以在不同的进程中共享变量。

以下代码是我目前拥有的代码:

@proteins = ""
@decoyProteins = "" 

fork do
  @proteins = YAML.load_file(database)
  exit
end

fork do
  @decoyProteins = YAML.load_file(database)
  exit
end

p @proteins["LVDK"]

P 因为叉子显示为零。

那么分叉进程可以共享变量吗?如果是这样,怎么样?


7587
2018-06-16 20:57


起源

你确定这是YAML花时间吗?如果是这样,你有没有试过加载Psych而不是Syck? - Andrew Grimm


答案:


一个问题是你需要使用 Process.wait 等待你的分叉进程完成。另一个是你不能通过变量进行进程间通信。看到这个:

@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)。在叉前打开它,然后让叉的每一边都关闭管的一端。

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>

如果要共享变量,请使用线程:

@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限制时,线程是否会给你带来任何好处。


13
2018-06-16 21:18



在哪里 :hash 符号去,当你写 p [:one, @one, :hash, @hash] #=> [ :one, 1, { :one => 1 } ]? - Jeriko
......由于转录不良而无法看见? :)修好了,thx - rampion
如何在运行Rails初始化程序的进程和运行HTTP请求的进程之间共享数据?所有这些都是由Phusion Passenger产生的,没有我的干涉。 - Paul
保罗:我不熟悉它们是如何产生的。您可能希望将其提升为完整的问题。我很想尝试命名管道,但可能有一种更简单的方法。也许DB? - rampion


鳕鱼 用于进程间通信,允许您在分叉进程之间轻松发送数据。


1
2017-10-01 13:07





可以在进程之间共享变量; DRuby可能是进入障碍的最低障碍。


0
2018-06-16 21:22



DOC: ensta.fr/~diam/ruby/online/ruby-doc-stdlib/libdoc/drb/rdoc/... - rampion


如果要共享数据,可能需要使用线程而不是fork。

http://ruby-doc.org/docs/ProgrammingRuby/html/tut_threads.html

哦,如果你真的想利用线程,你会想要使用JRuby。在[c] Ruby 1.9中你可能总是想看一下光纤。我没有看过它们,我不知道它是否适合你。


0
2018-06-16 21:24



线程不是我想要的,因为它没有利用多核。我实际上已经尝试了线程,它实际上更慢。 - Jesse Jashinsky