Lenguaje de desarrollo de software de computación científica paralela?

18

Quiero desarrollar un software paralelo de computación científica desde cero. Quiero algunas ideas sobre qué idioma comenzar. El programa implica leer / escribir datos en archivos txt y hacer cálculos pesados ​​en paralelo, con muchas factorizaciones LU y el uso de solucionadores lineales dispersos. Las soluciones candidatas que estaba pensando son Fortran 2003/2008 con OpenMP o co-array, C ++ con openmp cilk + o TBB, python. ¡Cualquier otra sugerencia documentada es bienvenida! Sé muy bien C, Fortran y Java (en ese orden). He hecho algunos scripts en Python pero cosas básicas.

Sé que fortran es muy rápido, pero difícil de mantener y paralelizar. Se dice que C ++ es lento a menos que use bibliotecas externas, etc. Me gusta Python, pero ¿es realista escribir un software a nivel industrial a escala completa?

El software debe ser capaz de manejar grandes cantidades de datos y ser efectivo con los cálculos científicos. El rendimiento es de la esencia.

Para el fondo, ya tengo un software de trabajo escrito en Fortran. Muchas personas estuvieron involucradas en el desarrollo durante muchos años y el código está muy sucio. Mantener y paralelizar el código ha resultado ser una pesadilla y estoy pensando en alternativas.

Pedro

electrique
fuente
55
Como un experto en C ++, no llamaría a Fortran difícil de mantener. La mantenibilidad está ligada a las buenas prácticas en su mayor parte, no a la elección del idioma. La lentitud de C ++ está sobrevendida. Además, recomendaría que aumente esta publicación para describir el tamaño de sus datos y los requisitos de tiempo de respuesta. He visto que "grande" varía en 9 o 10 órdenes de magnitud dependiendo de con quién estoy hablando.
Bill Barth
@BillBarth El problema con el código Fortran existente es que tres personas estuvieron involucradas usando diferentes prácticas. Vengo de un fondo C, un chico del fondo F77 y otro chico de Matlab. Los datos no son asignables y dimensionados para el sistema de mayor tamaño (estuve involucrado últimamente). El código fue capaz de simular un sistema con 72000 ecuaciones diferenciales y 74000 ecuaciones algebraicas en un horizonte temporal de 240 segundos en 350 segundos (tiempo transcurrido). Reduje eso a 170 usando OpenMP para paralelizar. Ahora necesito ejecutar varios casos en paralelo (para barrer para la verificación de seguridad).
Electrique
44
@BillBarth es demasiado modesto para vender sus habilidades en C ++, pero también es demasiado generoso en su declaración de que "la lentitud de C ++ está sobrevendida". Ha habido varios hilos de C ++ vs Fortran en scicomp.stackexchange.com que han discutido esta misma pregunta y la conclusión general fue que simplemente no es cierto, ya que C ++ es más lento que Fortran en casi todos los casos. Personalmente, creo que hoy podría considerarse un mito urbano. Lo que es muy cierto es que si tiene en cuenta la capacidad de mantenimiento del código, a Fortran no le va muy bien hoy.
Wolfgang Bangerth
2
@BillBarth y otros, si desea continuar discutiendo los méritos generales de Fortran, C ++ y otros idiomas, llévelo a la sala de chat de scicomp y a cualquier persona que desee abordar específicamente.
Aron Ahmadia
1
@AronAhmadia: ah, vamos, tengo mucho que decirle a Jed ;-) (Jed: en otro momento. En nuestro caso, no hay STL para matrices dispersas, pero mucho en las estructuras de datos de malla adaptativa).
Wolfgang Bangerth

Respuestas:

19

Déjame intentar y desglosar tus requisitos:

  • Mantenibilidad
  • Leer / escribir datos de texto
  • Interfaces fuertes / capacidad para factorizaciones LU
  • Solucionadores lineales dispersos
  • Rendimiento y escalabilidad a datos grandes

De esta lista, consideraría los siguientes idiomas:

C, C ++, Fortran, Python, MATLAB, Java

Julia es un nuevo lenguaje prometedor, pero la comunidad todavía se está formando a su alrededor y no se ha implementado en ningún código nuevo importante.

Leer / escribir datos de texto

