2009-11-09 25 views
6

Sono curioso delle prestazioni degli algoritmi numerici Java, ad esempio per la moltiplicazione a doppia precisione con matrice matrice, utilizzando le più recenti macchine JIT rispetto, ad esempio, a SSE C++/assembler sintonizzati a mano o controparti Fortran.Prestazioni Java in algoritmi numerici

Ho cercato sul web ma la maggior parte dei risultati proviene da quasi 10 anni fa e ho capito che Java ha progredito parecchio da allora.

Se hai esperienza con Java per applicazioni ad uso intensivo di numeri puoi condividere la tua esperienza. Inoltre, quanto bene funziona Java nei kernel dove i loop sono relativamente brevi e l'accesso alla memoria non è molto uniforme ma è ancora entro i limiti della cache L1? Se tale kernel viene eseguito più volte in successione, JVM può ottimizzarlo durante il runtime?

Grazie

+3

La tua migliore scommessa è quella di metterlo alla prova da solo, poiché il confronto con il C++ sarà difficile in quanto sarà il più veloce e qualsiasi confronto non avrà accesso alla tua particolare implementazione. –

+1

Nota per gli altri che vengono a questa pagina: questa domanda e la maggior parte delle risposte sono del 2009. JVM è molto meglio al giorno d'oggi di quanto non lo fosse una volta. – eis

+0

Si potrebbe voler guardare ND4J, che supporta matrici n-dimensionali per Java. http://nd4j.org/benchmarking.html – tremstat

risposta

-4

Java utilizza un compilatore Just in Time (JIT) per convertire il bytecode al linguaggio macchina nativo - quindi la prima volta che viene eseguito attraverso un blocco di codice sarà più lento, ma una volta che il segmento è 'riscaldato 'la performance sarà equivalente. In breve: le prestazioni numeriche sono piuttosto buone.

+1

I JIT sono buoni, ma non sono sufficienti per garantire buone prestazioni numeriche. –

0

In secondo luogo, la soluzione migliore è testarla personalmente, poiché le prestazioni variano in base a ciò che si sta facendo esattamente. Trovo difficile credere alla risposta di Shane C. Mason che le prestazioni di Java saranno le stesse di C++ o di Fortran, in quanto anche C++ e Fortran non sono paragonabili per alcuni algoritmi di calcolo scientifico.

Ho un codice di fluidodinamica computazionale che ho scritto usando C++ e lo stesso codice tradotto essenzialmente in Fortran. Non sono ancora sicuro del perché, ma la versione di Fortran è circa due volte più veloce della versione C++. Direi che con funzionalità come bounds-checking e garbage collection, Java sarebbe più lento di entrambi, ma non lo saprei fino a quando non lo avrò testato.

+0

hai usato limitare la parola chiave nel tuo codice C++? I compilatori Fortran non devono garantire che i puntatori di memoria non siano aliasati mentre i compilatori C++ devono assumere che la memoria sia di alias se non diversamente specificato. quali compilatori hai usato? Ho programmato il mio programma in C++ con l'intrinseco e il compilatore Intel è significativamente più veloce di GCC, suppongo che le istruzioni per gli ordini di Intel C++ siano migliori perché l'assemblaggio era altrimenti molto simile tranne che per l'ordine. – Anycorn

+0

Sono vagamente consapevole dei problemi di aliasing, ma non lo capisco abbastanza bene, ancora. Non ho ancora provato a restringere, sfortunatamente non ho avuto il tempo di spendere per questo. Stavo usando icpc e ifort (entrambi i compilatori Intel) su linux con -O3. Si noti che il mio punto non è che le prestazioni di C++ non possono corrispondere a fortran, ma piuttosto che è necessario confrontare le implementazioni oltre alle lingue. – notJim

+0

