20% de penalización de rendimiento para un buen diseño de software


17

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?


¿Qué operación de matriz dispersa estabas midiendo?
Bill Barth

Matriz-vector multiplicar. Las matrices variaron en tamaño de . Les hice el gráfico Laplaciano para gráficos aleatorios de Erdos-Renyi con un grado medio d = log 2 n . Además, la cifra del 20% empeora en algunas máquinas, por lo que ahora estoy más inclinado a tirar todo. Suspiro profundonorte=1024,...,16384re=Iniciar sesión2norte
Daniel Shapero

3
¿Que lenguaje de programación estas usando? Por lo general, algo como C ++ le permitirá escapar con diseños elegantes (ish) a un costo bajo (o inexistente). En otros lenguajes sin metaprogramación (Java, Fortran, etc.) un costo del 20% parece razonable.
LKlevin

¿Nos puede mostrar su código? ¿Qué idioma usaste? ¿Qué compilador y banderas de compilación? ¿Encontró exactamente de dónde viene el éxito de rendimiento? ¿Cómo te aseguraste de encontrar la razón correcta? ¿Qué perfil usaste y cómo lo usaste? ¿Está seguro de que el modelo de objeto agradable no se implementa de manera ineficiente? El 20% es lo suficientemente pequeño como para que necesite recopilar una gran cantidad de datos y tener un análisis detallado antes de decir que definitivamente se debe al diseño, en lugar de, digamos, una implementación inferior u otros problemas de codificación.
Kirill

Breve nota al margen: todos parecen elogiar públicamente el buen diseño sobre el rendimiento puro (con razones muy válidas, por supuesto). Pero entonces, ¿por qué hay tanto código del mundo real realmente, realmente imposible de mantener? ¿Se sienten culpables y, por lo tanto, públicamente silenciosos todos los descuidados del código?
AlexE

Respuestas:


9

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:

  • Completado en un mes
  • Se ejecuta correctamente en su computadora portátil y varias estaciones de trabajo
  • Corre eficientemente

Los científicos gradualmente están prestando más atención a otros requisitos comunes de la ingeniería de software:

  • Documentación (guía del usuario, tutorial, comentarios de código)
  • Mantenibilidad (control de versiones, pruebas, diseño modular)
  • Reutilización (diseño modular, "flexibilidad")

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.


Tengo curiosidad por los generadores de código: creo que podrían ser útiles para mí, pero me preocupa que sean difíciles de mantener. Sé que los programadores de Java los usan mucho, pero a menudo están diseñados para generar código para aplicaciones específicas. ¿Conoces algún código científico que los use?
Daniel Shapero

ATLAS, FFTW, Spiral, OSKI, Ignition, stencil_codegen, por nombrar varios. No se anuncia públicamente, pero no me sorprendería si varios de los núcleos importantes en MKL y ESSL se generan de esta manera. Escribir un código de generación de kernel mantenible sería una pregunta de seguimiento interesante. Tengo experiencia en esto, pero no me consideraría una autoridad.
Aron Ahmadia

12

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.


Buena respuesta, también agregaría la importancia donde el rendimiento es importante. Un código científico dado no está haciendo únicamente la multiplicación de matrices; Si el 20% de su tiempo de ejecución está en la multiplicación de matrices, un rendimiento del 20% solo tiene una diferencia del 4% en general, y con mucho gusto lo tomaría a cambio de una biblioteca más fácil de usar.
Aurelius

1
Y una mejor biblioteca escrita significa menos errores, por lo que perderá menos tiempo esperando resultados incorrectos.
Davidmh

4

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.


1

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.


No creo que esto responda la pregunta.
nicoguaro

0

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.

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.