2010-06-16 8 views
9

Tôi có một chương trình Ruby tải hai tệp yaml rất lớn, vì vậy tôi có thể tăng tốc bằng cách tận dụng nhiều lõi bằng cách tắt một số quy trình. Tôi đã thử tìm kiếm, nhưng tôi đang gặp khó khăn trong việc tìm cách, hoặc thậm chí nếu tôi có thể chia sẻ các biến trong các quy trình khác nhau.Biến chia sẻ giữa các quá trình Ruby

Các mã sau đây là những gì tôi hiện có:

@proteins = "" 
@decoyProteins = "" 

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

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

p @proteins["LVDK"] 

P màn Nil dù vì ngã ba.

Vì vậy, có thể có các quy trình chia đôi chia sẻ các biến không? Và nếu vậy, làm thế nào?

+0

Bạn có chắc là YAML đang dành thời gian không? Nếu vậy, bạn đã thử tải nó với Psych chứ không phải là Syck? –

Trả lời

13

Một vấn đề là bạn cần sử dụng Process.wait để đợi cho quá trình chia đôi của bạn hoàn tất. Cái còn lại là bạn không thể thực hiện truyền thông interprocess thông qua các biến. Để xem điều này:

@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, {} ] 

Một cách để thực hiện liên lạc liên thông là sử dụng đường ống (IO::pipe). Mở nó trước khi bạn ngã ba, sau đó có mỗi bên của ngã ba đóng một đầu của đường ống.

Từ 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> 

Nếu bạn muốn chia sẻ các biến, đề sử dụng:

@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 } ] 

Tuy nhiên, tôi không chắc chắn nếu luồng sẽ giúp bạn có bất kỳ khoản lãi khi bạn đang IO bị ràng buộc.

+0

Biểu tượng ': băm' ở đâu, khi bạn viết' p [: một, @one,: băm, @hash] # => [: một, 1, {: một => 1}] '? – Jeriko

+0

... vô hình do phiên mã kém? :) sửa lỗi, thx – rampion

+0

Làm cách nào để chia sẻ dữ liệu giữa quá trình chạy trình khởi tạo Rails và quá trình chạy yêu cầu HTTP? Tất cả chúng được sinh ra bởi Phusion Passenger mà không có sự can thiệp của tôi. – Paul

0

Có thể chia sẻ các biến giữa các quy trình; DRuby có lẽ là cách rào cản nhập cảnh thấp nhất để làm điều đó.

+0

doc: http://www.ensta.fr/~diam/ruby/online/ruby-doc-stdlib/libdoc/drb/rdoc/classes/DRb.html – rampion

0

Bạn có thể muốn sử dụng một chuỗi thay vì một ngã ba nếu bạn muốn chia sẻ dữ liệu.

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

Oh, và nếu bạn thực sự muốn tận dụng lợi thế của đề bạn sẽ muốn sử dụng JRuby. Trong [c] Ruby 1.9 bạn có thể luôn muốn nhìn vào sợi. Tôi đã không nhìn vào họ mặc dù, tôi không biết nếu nó là một giải pháp cho bạn.

+1

Chủ đề không phải là những gì tôi muốn bởi vì nó không tận dụng lợi thế của nhiều lõi. Tôi thực sự đã thử các chủ đề rồi, và nó thực sự chậm hơn. –

1

Cod có nghĩa là cho Inter Communication Communication và sẽ cho phép bạn dễ dàng gửi dữ liệu giữa các quy trình được chia hai.