Prestazioni delle librerie matematiche di matrice Java? [chiuso]


151

Stiamo calcolando qualcosa il cui runtime è vincolato da operazioni a matrice. (Alcuni dettagli di seguito, se interessati). Questa esperienza ha posto la seguente domanda:

La gente ha esperienza con le prestazioni delle librerie Java per la matematica a matrice (ad esempio, moltiplicare, inverso, ecc.)? Per esempio:

Ho cercato e non ho trovato nulla.


Dettagli del nostro confronto di velocità:

Stiamo utilizzando Intel FORTRAN (ifort (IFORT) 10.1 20070913). Lo abbiamo reimplementato in Java (1.6) usando le operazioni di matrice matematica 1.2 di comuni di Apache e accetta tutte le sue cifre di precisione. (Abbiamo motivi per volerlo in Java.) (Java raddoppia, Fortran reale * 8). Fortran: 6 minuti, Java 33 minuti, stessa macchina. La profilazione di jvisualm mostra molto tempo trascorso in RealMatrixImpl. {getEntry, isValidCoordinate} (che sembra essere sparito in Apache inediti in comune 2.0, ma 2.0 non è più veloce). Fortran sta usando le routine Atlas BLAS (dpotrf, ecc.).

Ovviamente questo potrebbe dipendere dal nostro codice in ogni lingua, ma crediamo che la maggior parte delle volte sia in operazioni con matrici equivalenti.

In molti altri calcoli che non coinvolgono le librerie, Java non è stato molto più lento e talvolta molto più veloce.


Le complicate operazioni matematiche con la matrice sono almeno O (n ^ 3) ... peggio ancora peggio, suppongo che potresti
cronometrare

2
Perché hai bisogno di inversioni? Per quasi tutte le applicazioni, non è necessario l'inverso reale. Il calcolo dell'inverso è una cattiva idea a causa di problemi di stabilità.
Ying Xiao,

1
@Calyth: Sì, potremmo cronometrare. Mi chiedevo se gli altri lo avessero già fatto. @Ying Xiao: Sì, le inversioni devono essere evitate. Tuttavia, questo calcolo sembra molto semplice usarlo. Vedi en.wikipedia.org/wiki/… .
dfrankow,

2
@Calyth Questo è sbagliato, ci sono metodi più efficienti di O (n ^ 3) usando un approccio di divisione e conquista.
Starblue,

1
Le prestazioni native più veloci provengono da JCublas. Se hai bisogno di un'algebra lineare veloce, hai bisogno di GPU. JOCL con clMath potrebbe anche funzionare ed essere portabile su CPU (e persino multipiattaforma senza ricompilazione), ma non l'ho provato.
Aleksandr Dubinsky,

Risposte:


98

Solo per aggiungere i miei 2 centesimi. Ho confrontato alcune di queste librerie. Ho tentato di moltiplicare una matrice di 3000 per 3000 di doppie con se stessa. I risultati sono i seguenti.

Utilizzando ATLAS multithread con C / C ++, Octave, Python e R, il tempo impiegato è stato di circa 4 secondi.

Usando Jama con Java, il tempo impiegato è stato di 50 secondi.

Usando Colt e Parallel Colt con Java, il tempo impiegato è stato di 150 secondi!

Utilizzando JBLAS con Java, il tempo impiegato è stato di nuovo circa 4 secondi poiché JBLAS utilizza ATLAS multithread.

Quindi per me era chiaro che le librerie Java non funzionavano troppo bene. Tuttavia, se qualcuno deve programmare in Java, l'opzione migliore è JBLAS. Jama, Colt e Parallel Colt non sono veloci.


3
Immagino che tu stia usando una macchina multicore, quindi questi risultati sono fortemente influenzati dal fatto che la libreria usi o meno multicore? Per alcuni scopi, ad esempio quando si sta parallelizzando usando mpi o hadoop ecc., Il momento importante è in realtà il tempo singlecore , poiché l'implementazione di mpi / hadoop si occupa di parallelizzare le cose. (Almeno, per me il jblas era circa 2,5 più veloce del jama, non 10 volte più veloce del jama come hai ottenuto.)
Hugh Perkins,

