2010-06-16 11 views
9

Ho un programma Ruby che carica due file yaml molto grandi, quindi posso ottenere un po 'di accelerazione sfruttando i core multipli mediante la forking di alcuni processi. Ho provato a cercare, ma ho difficoltà a capire come, o anche se, posso condividere variabili in diversi processi.Variabile condivisa tra i processi Ruby

Il codice seguente è quello attualmente ho:

@proteins = "" 
@decoyProteins = "" 

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

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

p @proteins["LVDK"] 

P display nil però perché della forcella.

Quindi è possibile che i processi biforcati condividano le variabili? E se sì, come?

+0

Sei sicuro che sia YAML a prendersi il tempo? Se è così, hai provato a caricarlo con Psych piuttosto che con Syck? –

risposta

13

Un problema è necessario utilizzare Process.wait per attendere il completamento dei processi fork. L'altro è che non puoi fare la comunicazione interprocesso attraverso le variabili. Per vedere questo:

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

Un modo per farlo comunicazione tra processi sta usando un tubo (IO::pipe). Aprilo prima di forchetta, quindi fai in modo che ogni lato della forcella chiuda un'estremità del tubo.

Da 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> 

Se si desidera condividere variabili, utilizzare le discussioni:

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

Tuttavia, non sono sicuro se filettatura ti porterà alcun guadagno quando sei IO limite.

+0

Dove va il simbolo ': hash', quando scrivi' p [: one, @one,: hash, @hash] # => [: one, 1, {: one => 1}] '? – Jeriko

+0

... invisibile a causa della scarsa trascrizione? :) risolto, thx – rampion

+0

Come condividere i dati tra il processo che esegue gli inizializzatori di Rails e un processo che esegue richieste HTTP? Tutti loro sono generati da Phusion Passenger senza la mia interferenza. – Paul

0

È possibile condividere le variabili tra i processi; DRuby è probabilmente il modo più basso barriera per entrare per farlo.

+0

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

0

Probabilmente si desidera utilizzare un thread anziché un fork se si desidera condividere i dati.

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

Oh, e se si vuole veramente sfruttare le discussioni si vorrà utilizzare JRuby. In [c] Ruby 1.9 puoi sempre dare un'occhiata alle fibre. Non li ho guardati però, non so se è una soluzione per te.

+1

I thread non sono quello che voglio perché non lo fa approfittare dei nuclei multipli. Ho già provato le discussioni, e in realtà è stato più lento. –

1

Cod è destinato a Inter Process Communication e consente di inviare facilmente i dati tra i processi biforcati.

Problemi correlati