A veces solo tiene algoritmos que no pueden ser mejores que el tiempo lineal para el que todavía hay una fuerte demanda de rendimiento.
Un ejemplo es el procesamiento de video en el que no puede hacer que una imagen / marco sea más brillante como un ejemplo básico sin recorrer cada píxel (bueno, supongo que puede hacerlo con algún tipo de estructura jerárquica que indique las propiedades heredadas por los niños que finalmente descienden en mosaicos de imágenes para los nodos de hoja, pero luego diferiría un costo mayor de recorrer cada píxel hasta el renderizador y el código probablemente sería más difícil de mantener que incluso el filtro de imagen más micro optimizado).
Hay muchos casos como ese en mi campo. Tiendo a estar haciendo más bucles de complejidad lineal que tienen que tocar todo o leer todo que los que se benefician de cualquier tipo de estructura de datos sofisticada o algoritmo. No hay trabajo que se pueda omitir cuando hay que tocar todo. Entonces, en ese punto, si inevitablemente se trata de una complejidad lineal, debe hacer el trabajo por iteración cada vez más barato.
Entonces, en mi caso, las optimizaciones más importantes y comunes son a menudo representaciones de datos y diseños de memoria, subprocesos múltiples y SIMD (generalmente en este orden, siendo la representación de datos la más importante, ya que afecta la capacidad de hacer las dos últimas). No me encuentro con tantos problemas que se resuelven con árboles, tablas hash, algoritmos de clasificación y cosas por el estilo. Mi código diario está más en la línea de "para cada cosa, hacer algo".
Por supuesto, es otro caso para hablar cuando las optimizaciones son necesarias (y más importante, cuando no lo son), micro o algorítmicas. Pero en mi caso particular, si una ruta de ejecución crítica necesita optimización, las ganancias de velocidad de 10x + a menudo se logran mediante optimizaciones de micro nivel como subprocesos múltiples, SIMD y reorganizando diseños de memoria y patrones de acceso para mejorar la localidad de referencia. No es tan frecuente que, digamos, reemplace un tipo de burbuja con un introsort o una clasificación de radix o detección de colisión de complejidad cuadrática con un BVH tanto como encontrar puntos de acceso que, por ejemplo, se benefician de la división de campo caliente / frío.
Ahora, en mi caso, mi campo es tan crítico para el rendimiento (trazado de rayos, motores de física, etc.) que un rastreador lento pero perfectamente correcto que tarda 10 horas en representar una imagen a menudo se considera inútil o más que uno rápido que es completamente interactivo pero emite las imágenes más feas con rayos que se escapan por todas partes debido a la falta de rayos impermeables / tri intersección. Podría decirse que la velocidad es la métrica de calidad principal de dicho software, posiblemente incluso más que la corrección hasta cierto punto (ya que la "corrección" es una idea confusa con el trazado de rayos ya que todo es aproximado, siempre que no se bloquee ni nada de eso). Y cuando ese es el caso, si no pienso en la eficiencia por adelantado, encuentro que tengo que cambiar el código al nivel de diseño más costoso para manejar diseños más eficientes. Entonces si no lo hago
El juego es otro campo similar al mío. No importa cuán correcta sea la lógica de su juego o cuán sostenible y ingeniosamente diseñada sea su base de código si su juego se ejecuta a 1 fotograma por segundo como una presentación de diapositivas. En ciertos campos, la falta de velocidad podría hacer que la aplicación sea inútil para sus usuarios. A diferencia de los juegos, no existe una métrica "suficientemente buena" en áreas como el trazado de rayos. Los usuarios siempre quieren más velocidad, y la competencia industrial es predominantemente en la búsqueda de soluciones más rápidas. Nunca será lo suficientemente bueno hasta que sea en tiempo real, momento en el cual los juegos usarán trazadores de ruta. Y entonces probablemente todavía no sea lo suficientemente bueno para VFX, ya que entonces los artistas podrían querer cargar miles de millones de polígonos y tener simulaciones de partículas con auto-colisión entre miles de millones de partículas a más de 30 FPS.
Ahora, si te sirve de consuelo, a pesar de eso, todavía escribo alrededor del 90% del código en un lenguaje de script (Lua) sin ninguna preocupación por el rendimiento. Pero tengo una cantidad de código inusualmente grande que realmente necesita pasar de millones a miles de millones de cosas, y cuando estás pasando de millones a miles de millones de cosas, comienzas a notar una diferencia épica entre el ingenuo código de un solo hilo que invoca un error de caché con cada iteración frente a, digamos, código vectorizado que se ejecuta en paralelo y accede a bloques contiguos donde no se cargan datos irrelevantes en una línea de caché.