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?
fuente
Respuestas:
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.
fuente
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.
fuente
Idioma características como
OOP
tareas 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,FFT
las 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
module
oclass
declaraciones 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
SUBROUTINE
llamadas con 55 argumentos (entrada y salida) y que reduje a 5 haciendo que el código mejor.Eso es valor.
fuente
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.
fuente
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.
fuente
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.
fuente