2009-11-09 10 views
6

Tengo curiosidad sobre el rendimiento de los algoritmos numéricos Java, por ejemplo multiplicación de doble matriz de matrices matriciales, utilizando las últimas máquinas JIT comparadas, por ejemplo, con SSE C++/ensamblador sintonizado o contrapartes Fortran.Rendimiento de Java en algoritmos numéricos

He buscado en la web pero la mayoría de los resultados provienen de hace casi 10 años y entiendo que Java ha progresado bastante desde entonces.

Si tiene experiencia en el uso de Java para aplicaciones numéricamente intensivas puede compartir su experiencia. ¿Qué tan bien funciona Java en núcleos donde los bucles son relativamente cortos y el acceso a la memoria no es muy uniforme, pero aún dentro de los límites de la memoria caché L1? Si dicho núcleo se ejecuta varias veces seguidas, ¿puede JVM optimizarlo durante el tiempo de ejecución?

Gracias

+3

Su mejor opción es probarlo usted mismo, ya que la comparación con C++ será difícil ya que será la más rápida, y cualquier comparación no tendrá acceso a su implementación particular. –

+1

Nota para otros que vienen a esta página: esta pregunta y la mayoría de las respuestas son de 2009. JVM es mucho mejor hoy en día de lo que solía ser. – eis

+0

Es posible que desee ver ND4J, que admite matrices n-dimensionales para Java. http://nd4j.org/benchmarking.html – tremstat

Respuesta

-4

Java utiliza un compilador justo a tiempo (JIT) para convertir el código de bytes de lenguaje de máquina nativo - por lo que la primera vez que se ejecuta a través de un bloque de código que será más lento, pero una vez que el segmento es 'calentado 'el rendimiento será equivalente. En resumen, el rendimiento numérico es bastante bueno.

+1

Los JIT son agradables, pero no son suficientes para garantizar un buen rendimiento numérico. –

0

Confirmando que su mejor opción es probarlo usted mismo, ya que el rendimiento variará un poco dependiendo de lo que esté haciendo exactamente. Me resulta difícil creer la respuesta de Shane C. Mason de que el rendimiento de Java será el mismo que el de C++ o el de Fortran, ya que incluso C++ y Fortran no son realmente comparables para algunos algoritmos científicos de cómputo.

Tengo un código de dinámica de fluidos computacional que escribí usando C++ y el mismo código esencialmente traducido a Fortran. Todavía no estoy seguro de por qué, pero la versión de Fortran es aproximadamente el doble de rápida que la versión de C++. Supongo que con funciones como comprobación de límites y recolección de basura, Java sería más lento que ambos, pero no lo sabría hasta que lo probara.

+0

¿ha utilizado restringir palabra clave en su código C++? Los compiladores Fortran no tienen que garantizar que los punteros de memoria no tengan alias, mientras que los compiladores C++ deben suponer que la memoria tiene un alias a menos que se indique lo contrario. ¿Qué compiladores usaste? Programé mi programa en C++ con intrínsecos y el compilador de Intel es significativamente más rápido que GCC, supongo que Intel C++ ordena las instrucciones mejor, ya que el ensamblaje fue muy similar, excepto por el orden. – Anycorn

+0

Soy vagamente consciente de los problemas de alias, pero aún no lo entiendo lo suficiente. No he intentado restringir aún, no he tenido el tiempo para gastar en esto, desafortunadamente. Estaba usando icpc y ifort (ambos compiladores de Intel) en Linux con -O3. Tenga en cuenta que mi punto no es que el rendimiento C++ no puede coincidir con fortran, sino que debe comparar las implementaciones además de los idiomas. – notJim

+0

Fortran también tiene un modelo numérico mucho más relajado que C++: está permitido hacer un montón de optimizaciones matemáticas de forma predeterminada que solo se obtienen en C/C++ con -funciones matemáticas y similares. A veces esto no importa, y algunas veces hará que sus resultados sean menos precisos. –

1

This es un enlace a la página de tiroteo del lenguaje de programación para java vs C++, que le dará una comparación de la velocidad de java en varios algoritmos de cálculo intensivo. También le mostrará el código Java de mayor rendimiento. En su mayor parte, para estos pocos puntos de referencia específicos, Java tardó más (pero no más de 2 o 3 veces) en ejecutarse.

+0

No pude saber de inmediato: esta comparación no tiene en cuenta los tiempos de calentamiento. Java aún necesita un lote de trabajo inicial antes de alcanzar la velocidad de crucero. –

+0

cierto. si desea escribir un programa que se inicia, realiza algunos cálculos y luego se apaga, es probable que no desee Java. pero si su programa se ejecutará durante unos minutos, entonces el tiempo de inicio es solo ruido. Una alternativa, por supuesto, es iniciar un proceso de java y hacer que actúe como un servidor de cálculo: cada vez que necesita un cálculo, simplemente llama a una instancia que ya se está ejecutando. –

+0

@ Thorbjørn Ravn Andersen - 1) ¡Lea las preguntas frecuentes! 2) ¡Observe que los programas se ejecutan durante segundos, no microsegundos! 3) Mira las aproximaciones de estado estacionario http://shootout.alioth.debian.org/u64q/benchmark.php?test=all&lang=javasteady&lang2=gpp&box=1 4) ¡Lee las preguntas frecuentes! acerca de Java http://shootout.alioth.debian.org/u64q/faq.php#dynamic – igouy

1

