A volte hai solo algoritmi che non possono essere migliori del tempo lineare per i quali c'è ancora una forte domanda di prestazioni.
Un esempio è l'elaborazione video in cui non è possibile rendere l'immagine / un fotogramma più luminoso come esempio di base senza scorrere tutti i pixel (beh, suppongo che tu possa con una sorta di struttura gerarchica che indica le proprietà ereditate dai bambini che alla fine scendono nelle tessere dell'immagine per i nodi foglia, ma poi rinvieresti un costo più elevato per il ciclo attraverso ogni pixel al renderer e il codice sarebbe probabilmente più difficile da mantenere rispetto al filtro immagine più micro-ottimizzato).
Ci sono molti casi del genere nel mio campo. Tendo a fare più cicli di complessità lineare che devono toccare tutto o leggere tutto di quelli che beneficiano di qualsiasi tipo di sofisticata struttura o algoritmo di dati. Non c'è lavoro che possa essere saltato quando tutto deve essere toccato. Quindi, a quel punto, se inevitabilmente hai a che fare con la complessità lineare, devi rendere il lavoro svolto per iterazione sempre più economico.
Quindi nel mio caso le ottimizzazioni più importanti e comuni sono spesso rappresentazioni di dati e layout di memoria, multithreading e SIMD (in genere in questo ordine con la rappresentazione dei dati è la più importante, poiché influisce sulla capacità di eseguire le ultime due). Non sto incontrando così tanti problemi che vengono risolti da alberi, tabelle hash, algoritmi di ordinamento e cose di quel tipo. Il mio codice giornaliero è più nella vena di "per ogni cosa, fai qualcosa".
Naturalmente è un altro caso di cui parlare quando sono necessarie ottimizzazioni (e soprattutto, quando non lo sono), micro o algoritmiche. Ma nel mio caso particolare, se un percorso di esecuzione critico necessita di ottimizzazione, i guadagni di velocità 10x + sono spesso raggiunti da ottimizzazioni a micro livello come multithreading, SIMD e riorganizzazione di layout di memoria e schemi di accesso per una migliore località di riferimento. Non è così spesso che riesco, ad esempio, a sostituire un ordinamento a bolle con un introsort o un ordinamento radix o un rilevamento di collisione con complessità quadratica con un BVH, piuttosto che trovare hotspot che, diciamo, traggono vantaggio dalla divisione del campo caldo / freddo.
Ora nel mio caso il mio campo è così critico per le prestazioni (raytracing, motori fisici, ecc.) Che un raytracer lento ma perfettamente corretto che impiega 10 ore per il rendering di un'immagine viene spesso considerato inutile o più di uno veloce che è completamente interattivo ma produce le immagini più brutte con raggi che perdono ovunque a causa della mancanza di un raggio a tenuta stagna / tri intersezione. La velocità è probabilmente la principale metrica di qualità di tale software, probabilmente anche più della correttezza fino ad un certo punto (poiché la "correttezza" è un'idea sfocata con raytracing poiché tutto è approssimativo, purché non si blocchi o qualcosa del genere). E in questo caso, se non penso all'efficienza in anticipo, trovo che devo effettivamente cambiare il codice al livello di progettazione più costoso per gestire progetti più efficienti. Quindi se non
Il gioco è un altro campo simile al mio. Non importa quanto sia corretta la logica del tuo gioco o quanto sia gestibile e brillantemente ingegnosa la tua base di codice se il tuo gioco gira a 1 frame al secondo come una presentazione. In alcuni campi la mancanza di velocità potrebbe effettivamente rendere l'applicazione inutile per i suoi utenti. A differenza dei giochi, non esiste una metrica "abbastanza buona" in aree come il raytracing. Gli utenti vogliono sempre più velocità e la concorrenza industriale è principalmente alla ricerca di soluzioni più veloci. Non sarà mai abbastanza buono fino a quando non sarà in tempo reale, a quel punto i giochi useranno i tracciatori di tracciati. E quindi probabilmente non sarà ancora abbastanza buono per VFX, da allora gli artisti potrebbero voler caricare miliardi di poligoni e simulazioni di particelle con auto-collisione tra miliardi di particelle a oltre 30 FPS.
Ora, se è di qualche conforto, nonostante ciò scrivo ancora circa il 90% del codice in un linguaggio di scripting (Lua) senza alcuna preoccupazione per le prestazioni. Ma ho una quantità insolitamente grande di codice che in realtà ha bisogno di scorrere da milioni a miliardi di cose, e quando fai scorrere da milioni a miliardi di cose, inizi a notare un'epica differenza tra ingenuo codice a thread singolo che invoca un errore cache con ogni iterazione rispetto a dire, codice vettoriale in esecuzione in parallelo accedendo a blocchi contigui in cui nessun dato irrilevante viene caricato in una riga della cache.