¿Cuánto debe optimizarse el software científico?

13

Para aplicaciones que requieren recursos computacionales significativos, el alto rendimiento puede ser un factor crítico cuando se trata de entregar resultados científicos o lograr "avances" en un tiempo razonable.

¿Cuánto tiempo y esfuerzo deberían invertir los desarrolladores de software para optimizar una aplicación? ¿Cuáles son los criterios clave utilizados?

Allan P. Engsig-Karup
fuente
Los programas que se ejecutan científicos escriben a menudo para un muy largo tiempo (por ejemplo, simulaciones). El tiempo del programador y el tiempo de funcionamiento de la computadora pueden ser comparables. Esto es muy diferente del trabajo de programador "habitual" de hoy. Al igual que en los primeros días de la informática, a menudo vale la pena invertir un poco de esfuerzo (y tiempo de programador) para hacer que la simulación sea más rápida y terminar más rápido, y hacer el trabajo más rápido.
Szabolcs

Respuestas:

15

En la gran mayoría de los casos, las mejoras en los algoritmos hacen una diferencia mayor que la mejora en la optimización. Los algoritmos también son más portátiles que las optimizaciones de bajo nivel. Mi consejo es seguir las mejores prácticas generales con respecto al diseño de la memoria para la reutilización de la memoria caché, evitar copias o comunicaciones excesivas, tratar el sistema de archivos de una manera sensata y hacer que los núcleos de punto flotante tengan suficiente granularidad para la vectorización. Algunas veces esto es suficiente para alcanzar una fracción aceptablemente alta de "pico" (para esta operación).

Siempre esboce un modelo de rendimiento para operaciones que considere importantes (o que descubra que son importantes mediante la creación de perfiles). Luego puede usar el modelo de rendimiento para estimar lo que podría ofrecer una implementación altamente ajustada. Si decide que la aceleración vale la pena (en relación con las otras cosas que podría estar haciendo), realice la optimización.

Quizás el desafío más difícil es diseñar interfaces de alto nivel e importantes (en el sentido de que mucho código dependerá de estas opciones) interfaces y estructuras de datos para que pueda optimizar más adelante sin necesidad de cambiar la API. A diferencia de las optimizaciones específicas y las pautas generales, no sé cómo enseñar esto, excepto a través de la experiencia. Trabajar con software de código abierto sensible al rendimiento ayuda. Como con cualquier decisión de API, es importante entender el espacio del problema.

Jed Brown
fuente
1
Recientemente obtuve un factor de mejora de 10,000 (para nuestros eventos más grandes) en el tiempo de ejecución de un paso limitante de nuestro análisis, simplemente reemplazando un algoritmo que era O (n ^ 2) en tiempo y espacio con un O (n log n ) en ambos. Eso sí, significaba otra dependencia y cierta complejidad añadida, pero a veces vale la pena ...
dmckee --- ex-gatito moderador
1
Los factores de aceleración (que son relativos a algo) no valen mucho una referencia clara a lo que ha comparado. Si se compara con una mala implementación basada en un algoritmo inapropiado y luego cambia, obviamente no sería irrazonable esperar grandes ganancias relativas.
Allan P. Engsig-Karup
1
@Allan: Si hubo un factor de 10,000 para obtener de un solo cambio, entonces obviamente fue una implementación mal elegida. El código anterior se vio afectado tanto por el espacio innecesario como por la complejidad del tiempo: el rendimiento del almacenamiento en caché fue abismal. Pero ese es el punto, ¿no?
dmckee --- ex gatito moderador
8

¿Cómo definirías "optimizar"? Existe un espectro completo desde el desarrollo de mejores algoritmos o modelos computacionales hasta el uso de ensamblador sintonizado a mano.

En mi opinión y experiencia, la fruta de bajo perfil está en algún lugar en el medio, por ejemplo, elegir un algoritmo que se adapte mejor a la arquitectura informática subyacente. El algoritmo no necesariamente tiene que ser novedoso y su comprensión de la arquitectura subyacente no necesariamente tiene que ser muy específica, p. Ej.

  • Si sabe que su arquitectura admite SIMD, vuelva a estructurar el cálculo de modo que sus operaciones puedan escribirse en términos de vectores cortos,
  • Si sabe que su arquitectura es una computadora multinúcleo, intente descomponer su tarea computacional en subtareas individuales que no interfieran entre sí y ejecutarlas en paralelo (piense en un DAG de sus subtareas) ,
  • Si su arquitectura subyacente tiene una GPU, piense en formas en que puede reformular su cálculo como un grupo de subprocesos que marchan a través de los datos en paso de bloqueo,
  • etc ...