17
Ho appena rilasciato la versione 1.0 di netlib-java ... le prestazioni sono alla pari (e talvolta superano) il codice Fortran e possono utilizzare nativi ottimizzati per la macchina senza alcuna modifica al codice utente. Consideralo quando cerchi librerie di algebra lineare di basso livello. Mantengo anche MTJ , che utilizza netlib-java. A Scala, usa Breeze (anche alimentato da netlib-java)
fommil

4
Usando ND4j e Java - il mio laptop relativamente vecchio completa la moltiplicazione suggerita entro 219 millis. Mentre python + numpy lo completa entro 349 millis
bennyl il

2
E solo per aggiungere il mio ultimo commento sull'utilizzo di nd4j, ho usato la piattaforma nativa come backend, se uso la piattaforma cuda ci vogliono circa 1 millisecondo
bennyl,

Hai pubblicato il tuo codice per benchmark da qualche parte?
bruziuz,

108

Sono l'autore di Java Matrix Benchmark ( JMatBench ) e darò i miei pensieri su questa discussione.

Esistono differenze significative tra le librerie Java e, sebbene non vi sia un chiaro vincitore nell'intera gamma di operazioni, ci sono alcuni leader chiari, come si può vedere negli ultimi risultati delle prestazioni (ottobre 2013).

Se stai lavorando con matrici "grandi" e puoi utilizzare librerie native, il chiaro vincitore (circa 3,5 volte più veloce) è MTJ con netlib ottimizzato per il sistema . Se hai bisogno di una soluzione Java pura, allora MTJ , OjAlgo , EJML e Parallel Colt sono buone scelte. Per le piccole matrici EJML è il chiaro vincitore.

Le librerie che non ho menzionato hanno mostrato significativi problemi di prestazioni o mancavano funzionalità chiave.


6
Ho pensato di menzionare che il tuo benchmark è davvero utile! Grazie per averci dedicato del tempo.
hohonuuli,

1
JBLAS sembra supportare SVD dal settembre '13: mikiobraun.github.io/jblas/javadoc/org/jblas/…
Leopd,

ottimo lavoro, grazie mille.
webpat,

C'è un elenco da qualche parte delle librerie che hai valutato ma per cui non hai pubblicato i risultati e i motivi di ciascuna?
Kevin Krumwiede,

1
MTJ sembra abbandonato: il repository è archiviato e l'ultimo commit è stato nel 2016.
Danila Piatov

51

Sono l'autore principale di jblas e volevo sottolineare che ho rilasciato la versione 1.0 alla fine di dicembre 2009. Ho lavorato molto sulla confezione, il che significa che ora puoi semplicemente scaricare un "vaso grosso" con le librerie ATLAS e JNI per Windows, Linux, Mac OS X, 32 e 64 bit (tranne Windows). In questo modo otterrai prestazioni native semplicemente aggiungendo il file jar al tuo percorso di classe. Dai un'occhiata a http://jblas.org !


2
ispirato dal tuo lavoro, ho fatto una cosa simile in netlib-java ;-)
fommil

2
Ahah , anche io, per Jeigen :-)
Hugh Perkins,

JogAmp fa lo stesso, vedi jogamp-fat.jar. Buona idea :)
gouessej

8

Non posso davvero commentare librerie specifiche, ma in linea di principio ci sono poche ragioni per rallentare tali operazioni in Java. L'hotspot generalmente fa il genere di cose che ti aspetteresti che faccia un compilatore: compila le operazioni matematiche di base sulle variabili Java in corrispondenti istruzioni macchina (usa istruzioni SSE, ma solo una per operazione); gli accessi agli elementi di un array vengono compilati per utilizzare le istruzioni MOV "raw" come previsto; prende decisioni su come allocare le variabili ai registri quando può; riordina le istruzioni per sfruttare l'architettura del processore ... Una possibile eccezione è che, come ho già detto, Hotspot eseguirà una sola operazione per istruzione SSE; in linea di principio potresti avere una libreria di matrici fantasticamente ottimizzata che ha eseguito più operazioni per istruzione, anche se non non so se, per esempio, la tua particolare libreria FORTRAN lo fa o se esiste una libreria del genere. In tal caso, attualmente non c'è modo per Java (o almeno, Hotspot) di competere con quello (anche se ovviamente potresti scrivere la tua libreria nativa con quelle ottimizzazioni da chiamare da Java).

