2010-02-27 14 views
11

Mi pregunta es sobre el rendimiento de Java frente al código compilado, por ejemplo C++/fortran/assembly en aplicaciones numéricas de alto rendimiento. Sé que este es un tema polémico, pero estoy buscando respuestas/ejemplos específicos. También comunidad wiki. He hecho preguntas similares anteriormente, pero creo que las expuse de manera amplia y no obtuve las respuestas que estaba buscando.C/C++ versus Java/C# en aplicaciones de alto rendimiento

multiplicación de matriz de matriz de doble precisión, comúnmente conocida como biblioteca dgemm en blas, es capaz de lograr un rendimiento de CPU máximo de casi 100 por ciento (en términos de operaciones flotantes por segundo).
Hay varios factores que permiten lograr que el rendimiento:

  • bloqueo caché, para lograr la máxima localidad de memoria

  • bucle desenrollado para reducir al mínimo el control de sobrecarga

  • instrucciones vectoriales, como el SSE

  • preconfiguración de memoria

  • garantía ninguna memoria aliasing

he visto una gran cantidad de puntos de referencia utilizando el montaje, C++, Fortran, Atlas, proveedor BLAS (casos típicos son la matriz de dimensión 512 y superiores). Por otro lado, he escuchado que los principales lenguajes/implementaciones compilados en bytes, como Java, pueden ser rápidos o casi tan rápidos como los lenguajes compilados por máquina. Sin embargo, no he visto puntos de referencia definidos que demuestren que sea así. Por el contrario, parece que (de mi propia investigación) los lenguajes compilados en bytes son mucho más lentos.

¿Tiene buenos puntos de referencia de multiplicación de matrices matriciales para Java/C#? ¿hace el compilador just-in-time (implementación real, no hipotética) capaz de producir instrucciones que satisfagan los puntos que he enumerado?

Gracias

en cuanto a rendimiento: cada CPU tiene un rendimiento máximo, dependiendo del número de instrucciones de procesador puede ejecutar por segundo. Por ejemplo, la moderna CPU Intel de 2 ghz puede alcanzar 8 billones de precisión doble agregar/multiplicar por segundo, lo que resulta en un rendimiento pico de 8 gflops. Matrix matrix Multiply es uno de los algoritmos que es capaz de lograr un rendimiento casi completo con respecto al número de operaciones por segundo, razón principal por la que es mayor la proporción de operaciones de computación sobre memoria (N^3/N^2). Números Estoy interesado en algo sobre el pedido N > 500.

en lo que respecta a la implementación: detalles de nivel superior como el bloqueo se realiza en el nivel de código fuente. La optimización de nivel inferior es manejada por el compilador, tal vez con sugerencias de compilador con respecto a la alineación/alias. La implementación compilada por bytes también se puede escribir usando el enfoque de bloques, por lo que, en principio, los detalles del código fuente para una implementación decente serán muy similares.

+0

Puedo escribir código en Java que utiliza el 100% de la CPU, incluso sin hacer nada significativo ;-) Supongo que entiendo lo que "realmente" significa, pero su fraseo es un poco ambigua. –

+0

Aún no está mucho más claro para mí ... ¿quiere decir que hay algún tipo de "ideal" que establece que para una arquitectura de CPU determinada, el mejor rendimiento numérico imaginable es tal y tal, y esto es lo que llama el 100 por ciento? ¿Habría alguna medida concreta como MFLOPS para esto? No soy un experto en esta área. –

+0

No voté para cerrar esta publicación (aún no tengo el derecho). Lo encuentro interesante, solo trato de darle retroalimentación para aclarar su publicación. –

Respuesta

0

Solucionando el problema de SSE: Java is using SSE instructions since J2SE 1.4.2.

+2

Hasta donde yo sé, no usa las instrucciones SSE para vectorizar el código, ni lo hace .NET CLR. Mono tiene algunas estructuras (Vectores y Matrices) que son tratadas especialmente por el compilador JIT que se convierte en código vectorizado. – JulianR

+0

@JR esa fue mi impresión también – Anycorn

1

Todos los factores que especifique probablemente se realicen mediante la optimización manual de la memoria/código para su tarea específica. Pero el compilador JIT no tiene suficiente información sobre su dominio para hacer que el código sea óptimo a medida que lo hace a mano, y puede aplicar solo reglas generales de optimización.Como resultado, será más lento que el código de manipulación de matriz C/C++ (pero puede utilizar el 100% de la CPU, si lo desea :)

+0

cierto. Pero los problemas de vectorización y aliasing son manejados por los compiladores con frecuencia. Además, loop lance algo que espero que haga el compilador. El acceso a la memoria caché es bastante sencillo en los lenguajes de compilación, pero ¿cómo lo maneja el lenguaje de compilación de bytes? – Anycorn

+0

@aaa: el motor/compilador JIT se encarga de eso. – LiraNuna

2

Comparación de VC++/.NET 3.5/Mono 2.2 en un escenario de multiplicación de matriz pura :

http://img237.imageshack.us/img237/2788/resultse.png Source

Mono con Mono.Simd va un largo camino para cerrar la brecha de rendimiento con el optimizado a mano C++ aquí, pero la versión de C++ sigue siendo claramente el más rápido. Pero Mono está en 2.6 ahora y podría estar más cerca y yo esperaría que si .NET alguna vez obtiene algo como Mono.Simd, podría ser muy competitivo ya que no hay mucha diferencia entre .NET y el C++ secuencial aquí.

+0

gracias. ¿Qué explica la diferencia entre dos implementaciones SIMD? buscar en un dato que parece estar relacionado con la memoria? – Anycorn

+1

Hablando de SSE en C++, sugiero que también compares GCC 4.4, solo por la integridad, ya que la generación de código SSE de MSVC es realmente horrible (mira http://www.liranuna.com/sse-intrinsics-optimizations-in-popular- compiladores/para más detalles). – LiraNuna

0

java no puede competir con c en multipli- caciones de matriz, una razón es que comprueba en cada acceso de matriz si se exceden los límites de la matriz. Además, las matemáticas de Java son lentas, no usan los procesadores sin(), cos().

Cuestiones relacionadas