Fortran ha anche un modello numerico molto più rilassato del C++: per impostazione predefinita è possibile eseguire molte ottimizzazioni matematiche skanky che si ottengono solo in C/C++ con -ffast-math e simili. A volte questo non ha importanza e a volte renderà i risultati meno accurati. –

1

This è un collegamento alla pagina di shootout del linguaggio di programmazione per java vs C++, che consente di confrontare la velocità di java su diversi algoritmi di calcolo intensivo. Ti mostrerà anche qual è il codice Java più performante. Per la maggior parte, per questi pochi benchmark specifici, java ha impiegato più tempo (ma non più di 2 o 3 volte) per essere eseguito.

+0

Non ho potuto dirlo immediatamente - questo confronto trascura i tempi di riscaldamento. Java ha ancora bisogno di un _lot_ di lavoro iniziale prima di raggiungere la velocità di crociera. –

+0

vero. se vuoi scrivere un programma che si avvia, fa alcuni calcoli e poi si spegne, probabilmente non vuoi java. ma se il programma verrà eseguito per alcuni minuti, il tempo di avvio sarà solo rumore. Un'alternativa, naturalmente, è avviare un processo java e farlo funzionare come server di calcolo: ogni volta che è necessario un calcolo, basta chiamare in un'istanza già in esecuzione. –

+0

@ Thorbjørn Ravn Andersen - 1) Leggi le FAQ! 2) Si noti che i programmi vengono eseguiti per secondi e non in microsecondi! 3) Osserva le approssimazioni allo stato stazionario http://shootout.alioth.debian.org/u64q/benchmark.php?test=all&lang=javasteady&lang2=gpp&box=1 4) Leggi le FAQ! su Java http://shootout.alioth.debian.org/u64q/faq.php#dynamic – igouy

1

Questo deriva dal lato .NET delle cose, ma sono sicuro al 90% che sia anche per Java. Mentre il JIT farà qualche uso delle istruzioni SSE dove può, al momento non auto-vettorizza il tuo codice quando si tratta, ad esempio, di moltiplicazioni di matrice. C++ vettorializzato a mano usando l'intrinseco del compilatore/assemblaggio in linea sarà sicuramente più veloce qui.

0

Questo può dipendere da ciò che si sta facendo nel codice C++.

Ad esempio, stai utilizzando la GPU? Modifica Ho dimenticato di jogl, quindi Java può competere qui.

Parallelizzato tramite STM o memoria condivisa, Java non può competere. Per un collegamento parallelo sull'analisi di moltiplicazione matriciale: http://www.cs.utexas.edu/users/plapack/papers/ipps98/ipps98.html

Hai memoria sufficiente per eseguire i calcoli in memoria, quindi non sarà necessario il garbage collector, e hai perfezionato il garbage collector per prestazioni ottimali ? Quindi, Java può essere competitivo, forse.

Si sta utilizzando il multicore e il C++ è ottimizzato per sfruttare questa architettura? Quindi Java non sarà in grado di competere.

Se si utilizzano più computer collegati tra loro, Java non sarà in grado di competere.

Si sta utilizzando qualsiasi combinazione di questi, quindi dipenderà dalla particolare implementazione.

Java non è progettato per competere con un programma C++ con regolazione manuale, ma, il tempo necessario per eseguire l'ottimizzazione, stai facendo abbastanza calcoli in cui sarà importante? Java sarà in grado di fornire una velocità ragionevole, ma con meno lavoro rispetto alla messa a punto manuale, ma non molto di miglioramento rispetto alla semplice esecuzione del codice C++.

Si potrebbe voler vedere se c'è un miglioramento su Haskell o Erlang, ad esempio, sul C++, in quanto queste lingue sono meglio progettate per questo tipo di lavoro.

+0

Utilizzo della GPU? Come in, usando OpenGL? Se si utilizza JOGL, Java può competere in modo soddisfacente. –

+0

Hai ragione, ho corretto la mia risposta, ho dimenticato che puoi usare jogl per il lavoro della GPU. –