Esto es fácil de entender en cualquier lenguaje de programación. Asegúrese de almacenar y fusionar adecuadamente su acceso de E / S, y obtendrá un buen rendimiento de cualquiera de los idiomas que debe considerar. Evite los objetos de flujo en C ++ a menos que sepa cómo usarlos de manera eficaz.

Interfaces fuertes / capacidad para factorizaciones LU

Si está realizando factorizaciones LU densas, querrá usar LAPACK o ScaLAPACK / Elemental para la funcionalidad paralela. LAPACK y ScaLAPACK están escritos en Fortran, Elemental está escrito en C ++. Las tres bibliotecas son eficaces y están bien respaldadas y documentadas. Puede interactuar con ellos desde cualquiera de los idiomas que debe considerar.

Solucionadores lineales dispersos

Los principales solucionadores lineales dispersos disponibles gratuitamente están casi todos disponibles a través de PETSc , escrito en C, que está bien documentado y respaldado. Puede interactuar con PETSc desde cualquiera de los idiomas que debe considerar.

Rendimiento y escalabilidad a datos grandes

Los únicos paradigmas de programación paralelos que menciona son basados ​​en memoria compartida, lo que significa que no está considerando un enfoque de computación de memoria distribuida basada en MPI (transmisión de mensajes). En mi experiencia, es mucho más fácil escribir código que se escala mucho más allá de una docena de núcleos utilizando una solución de memoria distribuida. Casi todos los "clústeres" universitarios están basados ​​en MPI en estos días, las grandes máquinas de memoria compartida son caras y, en consecuencia, raras. Debería considerar MPI para su enfoque, pero mi consejo se aplicará independientemente del paradigma de programación que elija.

Con respecto al rendimiento en el nodo, si está escribiendo rutinas numéricas usted mismo, es más fácil obtener un buen rendimiento en serie en Fortran. Si tiene un poco de experiencia en C, C ++ o Python, puede obtener un rendimiento muy comparable (C y C ++ están muertos, incluso con Fortran, Python y MATLAB tienen una sobrecarga de tiempo del 25% sin mucho esfuerzo). MATLAB hace esto a través de un compilador JIT y muy buena expresividad de álgebra lineal. Es probable que necesite usar núcleos numéricos Cython, numpy, numexpr o incrustar para obtener el rendimiento reclamado de Python. No puedo comentar sobre el rendimiento de Java, porque no conozco muy bien el lenguaje, pero sospecho que no está lejos de Python si está escrito por un experto.

Una nota sobre interfaces

Espero haberte convencido de que podrás hacer todo lo que quieras en cualquiera de los lenguajes de programación que estás considerando. Si está utilizando Java, las interfaces C serán un poco desafiantes. Python tiene una excelente compatibilidad con la interfaz C y Fortran a través de ctypes, Cython y f2py. LAPACK ya está envuelto y disponible a través de scipy. MATLAB tiene toda la funcionalidad que necesita en sus bibliotecas nativas, pero no es fácilmente escalable o particularmente fácil de ejecutar en clústeres. Java puede soportar interfaces C y Fortran con el JNI , pero no se encuentra comúnmente en clústeres y en software paralelo para computación científica.

Mantenibilidad

Mucho de esto se reducirá al gusto personal, pero el consenso general sobre la capacidad de mantenimiento es que desea minimizar la cantidad de líneas de código en su software, escribir código modular con interfaces bien definidas y, para el software computacional, proporcionar pruebas que verifican la corrección y la funcionalidad de la implementación.

Recomendación

Yo personalmente he tenido mucha suerte con Python y lo recomiendo para muchos proyectos computacionales. Creo que deberías considerarlo fuertemente para tu proyecto. Python y MATLAB son probablemente los lenguajes más expresivos disponibles para la computación científica. Puede conectar fácilmente Python con cualquier otro lenguaje de programación, puede usar f2py para ajustar su implementación actual de Fortran y reescribir pieza por pieza las partes que desee en Python mientras verifica que mantiene la funcionalidad. En este momento, recomendaría una combinación de la implementación oficial de Python 2.7 con scipy . Puede comenzar fácilmente con esta pila desde la distribución de Enthought Python disponible gratuitamente .

