¿En qué medida la programación genérica y la metaprogramación usando plantillas C ++ son útiles en la ciencia computacional?


17

El lenguaje C ++ proporciona programación genérica y metaprogramación a través de plantillas. Estas técnicas han encontrado su camino en muchos paquetes de computación científica a gran escala (por ejemplo, MPQC , LAMMPS , CGAL , Trilinos ). Pero, ¿qué han contribuido realmente a la informática científica en un valor que va más allá de los lenguajes no genéricos y no meta como C o Fortran en términos de tiempo de desarrollo general y usabilidad para una eficiencia igual o adecuada?

Dada una tarea informática científica, tiene genérica y meta-programación a través de plantillas de C ++ demostraron una mejora en la productividad, la expresividad, o la facilidad de uso, medida por cualquier punto de referencia bien entendidos (líneas de código, persona-esfuerzo, etc ...)? Correspondientemente, qué riesgos están asociados con el uso de plantillas de C ++ para la programación genérica y la meta?


Me preocupa que esta pregunta pueda estar demasiado abierta a opiniones, pero quiero ver qué dicen las personas de la comunidad.
Geoff Oxberry

1
Eliminé completamente el comentario descarrilar. Si le gustaría que reposted para charlar o meta estoy feliz de hacerlo. Mira mi meta aquí .
Aron Ahmadia

3
Además, vea la pregunta relacionada aquí en el consejo de cuándo usar y cuándo evitar las plantillas de expresión .
Aron Ahmadia

No creo que es correcto decir que LAMMPS utiliza plantillas o metaprogramming. LAMMPS es un código orientado a objetos que se parece mucho a Fortran la mayor parte del tiempo. No creo MPQC tiene mucho de plantillas o bien, pero es muy orientado a objetos y polimórfica.
Jeff

1
OpenFOAM hace un uso intensivo de plantillas y otras características de C ++.
Dohn Joe

Respuestas:


14

Creo que en general, metaprogramming plantilla se ha encontrado para ser inutilizable en la práctica - que compila demasiado lento, y los mensajes de error que recibe son simplemente imposible de descifrar. La barrera de entrada para los recién llegados también es demasiado alta cuando se usa la metaprogramación.

Por supuesto, la programación genérica es una cuestión totalmente diferente, como lo demuestra Trilinos, deal.II (mi propia biblioteca), duna, y muchas otras bibliotecas - expresando el mismo concepto de funcionamiento de diferentes tipos de datos es una especie de obviedad, y la comunidad lo ha aceptado en gran medida siempre que se mantenga dentro de los límites que evitan los problemas de la metaprogramación. Creo que la programación genérica califica como un éxito obvio.

Por supuesto, ninguno de estos temas está conectado inmediatamente a OOP. OOP, nuevamente, diría, universalmente aceptado por la comunidad científica informática. Incluso menos de programación genérica, no es un tema de debate: todas las bibliotecas exitosa escrito en los últimos 15 años (ya sea escrito en C ++, C o Fortran) utiliza técnicas de programación orientada a objetos.


44
tmp puede ser difícil para usuarios novatos, pero a menudo se hace muy bien dentro de la biblioteca. Es una de esas técnicas que realmente puede reducir la cantidad de código, pero realmente necesita saber lo que está haciendo. Si no me crees, lee la fuente de Eigen o Elemental. Su hermoso código que sin plantillas sería prácticamente imposible.
aterrel

55
Claro, es una técnica con valor. Pero es difícil de mantener, y a menudo es difícil de usar si está expuesto a la interfaz externa. Dicho esto, creo que una de las razones por las que TMP no ha sido el éxito que la gente esperaba inicialmente es que los compiladores se han vuelto muy buenos. TMP vive del hecho de que se conocen muchas cosas en tiempo de compilación, y luego se pueden propagar como constantes en el código real. Pero los compiladores se han vuelto bastante buenos en línea, clonación de funciones, etc., por lo que hoy en día se puede obtener una parte significativa del beneficio utilizando la programación "normal".
Wolfgang Bangerth

15

Permítanme dar un ejemplo basado en la experiencia. La mayoría de las bibliotecas que uso a diario usan OOP de alguna manera. OOP puede ocultar la complejidad requerida para muchos dominios, no es un mecanismo que realmente ayude con el rendimiento. Lo que puede suceder es que una biblioteca pueda usar optimizaciones específicas basadas en la jerarquía de objetos, pero en su mayor parte se trata de ocultar la complejidad del usuario. Busque patrones de diseño, son los mecanismos a menudo empleados para lograr esta ocultación de complejidad.

Tome PETSc como ejemplo. PETSc utiliza un modelo de inspector / ejecutor de programación orientada a objetos, donde cualquiera de sus miradas algoritmos en las rutinas disponibles en un objeto dado un elige que desea ejecutar para llevar a cabo la rutina. Esto permite que un usuario separe las preocupaciones, por ejemplo, la acción de la matriz puede incluir cualquier tipo de rutina bloqueada u optimizada y puede ser utilizada efectivamente por numerosos solucionadores iterativos. Al darle al usuario la capacidad de especificar sus propios tipos de datos y evaluaciones, obtiene algunas rutinas importantes aceleradas y también tiene toda la funcionalidad de la biblioteca aún disponible.

Otro ejemplo que daré es FEniCS y deal.II. Ambas bibliotecas usan OOP para generalizar sobre una gran cantidad de métodos de elementos finitos. En ambos, todo, desde el tipo de elemento, el orden del elemento, la representación en cuadratura, etc., es intercambiable. Si bien estas dos bibliotecas son "más lento" que algunos códigos FEMENINO estructurado para propósitos especiales, que son capaces de resolver una amplia variedad de problemas con gran parte de la complejidad de FEM desconocido para el usuario.