Cosa significa tutto ciò? Bene:

  • in linea di principio, vale la pena cercare una biblioteca dalle prestazioni migliori, anche se sfortunatamente non posso consigliarne una
  • se le prestazioni sono davvero cruciali per te, prenderei in considerazione la semplice codifica delle tue operazioni con le matrici, perché potresti quindi essere in grado di eseguire determinate ottimizzazioni che una libreria in genere non può o che una determinata libreria che stai utilizzando non ha (se hai un macchina multiprocessore, scopri se la libreria è effettivamente multithread)

Un ostacolo alle operazioni con la matrice sono spesso problemi di localizzazione dei dati che sorgono quando è necessario attraversare riga per riga e colonna per colonna, ad esempio nella moltiplicazione di matrice, poiché è necessario archiviare i dati in un ordine che ottimizzi l'uno o l'altro. Ma se scrivi a mano il codice, a volte puoi combinare operazioni per ottimizzare la localizzazione dei dati (ad esempio se stai moltiplicando una matrice per la sua trasformazione, puoi trasformare un attraversamento di colonne in un attraversamento di riga se scrivi una funzione dedicata invece di combinare due funzioni di libreria). Come al solito nella vita, una libreria ti darà prestazioni non ottimali in cambio di uno sviluppo più veloce; devi decidere quanto sia importante per te la performance.


8

Ho appena confrontato Apache Commons Math con jlapack.

Test: decomposizione del valore singolare di una matrice casuale 1024x1024.

Macchina: CPU Intel (R) Core (TM) 2 Duo E6750 a 2,66 GHz, Linux x64

Codice di ottava: A = rand (1024); tic [U, S, V] = SVD (A); toc

tempo di esecuzione dei risultati
-------------------------------------------------- -------
Ottava 36,34 sec

JDK 1.7u2 64 bit
    jlapack dgesvd 37.78 sec
    apache commons matematica SVD 42.24 sec


JDK 1.6u30 64 bit
    jlapack dgesvd 48,68 sec
    apache commons matematica SVD 50,59 sec

Routine native
Lapack * invocato da C: 37,64 sec
Intel MKL 6,89 sec (!)

La mia conclusione è che jlapack chiamato da JDK 1.7 è molto vicino alle prestazioni binarie native di Lapack. Ho usato la libreria binaria lapack fornita con Linux Distro e ho invocato la routine dgesvd per ottenere anche le matrici U, S e VT. Tutti i test sono stati eseguiti usando la doppia precisione esattamente sulla stessa matrice per ogni corsa (tranne Octave).

Disclaimer - Non sono un esperto di algebra lineare, non affiliato a nessuna delle librerie sopra e questo non è un punto di riferimento rigoroso. È un test "fatto in casa", poiché ero interessato a confrontare l'aumento delle prestazioni di JDK da 1,7 a 1,6, nonché i comuni SVD di matematica con jlapack.


8

Jeigen https://github.com/hughperkins/jeigen

  • avvolge la libreria Eigen C ++ http://eigen.tuxfamily.org , che è una delle librerie C ++ gratuite più veloci disponibili
  • sintassi relativamente concisa, ad es. 'mmul', 'sub'
  • gestisce matrici sia dense che sparse

Un test rapido, moltiplicando due matrici dense, ovvero:

import static jeigen.MatrixUtil. *;

int K = 100;
int N = 100000;
DenseMatrix A = rand(N, K);
DenseMatrix B = rand(K, N);
Timer timer = new Timer();
DenseMatrix C = B.mmul(A);
timer.printTimeCheckMilliseconds();

risultati:

