Quali sono le mie opzioni per eseguire codice altamente ottimizzato sul BEAM?

3

Ho un piccolo modulo Elixir che occupa quasi tutto il tempo di esecuzione del mio programma. Mi piacerebbe ottimizzarlo Sembra che occorra circa 15 volte tanto quanto la stessa implementazione in C, quindi ci dovrebbe essere un margine da cui prendere. Il passo naturale sembra scrivere assembly BEAM per questo modulo, ma non sembra troppo amichevole. IIRC, il codice byte BEAM cambia tra le versioni, ed è per lo più non documentato. Tuttavia, sembra che ci siano un sacco di istruzioni extra nel bytecode generato.

Quali sono le mie opzioni per l'ottimizzazione di questa piccola parte? Riscrivendolo e il modulo che lo usa in un altro linguaggio e lo chiama esternamente potrebbe funzionare, ma sembra molto lavoro. Scrivere bytecode che non funzionerà dopo la prossima release sembra anche una cattiva idea.

    
posta Filip Haglund 10.09.2016 - 19:59
fonte

2 risposte

4

Non ne so molto di BEAM, quindi prendi tutto ciò che dico con una palata di sale.

Potresti provare a utilizzare HiPE , il compilatore del codice nativo BEAM. Da quello che ho capito, a differenza della maggior parte delle altre macchine virtuali, BEAM non compila automaticamente il codice caldo, ma è necessario compilare manualmente il codice. Da quanto ho sentito, HiPE offre un aumento delle prestazioni del 20%.

Potresti provare a utilizzare ErLLVM , un backend di generazione di codice sperimentale per HiPE che utilizza l'infrastruttura del compilatore LLVM. Secondo quanto riferito, in questo momento è leggermente più lento di HiPE (ma più veloce dell'interpretazione di BEAM) al momento, ma le informazioni che ho letto erano piuttosto vecchie, quindi ora potrebbe essere migliorato. Inoltre, c'è sempre la possibilità, che il tuo codice capiti di colpire un punto debole per ErLLVM. E sia LLVM che ErLLVM continuano a essere migliorati. L'ottimizzatore di LLVM dovrebbe essere in grado di rimediare al codice BEAM non ottimale che hai citato.

La tua prossima opzione è Erjang , un'implementazione di BEAM sulla piattaforma Java. Erjang è a circa due volte più veloce di BEAM, tuttavia, mi aspetto che il divario sia molto più grande per il codice ad alta intensità di calcolo. Erjang ha un profilo di performance leggermente diverso rispetto a BEAM: il throughput è significativamente più alto (2x). Le prestazioni di trasmissione dei messaggi sono alla pari con BEAM, ma iniziano leggermente più lentamente, ma una volta che le JIT, profilazione e ottimizzazioni dinamiche hanno dato il via, superano effettivamente BEAM. Le pause della raccolta dei dati inutili possono essere meno prevedibili: BEAM utilizza un heap per processo, Erjang utilizza un singolo heap per tutti i processi. Se GC inizia a diventare un problema, puoi provare a passare a Azul Zing JVM con C4 (Collector di compattazione simultanea continua) o variante in tempo reale del IBM J9 JVM con il Metronome Garbage Collector.

Anche se Erjang non soddisfa le tue esigenze in termini di prestazioni, potresti comunque eseguire l'app su Erjang e sostituire il modulo incriminato con uno scritto in Scala , Kotlin , Ceylon , Clojure , Java, ecc. I batti devono scrivere assemblaggio BEAM a mano, certamente.

Oppure puoi rimanere su BEAM e sostituire la funzione lenta con un NIF , che non ha da scrivere in C, potresti anche scriverlo in Haskell (che ti permetterà di mantenere la funzionalità dell'elisir), Go (che consente di mantenere un modello di concorrenza in qualche modo simile), Rust , OCaml , D o C ++.

    
risposta data 11.09.2016 - 21:35
fonte
0

Il fascio di assi probabilmente non è il modo per andare qui. Vorrei iniziare analizzando molto attentamente il codice in questione per vedere se ci sono alcuni miglioramenti evidenti che possono essere apportati. È possibile che tu abbia un problema con qualcosa che richiede una quantità di tempo non lineare.

Per quanto riguarda la riscrittura dell'opzione, una cosa da tenere a mente è come funzionerà sotto carico? Il codice Erlang / Elixir andrà abbastanza bene quando ne hai migliaia di copie in esecuzione, il codice in altre lingue funzionerà diversamente.

Trovo che uno dei problemi con cui le persone si spostano in faccia a Erlang sia l'idea che la velocità di un singolo processo sia più importante del throughput in condizioni concomitanti (nel mondo reale).

    
risposta data 03.07.2017 - 13:02
fonte

Leggi altre domande sui tag