Esto viene de un lado .NET de cosas, pero estoy 90% seguro de que es el caso de Java también. Si bien el JIT hará un uso de las instrucciones de SSE donde sea posible, actualmente no auto-vectoriza su código cuando se trata, por ejemplo, de multiplicaciones de matrices. C++ vectorizado a mano utilizando compiladores intrínsecos/ensamblado en línea definitivamente será más rápido aquí.

0

Esto puede ser tan dependiente de lo que está haciendo en el código C++.

Por ejemplo, ¿está utilizando la GPU? Editar Me olvidé de jogl, por lo que Java puede competir aquí.

Si está paralelizado usando STM o memoria compartida, entonces Java no puede competir. Para un enlace en el análisis de la multiplicación de matrices en paralelo: http://www.cs.utexas.edu/users/plapack/papers/ipps98/ipps98.html

¿Tiene suficiente memoria para hacer los cálculos en la memoria, por lo que no será necesario el recolector de basura, y tienen que afinaron el recolector de basura para un rendimiento óptimo ? Entonces, Java puede ser competitivo, tal vez.

¿Está utilizando multinúcleos y está optimizado en C++ para aprovechar esta arquitectura? Entonces Java no podrá competir.

¿Está utilizando varias computadoras atadas, entonces Java no podrá competir.

¿Está utilizando alguna combinación de estos, entonces dependerá de la implementación particular.

Java no está diseñado para competir con un programa C++ sintonizado a mano, pero, el tiempo que lleva realizar la sintonía, ¿está haciendo suficientes cálculos donde va a importar? Java podrá dar una velocidad razonable pero con menos trabajo que el ajuste a mano, pero no representa una gran mejora con respecto al código C++.

Es posible que desee ver si hay una mejora sobre Haskell o Erlang, por ejemplo, sobre su C++, ya que estos idiomas están mejor diseñados para este tipo de trabajo.

+0

¿Usando la GPU? Como en, usando OpenGL? Si usa JOGL Java puede competir muy bien. –

+0

Tiene razón, he corregido mi respuesta, olvidé que puede usar jogl para el trabajo de la GPU. –

1

Uno de los puntos más débiles en Java es el funcionamiento (nativo) de la matriz. Esto se debe a la naturaleza de las matrices Java:

  • No se puede declarar que una matriz sea rectangular, es decir. cada fila puede tener un número diferente de columnas.

  • Una matriz no es técnicamente una "matriz de dobles (o ints, ...)", sino una matriz de matrices de .... La gran diferencia es que, dado que las matrices son objetos de Java, puede asignar el mismo objeto de matriz a más de 1 fila.

Estas dos propiedades hacen que muchas optimizaciones de matriz estándar sean imposibles para el compilador.

Puede obtener un mejor rendimiento utilizando una biblioteca Java que emula matrices en una única matriz larga. Sin embargo, tiene la sobrecarga de llamadas de método para todos los accesos.

+2

Creo que quiere decir que no puede declarar que una matriz 2D es rectangular. Pero pareces estar argumentando que la implementación más literal y directa de una matriz en Java tiene algunos problemas. ¿Por qué sería esta la única implementación posible? Si no es así, no hay mucho de una declaración posible aquí acerca de la 'naturaleza de las matrices Java'. ¿Qué pasa con las bibliotecas de matrices Java como Colt? –

+0

Las matrices no siempre se representan de esa manera. Ver 'java.awt.image.Kernel' para un ejemplo de una matriz representada por una matriz 1D – finnw

+0

El problema con dichas bibliotecas es que todo el acceso a la matriz se realiza a través de métodos. Las llamadas a métodos son más lentas que el acceso a la matriz en general y evitan ciertas optimizaciones del compilador. P.ej. 'for (int i = 0; i Carsten

1

C++ será definitivamente más rápido. Incluso puede tener algunas bibliotecas optimizadas a mano para sus propósitos que contienen códigos de ensamblaje para cada una de las principales CPU que existen. No puedes ser mejor que eso.

Después, puede usar JNI para llamar desde Java, si es necesario.

Java no está diseñado para cálculos aritméticos de alto rendimiento como este. Si dependes de estos, te recomendaría escoger un lenguaje apropiado de bajo nivel para implementarlo. O, alternativamente, puede escribir la parte específica del rendimiento en un lenguaje de bajo nivel y luego conectarla a un front-end Java utilizando JNI o ​​algún otro método IPC.

0

¿Este tipo de cálculos le interesan? ¿Transformación de Fourier rápida, Jacobi sucesiva sobre relajación, integración de Monte Carlo, matriz escasa Mult, densificación de matriz LU densa?

Constituyen el SciMark 2.0 composite benchmark que puede iniciar como un applet en su máquina.

También hay ANSI C versions de los programas, y Intel document (pdf) on optimizing and recompiling SciMark for C++.


Del mismo modo se puede utilizar The Java Grande Forum Benchmark Suite y the comparison C programs.

2

He escrito un código numérico razonablemente grande y sensible al rendimiento en Java (por lo general, se utilizan grandes matrices de dobles).

He encontrado que Java es "lo suficientemente bueno" para realizar cálculos numéricos rápidos. Especialmente si tenemos en cuenta que, por lo general, no está vinculado a la CPU, la latencia de la memoria y el conocimiento de la caché probablemente serán su mayor problema para grandes conjuntos de datos.

Sin embargo, aún puede vencer a Java con código C/C++ optimizado a mano que aprovecha las instrucciones vectorizadas específicas, etc. o diseños de memoria altamente personalizados. Entonces, para el código más rápido, podría considerar escribir el algoritmo central en C/C++ y llamarlo desde Java usando JNI.

Personalmente, creo que crear una dependencia de código nativo suele ser más problemático de lo que vale, así que tiendo a apegarme al enfoque puro de Java.