También podría hacer la mayor parte de esto en C, C ++ o Fortran. C y C ++ son lenguajes muy atractivos para desarrolladores profesionales con mucha experiencia, pero con frecuencia tropiezan con nuevos desarrolladores y, en este sentido, probablemente no sean una gran idea para un código más académico. Fortran y MATLAB son populares en computación académica, pero son débiles en las estructuras de datos avanzadas y la expresividad que ofrece Python (piense en un objeto dict Python, por ejemplo).

Preguntas relacionadas:

Aron Ahmadia
fuente
1
Una respuesta muy bien documentada, todo incluido. Bajo Fortran uso mucho Lapack. Echaré un vistazo a Python e intentaré envolver mi código Fortran para comenzar, y lentamente me moveré a Python. Lo único que me asusta es la sobrecarga de tiempo del 25% que podría tener. Pero si viene con el beneficio de un código más expresivo y un mejor manejo de la computación paralela, lo intentaré. Mencioné la memoria compartida solo porque el software actualmente se ejecuta de manera interactiva (hacer un cambio en los datos y volver a ejecutar) en computadoras con memoria compartida de 2,4,8,24,48 núcleos de investigadores en la Uni bajo Windows y Linux.
Electrique
3
No sé cómo puede reclamar una sobrecarga del 25% para los núcleos numéricos escritos en Python. Los núcleos numéricos de Python puros suelen ser 100 veces más lentos que C. Numpy y numexpr pueden hacer un trabajo decente con ciertas expresiones, pero eso difícilmente es escribir nuevos núcleos numéricos en Python. Cython puede hacer que algunas cosas sean rápidas, pero por lo general no está dentro del 25% de C. Python es un excelente lenguaje de "pegamento", pero creo que Aron lo está vendiendo demasiado como una solución de propósito general para tareas sensibles al rendimiento.
Jed Brown
I / O es el punto débil de Fortran, porque Fortran requiere mucha estructura en I / O. Mi experiencia de segunda mano al hablar con colegas en mi laboratorio que trabajan con Cython coincide con lo que Jed dice sobre Cython; al menos uno de ellos escribe C sintonizado a mano para reemplazar el Cython por tareas de alto rendimiento, y luego creo que el rendimiento de Python llamando al código C resultante está más cerca de la afirmación de Aron. Además, si vas a mencionar PETSc y Python, también podrías mencionar petsc4py. Lo último que vi (esto fue hace unos años), no había buenas interfaces MPI para Java. ¿Ha cambiado eso?
Geoff Oxberry
@ GeoffOxberry: Los enlaces MPI de Java existen pero no se han actualizado en casi una década. Considero dudoso su estado. Fortran tiene numerosas opciones de E / S que se pueden hacer para que funcionen muy rápido. Recomiendo explorar Parallel HDF5 (y HDF5, en general). Si la E / S es verdaderamente dominante (más del 50% del tiempo de ejecución), podrían ser necesarias medidas más serias, pero de lo contrario, la calidad y la portabilidad de una interfaz similar a HDF probablemente valga la pena.
Bill Barth
@BillBarth: tendré que comprobar eso. Mi comentario sobre Fortran I / O proviene del punto de vista de alguien que alguna vez me recomendó que escribiera un analizador de archivos de entrada en Fortran. Es posible, aplicando una gran cantidad de estructura, pero simplemente no he visto bibliotecas de analizador de expresiones regulares o analizador XML en Fortran (para dar algunos ejemplos). Hay una buena razón para eso: ya somos las únicas personas que usan Fortran. Quizás estamos pensando en diferentes casos de uso.
Geoff Oxberry
2

Además de la respuesta muy completa de Aron, echaría un vistazo a los diversos hilos en scicomp.stackexchange que trataban la pregunta sobre qué lenguaje de programación tomar, tanto con respecto a la velocidad de los programas como a la cuestión de cuán fácil o difícil es para escribir y mantener software en estos idiomas.

Dicho esto, además de lo que se ha escrito allí, permítanme hacer algunas observaciones:

(i) Usted incluye Fortran co-array en su lista. Que yo sepa, el número de compiladores que realmente lo admiten es muy pequeño y, de hecho, mi cero. El compilador Fortran más ampliamente disponible es GNU gfortran, y aunque las fuentes de desarrollo actuales analizan un subconjunto de co-arrays, creo que en realidad no admite ninguno de ellos (es decir, acepta la sintaxis pero no implementa ninguna de las semánticas) . Por supuesto, esta es una observación general sobre los nuevos estándares de Fortran: que el retraso con el que los compiladores realmente admiten nuevos estándares se mide en varios años: los compiladores solo han implementado Fortran 2003 en los últimos años, y solo parcialmente Fortran 2008. Esto no debería impedir que uses nada si tienes un compilador que admite lo que usas,