Jama: 4090 ms
Jblas: 1594 ms
Ojalgo: 2381 ms (using two threads)
Jeigen: 2514 ms
  • Rispetto al jama, tutto è più veloce :-P
  • Rispetto ai jblas, Jeigen non è altrettanto veloce, ma gestisce matrici sparse.
  • Rispetto all'ojalgo, Jeigen impiega circa la stessa quantità di tempo trascorso, ma utilizzando solo un core, quindi Jeigen utilizza metà della CPU totale. Jeigen ha una sintassi terser, cioè 'mmul' contro 'multiplyRight'

Jeigen è fantastico! Di recente ho implementato Eigen in Java usando JNI e una DLL per risolvere matrici sparse molto grandi. La mia versione con la DLL è oltre 20 più veloce del colt parallelo per i miei test (oltre 8000 matrici di 8000x8000). Vorrei sapere di Jeigen!
Bosone Z,

6

C'è un benchmark di vari pacchetti matrice disponibili in java su http://code.google.com/p/java-matrix-benchmark/ per alcune diverse configurazioni hardware. Ma non è un sostituto per fare il tuo benchmark.

Le prestazioni varieranno con il tipo di hardware che hai (CPU, core, memoria, cache L1-3, velocità del bus), la dimensione delle matrici e gli algoritmi che intendi utilizzare. Diverse librerie hanno diversi punti di vista sulla concorrenza per algoritmi diversi, quindi non esiste una risposta singola. Potresti anche scoprire che l'overhead della traduzione nel modulo previsto da una libreria nativa nega il vantaggio in termini di prestazioni per il tuo caso d'uso (alcune delle librerie Java hanno opzioni più flessibili per quanto riguarda l'archiviazione delle matrici, che possono essere utilizzate per ulteriori ottimizzazioni delle prestazioni).

In genere, tuttavia, JAMA, Jampack e COLT stanno invecchiando e non rappresentano lo stato delle prestazioni correnti disponibili in Java per l'algebra lineare. Le librerie più moderne fanno un uso più efficace di più core e cache della CPU. JAMA era un'implementazione di riferimento e praticamente implementa algoritmi di libri di testo con scarso riguardo alle prestazioni. COLT e IBM Ninja sono state le prime librerie Java a dimostrare che le prestazioni erano possibili in Java, anche se erano in ritardo del 50% rispetto alle librerie native.


4

Sono l'autore della libreria la4j (Linear Algebra per Java) ed ecco il mio punto. Ho lavorato su la4j per 3 anni (l'ultima versione è 0.4.0 [01 giu 2013]) e solo ora posso iniziare a fare analisi delle prestazioni e ottimizzazioni poiché ho appena coperto il minimo richiesto funzionale. Quindi, la4j non è veloce come volevo, ma sto spendendo un sacco di tempo per cambiarlo.

Attualmente sto eseguendo il porting della nuova versione di la4j sulla piattaforma JMatBench . Spero che la nuova versione mostrerà prestazioni migliori rispetto alla precedente poiché ci sono diversi miglioramenti che ho apportato in la4j come un formato di matrice interno molto più veloce, accessori non sicuri e algoritmo di blocco rapido per le moltiplicazioni di matrice.


1
No - la4j è davvero non competitivo. Vedi code.google.com/p/java-matrix-benchmark
Christopher Manning

È cambiato molto. Ho rilasciato due versioni della libreria dalla tua risposta. La versione corrente è 0.4.0. E vola solo.
Vladimir Kostyukov,

3

Il codice Linalg che si basa fortemente su Pentiums e sulle capacità di elaborazione vettoriale dei processori successivi (a partire dalle estensioni MMX, come LAPACK e ora Atlas BLAS) non è "ottimizzato fantasticamente", ma semplicemente standard di settore. Per replicare quella prestazione in Java avrai bisogno di librerie native. Ho avuto lo stesso problema di prestazioni che descrivi (principalmente, per essere in grado di calcolare le decomposizioni di Choleski) e non ho trovato nulla di veramente efficace: Jama è puro Java, dal momento che dovrebbe essere solo un modello e un kit di riferimento che gli implementatori devono seguire. .. che non è mai successo. Sai che i comuni matematici di Apache ... Per quanto riguarda COLT, devo ancora provarlo, ma sembra fare molto affidamento sui miglioramenti di Ninja, molti dei quali sono stati raggiunti costruendo un compilatore Java ad hoc, quindi dubito che sarà di aiuto. A quel punto, penso che "


