2012-11-12 9 views
5

Ho cercato di ottimizzare un programma di ruby ​​che è piuttosto complesso di calcoli su molti dati. Non conosco C e ho scelto Ruby (non che lo conosca bene) e sono abbastanza soddisfatto dei risultati, a parte il tempo necessario per l'esecuzione. Sono molti dati e, senza spendere soldi, mi piacerebbe sapere cosa posso fare per assicurarmi di massimizzare le mie risorse di sistema.Esecuzione del programma di ruby ​​su tutti i processori

Quando si esegue un programma Ruby di base, viene utilizzato un singolo processore? Se non ho assegnato compiti specifici a un processore, Ruby non leggerà il mio programma e caricherà magicamente ogni processore per completare il programma il più velocemente possibile? Sto assumendo no ...

Ho letto un po 'per accelerare Ruby, e in un altro thread ho letto che Ruby non supporta il vero multithreading (anche se ha detto JRuby). Ma, se dovessi "scomporre" il mio programma in due blocchi che possono essere eseguiti in istanze separate ed eseguirli in parallelo ... questi due blocchi verranno eseguiti automaticamente su due processori separati? Se avessi quattro processori e avessi aperto quattro shell e avessi eseguito quattro parti separate (1/4) del programma, sarebbe stato completato in 1/4 di tempo?

Aggiornamento

Dopo aver letto i commenti che ho deciso di dare un colpo di JRuby. Portare l'app non è stato difficile. Non ho ancora usato "pesca", ma semplicemente eseguendolo in JRuby, l'app viene eseguita in 1/4 del tempo !!! Insane. Non mi aspettavo tanto di un cambiamento. Andando a dare. Sparare un colpo ora e vedere come questo migliora le cose. Non riesco ancora a crederci.

Aggiornamento # 2

appena dato pesca una prova. Finito per radersi un altro 15% di sconto sul tempo. Quindi passare a JRuby e usare Peach è valsa la pena.

Grazie a tutti!

+0

Senza vedere il codice sorgente, indoviniamo cosa potrebbe essere fatto per velocizzare la vostra applicazione. Potrebbe essere possibile velocizzare un po 'anche se, se stai facendo alcune cose in modo duro/lento. –

risposta

4

Utilizzare JRuby e la gemma peach e non potrebbe essere più semplice. Basta sostituire uno .each con .peach e voilà, stai eseguendo in parallelo. E ci sono altre opzioni per controllare esattamente quanti thread sono generati, ecc. Ho usato questo e funziona benissimo.

ci si avvicina al n volte SpeedUp, dove n è il numero di CPU/core disponibili. Trovo che il numero ottimale di thread sia leggermente superiore al numero di CPU/core.

0

Il threading è in genere considerato uno dei punti deboli di Ruby, ma dipende più dall'implementazione di Ruby che si utilizza.

Una buona annotazione sui diversi modelli di threading è "Does ruby have real multithreading?".

Dalla mia esperienza e da ciò che ho raccolto da persone che conoscono meglio questa roba, sembra che se si sceglierà un'implementazione di Ruby, JRuby è la strada da percorrere. Tuttavia, se stai imparando Ruby potresti voler scegliere un'altra lingua come Erlang, o forse Clojure, che sono scelte popolari se vuoi usare la JVM.

0

Bello come Ruby, non è noto per la sua velocità di esecuzione. Detto questo, se, come notato nel tuo commento, puoi suddividere l'input in blocchi di uguali dimensioni dovresti essere in grado di avviare n istanze del programma, dove n è il numero di core che hai, e il SO sarà prenditi cura di usare tutti i core per te.

Nel migliore dei casi sarebbe eseguito in 1/n il tempo, ma questo tipo di cose può essere difficile da ottenere esattamente come alcune parti del sistema, come la memoria, devono essere condivise tra i processi e la contesa tra i processi possono far sì che le cose non si scalino linearmente. Se la divisione è facile da fare, farei un tentativo. Puoi anche provare a eseguire lo stesso programma due volte e vedere quanto tempo ci vuole per eseguire, se ci vuole lo stesso tempo per eseguirne uno, perché è possibile eseguire due, è probabile che siano tutti impostati, basta dividere i dati e andare per esso.

Provare probabilmente jruby e alcuni thread potrebbe aiutare, ma ciò aggiunge una buona dose di complessità. (Probabilmente sarebbe una buona scusa per conoscere il threading.)

2

Come altri hanno affermato che l'implementazione RMI di ruby ​​(quella che molti usano) non supporta i thread nativi. Quindi non è possibile dividere il lavoro tra i core della CPU avviando più thread utilizzando l'implementazione della risonanza magnetica.

Tuttavia, se il processo è legato all'IO (limitato da disco o attività di rete, ad esempio), è comunque possibile trarre vantaggio da più thread MRI.

JRuby d'altra parte supporta i thread nativi, il che significa che è possibile utilizzare i thread per dividere il lavoro tra i core della CPU.

Ma non tutto è perduto. Con la risonanza magnetica (e tutte le altre implementazioni di rubini), è ancora possibile utilizzare i processi per suddividere il lavoro.

questo può essere fatto utilizzando Process.fork per esempio come questo:

Process.fork { 
    10.times { 
    # Do some work in process 1 
    sleep 1 
    puts "Hello 1" 
    } 
} 

Process.fork { 
    10.times { 
    # Do some work in process 2 
    sleep 1 
    puts "Hello 2" 
    } 
} 

# Wait for the child processes to finish 
Process.wait 

Utilizzando fork sarà dividere il trattamento tra i core della CPU, quindi se si può vivere senza fili quindi processi separati sono un modo per farlo.

Problemi correlati