(ii) Lo mismo es cierto con C ++ / Cilk +: Sí, Intel está desarrollando esto en una rama de GCC pero no está disponible en ninguna de las versiones de GCC y, probablemente, no lo estará por un tiempo. Puede esperar que demore otros 2-3 años por lo menos hasta que encuentre Cilk + con las versiones de GCC instaladas en máquinas típicas de Linux.

(iii) C ++ / TBB es una historia diferente: el TBB ha existido por un tiempo, tiene una interfaz muy estable y es compilable con la mayoría de los compiladores de C ++ que han existido durante los últimos años (en Linux y en Windows) . Lo hemos estado utilizando en el negocio. II durante varios años ya con buenos resultados. También hay un muy buen libro al respecto.

(iv) Tengo mi propia opinión sobre OpenMP, a saber, que es una solución en busca de un problema. Funciona bien para paralelizar los bucles internos, que es lo que podría ser de interés si tiene estructuras de datos muy regulares. Pero rara vez es lo que quieres hacer si necesitas paralelizar algo, porque lo que realmente quieres hacer es paralelizar los bucles externos . Y para eso, las soluciones como el TBB son soluciones mucho mejores porque usan los mecanismos del lenguaje de programación en lugar de tratar de describir lo que sucede fuera del lenguaje (a través de #pragmas) y de tal manera que no tiene acceso a los controladores de hilos , indicadores de estado de resultados, etc., desde su programa.

(v) Si eres experimental, también puedes echar un vistazo a los nuevos lenguajes de programación diseñados para la programación paralela y, en particular, para tareas como las que describes. Esencialmente, hay dos que echaría un vistazo: X10 y Chapel . He visto buenos tutoriales sobre Chapel, y parece estar bien diseñado, aunque ambos, por supuesto, también son soluciones insulares.

Wolfgang Bangerth
fuente
Para el registro, Intel afirma tener un conjunto paralelo (memoria distribuida) Fortran integrado en sus compiladores actuales. Lo estamos investigando en TACC, pero todavía no tengo nada que informar. Cray también tiene una implementación en su compilador, pero solo está disponible en un pequeño número entero de máquinas en todo el mundo. No creo que nadie implemente el estándar completo de Fortran 2008 con respecto a los arreglos conjuntos, pero hay un soporte más que incipiente en algunos compiladores. Cilk +, por supuesto, también está disponible con los compiladores Intel, pero ser confiable aún no es prudente.
Bill Barth
El estándar Fortran 2008 no se aprobó hasta finales de 2010, por lo que pasarán algunos años antes de que CAF esté ampliamente disponible. G95 en realidad tenía una implementación (no gratuita) pero ya no se desarrolla (el desarrollador se había unido a PathScale).
stali
La mayor parte de g95 finalmente terminó en gfortran, pero puede ser que CAF no sea parte de eso.
Wolfgang Bangerth
Creo que el compilador de Intel proporciona un buen soporte de co-array. Lo han construido usando mpiexec. No será mi primera opción. Lo bueno es que la misma implementación puede ejecutarse en memoria compartida y distribuida (ejecuté algunas pruebas). Con los procesadores opteron de memoria compartida que alcanzan los 60 núcleos a precios realmente razonables, quiero ver primero mis opciones de memoria compartida.
Electrique
2

En general, si usted es realmente serio sobre este proyecto de software, sugeriría una reescritura completa en cualquier idioma con el que se sienta más cómodo. Parece que va a hacer el trabajo solo y, por lo tanto, obtendrá los mejores resultados en el idioma con el que se sienta más a gusto.

Sin embargo, más específicamente, con respecto al paralelismo, le animo a que trate de pensar un poco fuera de la caja. OpenMP tiene sus puntos fuertes, pero está atrapado en una mentalidad de tomar un código secuencial y poner paralelismo aquí y allá. Lo mismo ocurre, en esencia, para Intels TBB.

Cilk es definitivamente un paso en la dirección correcta, es decir, te obliga a repensar tu problema / solución en una configuración inherentemente paralela. Sin embargo, lo que no me gusta es que es otro idioma . Además, dado que solo puede inferir aproximadamente las relaciones entre tareas paralelas, el programador puede ser bastante conservador y puede que no se adapte bien a ciertos problemas.

Sin embargo, la buena noticia es que, una vez más, si se toma en serio su implementación, puede hacer lo que hace Cilk, por ejemplo, volver a escribir su problema como un conjunto de tareas interdependientes y distribuirlas en varios procesadores / núcleos, todo por su cuenta, ya sea utilizando pthreads o mal uso de OpenMP para generar procesos. Un buen ejemplo de cómo se puede hacer esto es el planificador QUARK utilizado en la biblioteca PLASMA . Aquí se ofrece una buena comparación de su rendimiento frente a Cilk .

Pedro
fuente
Veré los enlaces sugeridos. ¡El papel de comparación es muy bueno! ¡Gracias! He estado pensando en pthreads pero quiero que el programa sea multiplataforma. Por lo que sé, los pthreads tienen problemas en Windows (¿mal?).
Electrique
@ p3tris: La "p" en pthreads es para POSIX, por lo que es lo más portátil posible. Hay algunas implementaciones de Windows compatibles como pthreads-win32o dentro del cygwinproyecto.
Pedro
Basado en stackoverflow.com/q/2797690/801468 , veo que hay muchas cosas necesarias para resolverlo para usarlo. Dado que no soy programador, preferiría seguir con algo más probado.
Electrique
2

Se ha discutido poco sobre coarray fortran en los comentarios anteriores. En este momento, y para mi conocimiento limitado, el soporte de la matriz en los compiladores es aproximadamente el siguiente:

  • Cray tiene un compilador que admite al menos las características básicas de la matriz. Lo he usado para escribir código destinado a ser "educativo", pero diría que podría escribir código real en coarray fortran. La sintaxis y los conceptos son en su mayoría mucho más simples que MPI, pero como siempre, hay muchas trampas, y las trampas son diferentes de MPI.
  • Intel fortran tiene soporte de conjunto de arrays construido sobre su biblioteca MPI. Supuestamente, esto limita su máximo rendimiento teórico, pero no he visto ninguna métrica.
  • Gfortran admite conjuntos de secuencias, pero solo para una sola imagen (o rango único, en lenguaje MPI). Por lo tanto, no hay paralelización real disponible hasta que gfortran 4.8 o 4.9 esté fuera.

En general, tendría cuidado si comenzara un código basado en una matriz. La sintaxis es simple y mucho más conveniente que Fortran / C / C ++ con MPI, pero no es tan completa. Por ejemplo, MPI admite muchas operaciones de reducción, etc., lo que podría ser muy conveniente para usted. Realmente dependería de su necesidad de mucha comunicación. Si desea un ejemplo, hágamelo saber y puedo proporcionarle algunos, si puedo desenterrar los archivos.

Pletnes
fuente
Sí, más información acerca de la preparación del coarray Fortran para este tipo de problema sin duda sería útil. ¡Bienvenido a scicomp!
Aron Ahmadia 01 de
1

Eche un vistazo a Spark , es un marco distribuido para cálculos en memoria que aprovecha la programación funcional. La estructura de un programa en Spark es muy diferente en comparación con MPI, básicamente se escribe un código como para una sola computadora, que se distribuye automáticamente como funciones a los datos ubicados en la memoria. Es compatible con Scala, Java y Python.

Regresión logística (scala):

//load data to distributed memory
val points = spark.textFile(...).map(parsePoint).cache()
var w = Vector.random(D) // current separating plane
for (i <- 1 to ITERATIONS) {
  val gradient = points.map(p =>
    (1 / (1 + exp(-p.y*(w dot p.x))) - 1) * p.y * p.x
  ).reduce(_ + _)
  w -= gradient
}
println("Final separating plane: " + w)

Hay una extensión llamada MLib (biblioteca de Machine Learning) que usa una biblioteca Fortran para algunos cálculos de bajo nivel (supongo que para Python se usa numpy). Entonces, la idea es simple, concéntrese en su algoritmo y deje las optimizaciones en niveles más bajos (orden de procesamiento, distribución de datos, etc.).

Tombart
fuente