2011-11-05 10 views
9

Quindi ho un array di 40000 elementi e desidero eseguire un metodo su ciascun elemento.Ruby - come si esegue un metodo su ciascun elemento dell'array su thread diversi?

Per ridurre il tempo necessario, sto pensando di eseguirlo su più thread. Forse dividere l'array in più array e girare su un thread diverso o qualcosa del genere. Ma non so come iniziare.

Dire che l'array è foo [], e il metodo da chiamare è bar(). bar() restituisce una stringa. Dopo l'esecuzione del codice, voglio essere in grado di combinare/sommare tutte le stringhe insieme in un'unica grande stringa.

C'è un modo per farlo? Ho cercato di mantenere la mia domanda il più semplice possibile, ma se vuoi maggiori informazioni, fammi sapere.

Grazie in anticipo!

risposta

1

Se ho correttamente capito, avete bisogno di qualcosa di simile a questo frammento:

foo = %w{1 2 3} # => ["1", "2", "3"] 

# in your case it would be some time-consumed operation on string 
def inc(element) 
    element.succ 
end # => nil 
inc("1") # => "2" 

threads = foo.map do |f| 
    Thread.new { inc(f) } 
end 
# => [#<Thread:0x8d28694 run>, #<Thread:0x8d28630 run>, #<Thread:0x8d28590 run>] 

threads.map { |t| t.value } # => ["2", "3", "4"] 
3

Sembra che si desidera qualcosa di simile a una funzione pmap. C'è una libreria ruby ​​chiamata peach che fornisce sia un metodo pmap che un metodo peach ("parallelo") sugli array nativi.

Con questa libreria, si può fare qualcosa di simile

require 'peach' 
[1,2,3,4].pmap{|x| f(x)} #Spawns 4 threads, => [f(1),f(2),f(3),f(4)] 
+2

Probabilmente la pena ricordare che 'a.pmap (n) {...}' può essere usato per limitarsi ai soli 'n' discussioni, il computer di Gbert90 sarebbe probabilmente arrabbiarsi con lui se ha provato a lanciare i thread 40k. –

+0

Ho provato questo, ma non ha funzionato per un grande array. C'è qualche articolo/libro che può aiutare con questo? – Gbert90

+0

Quanto è grande il tuo array? Hai provato a limitare il numero di thread come suggerito nel commento sopra con 'a.pmap (n) {...}'? Assicurati solo di n <= # di cpu nel tuo sistema. – drsnyder

3

Ci sono molti modi per raggiungere la concorrenza, e l'utilizzo di fili è un modo. Tuttavia, le migliori prestazioni dipendono dal tempo di esecuzione di Ruby che si sceglie.

Ad esempio, un modo semplice per il multithread è la libreria "peach" (parallela) http://peach.rubyforge.org/. Tuttavia, questo funziona meglio su JRuby, che usa i thread nativi.

Per il runtime MRI è possibile utilizzare più processi come DRb o un bus di messaggi come RabbitMQ.

Per una grande interessante resoconto sulle molte opzioni, vedi questo post: http://merbist.com/2011/02/22/concurrency-in-ruby-explained/

0

Un'altra opzione è quella di utilizzare Eventmachine, che consente di eseguire 'pseudo parallela' su un singolo thread. Vedere EM::Iterator - ad esempio:

ret = nil 

EM.run do 

    # run 10 at a time; you can set the concurrency level to whatever you want 
    # but processing will slow down depending on how costly your bar method is 

    EM::Iterator.new(foo, 10).map( 
    proc{|item, iter| iter.return(item.bar)}, 
    proc{|results| ret = results.join; EM.stop} 
) 

end 
Problemi correlati