1

Uno dei punti più deboli in java è la matrice (nativa) delle operazioni. Ciò è dovuto alla natura delle matrici Java:

  • Non è possibile dichiarare una matrice come rettangolare, vale a dire. ogni riga può avere un diverso numero di colonne.

  • Una matrice tecnicamente non è una "matrice di doppi (o int, ...)", ma una serie di matrici di .... La grande differenza è che, poiché gli array sono oggetti Java, è possibile assegnare lo stesso oggetto array a più di 1 riga.

Queste due proprietà rendono impossibile per il compilatore molte ottimizzazioni di matrice standard.

È possibile ottenere prestazioni migliori utilizzando una libreria Java che emula le matrici su un singolo array lungo. Tuttavia, si ha il sovraccarico delle chiamate di metodo per tutti gli accessi.

+2

Penso che tu intenda che non puoi dichiarare un array 2D come rettangolare. Ma sembra che tu stia sostenendo che l'implementazione più letterale e diretta di una matrice in Java ha alcuni problemi. Perché questa sarebbe l'unica implementazione possibile? Se non lo è, non c'è molta dichiarazione qui sulla "natura delle matrici Java". Che dire delle librerie di matrici Java come Colt? –

+0

Le matrici non sono sempre rappresentate in questo modo. Vedi 'java.awt.image.Kernel' per un esempio di una matrice rappresentata da un array 1D – finnw

+0

Il problema con tali librerie è che tutti gli accessi alla matrice avvengono tramite metodi. Le chiamate ai metodi sono più lente dell'accesso agli array in generale e impediscono alcune ottimizzazioni del compilatore. Per esempio. 'for (int i = 0; i Carsten

1

C++ sarà sicuramente più veloce. Puoi anche avere alcune librerie ottimizzate a mano per i tuoi scopi che contengono codici di assemblaggio per ciascuna delle principali CPU là fuori. Non puoi migliorare.

Successivamente, è possibile utilizzare JNI per chiamarlo da Java, se necessario.

Java non è pensato per calcoli aritmetici ad alte prestazioni come questo. Se dipendi da questi, ti consiglio di scegliere un linguaggio corretto e di basso livello per implementarlo. Oppure, in alternativa, è possibile scrivere la parte specifica della performance in un linguaggio di basso livello, quindi collegarla a un front-end Java utilizzando JNI o ​​qualche altro metodo IPC.

0

Sono questi tipi di calcoli a cui sei interessato: Fast Fourier Transform, Jacobi Successive Over Relaxation, Monte Carlo Integration, Sparse Matrix Mult, Dense LU Matrix Factorisation?

Essi costituiscono il SciMark 2.0 composite benchmark che è possibile avviare come applet sulla macchina.

Ci sono anche ANSI C versions dei programmi e uno Intel document (pdf) on optimizing and recompiling SciMark for C++.


Allo stesso modo si potrebbe usare The Java Grande Forum Benchmark Suite e the comparison C programs.

2

Ho scritto codice numerico ragionevolmente grande e sensibile alle prestazioni in Java (scricchiolio di grandi matrici di doppi di solito).

Ho trovato Java "abbastanza buono" per i calcoli numerici veloci. Soprattutto se si considera che di solito non si è vincolati alla CPU, la latenza della memoria e la consapevolezza della cache saranno probabilmente il problema più grande per i set di dati di grandi dimensioni.

Tuttavia, è ancora possibile battere Java con codice C/C++ ottimizzato a mano che sfrutta specifiche istruzioni vettoriali ecc. O layout di memoria altamente personalizzati. Quindi per il codice molto veloce, potresti prendere in considerazione la scrittura dell'algoritmo di base in C/C++ e chiamarlo da Java usando JNI.

Personalmente, trovo che la creazione di una dipendenza da codice nativo sia di solito più problematica di quanto valga, quindi tendo ad attenermi all'approccio Java puro.