Buon punto! Un progetto in fase alfa con involucri JNI per Atlas: jblas.org . Post del blog dell'autore
dfrankow

3

Abbiamo usato COLT per alcuni calcoli finanziari piuttosto grandi e ne siamo rimasti molto soddisfatti. Nel nostro codice fortemente profilato non abbiamo quasi mai dovuto sostituire un'implementazione COLT con una nostra.

Nei loro test (ovviamente non indipendenti) penso che sostengano entro un fattore 2 delle routine di assemblaggio Intel ottimizzate a mano. Il trucco per usarlo bene è assicurarsi di comprendere la loro filosofia di progettazione ed evitare l'allocazione di oggetti estranei.


3

Hai dato un'occhiata alla libreria Intel Math Kernel ? Sostiene di sovraperformare anche ATLAS . MKL può essere utilizzato in Java tramite wrapper JNI.


2
Abbiamo quello. a) Le sue licenze sono più restrittive di Atlas (quindi non possiamo usare tutti i nostri computer); b) non è Java (e come ho detto abbiamo motivi per voler essere in Java).
dfrankow,

cioè, questa non è una risposta alla mia domanda sulle librerie Java (ma non ho la reputazione di sottovalutarlo).
dfrankow,

@dfrankow: ho aggiornato la mia risposta per rispondere alle tue preoccupazioni sull'utilizzo in Java.
Zach Scrivena,

1
+1, Se è la velocità che stai cercando, questa sembra essere la strada da percorrere
Gab Royer

2
L'ultimo collegamento è interrotto.
gouessej,


2

Potresti voler dare un'occhiata al progetto jblas . È una libreria Java relativamente nuova che utilizza BLAS, LAPACK e ATLAS per operazioni a matrice ad alte prestazioni.

Lo sviluppatore ha pubblicato alcuni benchmark in cui jblas si stacca favorevolmente contro MTJ e Colt.


2

Per le applicazioni di grafica 3d l'implementazione vettoriale lwjgl.util ha superato jblas sopra menzionati di un fattore di circa 3.

Ho fatto 1 milione di moltiplicazioni di matrice di un vec4 con una matrice 4x4.

Dopo circa 18ms, jblas ha richiesto circa 60ms.

(Suppongo che l'approccio JNI non sia molto adatto per un'applicazione rapida successiva di moltiplicazioni relativamente piccole. Poiché la traduzione / mappatura può richiedere più tempo rispetto all'esecuzione effettiva della moltiplicazione.)


1

Ho scoperto che se stai creando molte matrici ad alta dimensione, puoi rendere Jama circa il 20% più veloce se lo cambi per utilizzare un array monodimensionale anziché un array bidimensionale. Questo perché Java non supporta gli array multidimensionali in modo efficiente. vale a dire. crea una matrice di array.

Colt lo fa già, ma ho scoperto che è più complicato e più potente di Jama, il che potrebbe spiegare perché le funzioni semplici sono più lente con Colt.

La risposta dipende davvero da quello che stai facendo. Jama non supporta una frazione delle cose che Colt può fare e che fanno più la differenza.



0

Esistono molte diverse librerie di algebra lineare Java disponibili gratuitamente. http://www.ujmp.org/java-matrix/benchmark/ Purtroppo questo benchmark fornisce solo informazioni sulla moltiplicazione di matrici (con il recepimento del test non consente alle diverse librerie di sfruttare le rispettive funzionalità di progettazione).

Quello che dovresti guardare è come si comportano queste librerie di algebra lineare quando viene chiesto di calcolare varie scomposizioni di matrici. http://ojalgo.org/matrix_compare.html


0

Matrix Tookits Java (MTJ) era già stato menzionato prima, ma forse vale la pena menzionarlo di nuovo per chiunque si imbattesse in questo thread. Per gli interessati, sembra che si parli anche di avere MTJ a sostituire la libreria linalg in apache commons math 2.0 , anche se non sono sicuro di come stia procedendo di recente.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.