Mi último ejemplo es elemental. Elemental es una nueva biblioteca de álgebra lineal densa que ha llevado la dificultad de administrar los comunicadores MPI y la ubicación de datos a una construcción de lenguaje muy simple. El resultado es que si tiene un código de serie FLAME, al cambiar los tipos de datos también puede tener un código paralelo a través de Elemental. Aún más interesante se puede jugar con la distribución de datos mediante el establecimiento de la distribución igual a otro.

Programación orientada a objetos debe ser considerado como una forma de gestionar la complejidad, no es un paradigma para competir con la mano laminado montaje. También lo hace mal dará lugar a un montón de gastos generales por lo tanto hay que tener tiempo y la actualización de los mecanismos que usan con.


3

Idioma características como OOPtareas pendientes para la computación científica es hacer de instrucciones de código más compacto que ayuda en la comprensión y el uso de código mejor. Por ejemplo, FFTlas rutinas tienen que llevar a un gran número de argumentos para cada llamada a la función de hacer el engorroso código.

Al usar moduleo classdeclaraciones solo se puede pasar lo que se necesita en el momento de la llamada, ya que el resto de los argumentos se refieren a la configuración del problema (es decir, el tamaño de las matrices y los coeficientes).

En mi experiencia, he tenido SUBROUTINEllamadas con 55 argumentos (entrada y salida) y que reduje a 5 haciendo que el código mejor.

Eso es valor.


3

Soy un gran defensor de la programación genérica y la metaprogramación para la informática científica. De hecho, estoy desarrollando una biblioteca de C ++ para el software libre de métodos de Galerkin sobre la base de estas técnicas se llama Feel ++ (http://www.feelpp.org) que está recibiendo de manera constante impulso. Es cierto que todavía hay dificultades, como tiempos de compilación lentos y que la curva de aprendizaje podría ser empinada si uno quiere entender lo que está sucediendo detrás de escena. Sin embargo, esto es extremadamente interesante y alucinante. Si se realiza a nivel de biblioteca y oculta la complejidad detrás de un lenguaje específico de dominio, obtendrá una herramienta extremadamente poderosa. Tenemos a nuestra disposición una amplia gama de métodos para usar y comparar. Para fines de enseñanza de la informática científica, esto es impresionante, para la investigación y los nuevos métodos numéricos, para aplicaciones a gran escala bueno, trabajamos en ello, pero hasta ahora todo bien, ya podemos hacer algunas cosas buenas. Tenemos ingenieros, físicos y matemáticos que lo usan: la mayoría de ellos solo usan el lenguaje para la formulación variacional y están contentos con él. Al observar algunas de las formulaciones que manipulan nuestros colegas físicos, no quisiera verlas hechas "a mano" sin un lenguaje de alto nivel para describir la formulación variacional. Personalmente considero que estas "técnicas" o "paradigmas" ahora son necesarios para abordar la complejidad en el código informático científico al tener que multiplicar el tamaño del código por un factor enorme. Probablemente exista una necesidad de mejorar el soporte de la metaprogramación en C ++, pero ya está en buena forma, especialmente desde C ++ 11.


2

Es posible encontrar el papel http://arxiv.org/abs/1104.1729 relevante a su pregunta. Se analizan las plantillas de expresión (una aplicación particular de la plantilla de meta-programación utilizado en el código científica) desde la perspectiva del rendimiento.


Que las unidades de papel me vuelve loco. Compare el Fortran simple más rápido que tiene con MKL y también perderá. El ensamblaje sintonizado a mano no es algo a lo que uno aspira, es lo que haces cuando cada nanosegundo cuenta y puede ser reutilizado por un gran número de personas.
aterrel

@aterrel: Este es precisamente el contraste del que me pregunto. Sabiendo que tendrá que hacer la optimización manual como la última etapa de desarrollo, ¿qué idioma elegiría como base para usar antes de la última etapa? Qué tenemos datos duros para sugerir que el lenguaje para elegir?
Deathbreath

9
@Deathbreath: repetiré una respuesta que he hecho en varios otros hilos también: que, en general, ajustar el último bit de velocidad de tu código es algo que haces muy raramente. Pero usted programa algoritmos de alto nivel todo el tiempo. Así que elige el idioma que te permita hacer grandes cosas rápidamente. Siempre hay una manera de incluir cosas de bajo nivel de alguna manera, pero no debería ser lo que determina su elección del lenguaje de programación.
Wolfgang Bangerth

0

Las plantillas son muy buenas para eliminar verificaciones de tipo / dominio en tiempo de ejecución. Estos pueden ser atendidos en el momento de la compilación. En teoría, esto puede aumentar el rendimiento sobre el mismo tipo de implementación en C o Fortran, donde la verificación de tipo solo se puede realizar en tiempo de ejecución: las verificaciones se implementan en el código fuente. Sin embargo, puede lograr los mismos resultados en C usando las opciones del precompilador, pero estas deben hacerse a mano, a diferencia de las plantillas.

Sin embargo, las plantillas también pueden generar una sobrecarga significativa. A menudo pueden crear una acumulación de código que puede afectar el uso del caché de instrucciones. Además, los enfoques genéricos a menudo pueden encadenar al compilador durante la optimización: no siempre es sencillo analizar el código cuando se usan enfoques genéricos. Siempre es un problema con la automatización, incluida la optimización del compilador, muy a menudo el código de salida no es compatible con la memoria caché.

Los beneficios de la verificación de tipo / dominio, aunque ciertamente son más seguros, es el único beneficio real que puedo ver en términos de rendimiento y estos son típicamente imperceptibles. Pero como digo, el efecto general puede ser negativo dependiendo de lo que estés haciendo. Es por eso que a menudo es mejor optimizar a mano su código donde tiene cuellos de botella significativos.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.