Se puede acceder a todas las características anteriores, por ejemplo, SIMD, paralelismo y GPU, sin demasiado conocimiento de bajo nivel, pero solo ofrecen una ventaja en algoritmos que pueden explotarlas fácilmente.

Pedro
fuente
4

Estoy de acuerdo con todas las respuestas ya presentadas hasta ahora ... Solo quiero abordar un aspecto más ignorado de la optimización del código: la expectativa de calidad.

El problema de la optimización del código generalmente surge cuando el usuario intenta resolver problemas cada vez más grandes y el código es insuficiente para satisfacer las necesidades / expectativas del usuario. La cantidad de tiempo que uno debe invertir en la optimización del código depende de la demanda para cumplir con esta expectativa. Sin duda vale la pena invertir un tiempo considerable si existe una necesidad crítica de una ventaja competitiva (por ejemplo, finalizar y publicar su investigación sobre un tema candente antes que otros).

Por supuesto, cuánto tiempo debe invertirse depende de qué tan rápido lo necesite y qué tan portátil desee que sea el código. A menudo, estas dos necesidades están en conflicto entre sí, y debe decidir cuál es más importante antes de comenzar la optimización. Cuanto más portátil lo desee, más tendrá que confiar en los cambios de diseño de alto nivel en el código (algoritmo / estructura de datos). Cuanto más rápido desee que se ejecute el código, debe ajustarse con optimizaciones de bajo nivel específicas para una máquina en particular (por ejemplo, optimizaciones de código / compilador / tiempo de ejecución).

Paul
fuente
4

Tendrá que hacer el análisis (costo) de gastar tantos meses-hombre (y esos siempre son míticos :-)) para ganar velocidad de ejecución. Tendrá que calcular cuántas veces se utilizará este software y cuántas personas utilizarán para poder estimar la ganancia.

La regla general, como siempre, es la famosa regla 80/20. En algún momento, simplemente no suma más pasar más y más tiempo ganando pocos porcentajes (o menos) de tiempo de ejecución. Pero tendrás que analizar.

Y estoy sinceramente de acuerdo con los carteles anteriores: asegúrese de que su API esté bien pensada para que no necesite muchos cambios y asegúrese de que el código sea portátil y fácil de mantener (piense en tener que volver a analizar un algoritmo que escribió y en detalle) optimizado hace diez años). Y asegúrese de utilizar buenas prácticas de programación y bibliotecas estándar. Es probable que alguien ya haya pensado en el algoritmo más eficiente para su aplicación.

Para citar a Donald Knuth: "la optimización prematura es la raíz de todo mal". Así que perfile su código, pero no demasiado pronto.

GertVdE
fuente
¿Te refieres a la regla del Principio de Pareto (80/20)? Si es así, ¿quiere decir que deberíamos centrar los esfuerzos de optimización en el 20% del código que produce el 80% de la desaceleración? ¿O quiere decir que si puede esperar solo un 20% de aceleración, entonces no vale la pena optimizarlo?
Paul
No, solo lo usé como una especie de principio, no exactamente 80/20. En algún momento, gastará tanto esfuerzo en obtener solo unos pocos porcentajes que ya no vale la pena.
GertVdE
3

Algunos consejos adicionales:

  1. Antes de realizar cualquier optimización de un programa de trabajo, asegúrese de tener un buen conjunto de casos de prueba que ayuden a mantener la integridad del código. No tiene sentido obtener resultados incorrectos más rápido.
  2. Si su optimización hace que el código sea menos legible, mantenga la versión original, al menos en forma de un comentario, pero mejor como una versión alternativa para seleccionar en tiempo de compilación y tiempo de ejecución. Sus necesidades de optimización pueden cambiar a medida que sus problemas y sus máquinas evolucionen, y el código original puede ser un mejor punto de partida para la optimización que hará dentro de cinco años.
  3. Si su versión optimizada resulta tener un impacto mínimo, pero hace que el código sea menos legible, menos universal o menos estable, vuelva a la versión original. Pierdes más de lo que ganas.
Khinsen
fuente