Estoy escribiendo una pequeña biblioteca para cálculos de matriz dispersos como una forma de enseñarme a mí mismo a hacer el mejor uso de la programación orientada a objetos. He trabajado muy duro para tener un buen modelo de objetos, donde las partes (matrices dispersas y los gráficos que describen su estructura de conectividad) están muy poco acoplados. En mi opinión, el código es mucho más extensible y fácil de mantener.
Sin embargo, también es algo más lento que si hubiera usado un enfoque contundente. Para probar las compensaciones de tener este modelo de objeto, escribí un nuevo tipo de matriz dispersa que rompió la encapsulación del gráfico subyacente para ver cuánto más rápido se ejecutaría.
Al principio, parecía bastante sombrío; El código del que alguna vez me sentí orgulloso era un 60% más lento que una versión sin ningún diseño de software elegante. Sin embargo, pude hacer algunas optimizaciones de bajo nivel, incluyendo una función y cambiando un bucle un poco, sin cambiar la API. Con esos cambios, ahora es solo un 20% más lento que la competencia.
Lo que me lleva a mi pregunta: ¿Qué pérdida de rendimiento debo aceptar si significa que tengo un buen modelo de objeto?
fuente
Respuestas:
Muy pocos desarrolladores de software científico entienden los buenos principios de diseño, por lo que me disculpo si esta respuesta es un poco larga. Desde una perspectiva de ingeniería de software, el objetivo del desarrollador científico de software es diseñar una solución que satisfaga un conjunto de restricciones que a menudo son conflictivas .
Estos son algunos ejemplos típicos de estas restricciones, que podrían aplicarse al diseño de su biblioteca de matriz dispersa:
Los científicos gradualmente están prestando más atención a otros requisitos comunes de la ingeniería de software:
Es posible que necesite más o menos de uno de estos requisitos. Si está tratando de ganar un premio Gordon Bell por su desempeño, incluso las fracciones de un porcentaje son relevantes, y pocos de los jueces evaluarán la calidad de su código (siempre que pueda convencerlos de que es correcto). Si está tratando de justificar la ejecución de este código en un recurso compartido, como un clúster o una supercomputadora, con frecuencia debe defender las afirmaciones sobre el rendimiento de su código, pero rara vez son muy estrictas. Si está tratando de publicar un artículo en una revista que describa las ganancias de rendimiento de su enfoque, entonces necesita ser legítimamente más rápido que sus competidores, y el 20% de rendimiento es una compensación que con mucho gusto haría para una mejor mantenibilidad y reutilización.
Volviendo a su pregunta, el "buen diseño", con suficiente tiempo de desarrollo, nunca debería sacrificar el rendimiento. Si el objetivo es crear un código que se ejecute lo más rápido posible, entonces el código debe diseñarse en torno a esas restricciones. Puede usar técnicas como la generación de código, el ensamblaje en línea o aprovechar las bibliotecas altamente ajustadas para ayudarlo a resolver su problema.
Pero, ¿qué pasa si no tienes suficiente tiempo de desarrollo? ¿Qué es lo suficientemente bueno? Bueno, depende, y nadie podrá darle una buena respuesta a esta pregunta sin más contexto.
FWIW: Si realmente está interesado en escribir núcleos de matriz dispersos de alto rendimiento, debe compararlo con una instalación PETSc optimizada y trabajar con su equipo si los supera, estarán encantados de incorporar núcleos ajustados a la biblioteca.
fuente
Es una pregunta sobre en qué pasas tu tiempo. Para la mayoría de nosotros, pasamos 3/4 del tiempo programando y 1/4 del tiempo esperando resultados. (Sus números pueden variar, pero creo que el número no carece por completo de méritos). Entonces, si tiene un diseño que le permitió programar el doble de rápido (3/4 de una unidad de tiempo en lugar de 1.5 unidades de tiempo), entonces puede tener un 300% de éxito en el rendimiento (de 1/4 a 1 unidad de tiempo) y aún así se adelanta en términos de tiempo real dedicado a resolver el problema.
Por otro lado, si está haciendo cálculos pesados, sus cálculos pueden tener un aspecto diferente y es posible que desee pasar más tiempo optimizando su código.
Para mí, el 20% parece una compensación bastante buena si terminas siendo más productivo.
fuente
En mi humilde opinión, una penalización de hasta el 50% (por cualquier razón) no es tan malo.
De hecho, he visto una diferencia de 0-30% en el rendimiento solo en función del tipo de compilador. Esto es para la escasa rutina MatMult de PETSc en matrices que surgen de discretizaciones FE de bajo orden.
fuente
El diseño del software no mejorará automáticamente con el tiempo. La actuación lo hará. Obtendrá el 20% de vuelta con su próxima CPU. Además, un buen diseño de software hará que sea más fácil extender o mejorar la biblioteca en el futuro.
fuente
Un principio general es buscar un buen diseño primero y luego optimizar el rendimiento solo si es necesario . Es probable que los casos de uso en los que realmente se necesite un aumento del rendimiento del 20% sean bastante raros, si es que aparecen.
fuente