Come misurare la complessità in pratica nel tuo grande progetto software?


11

All'università, durante i nostri corsi sugli algoritmi, impariamo come calcolare con precisione la complessità di vari semplici algoritmi utilizzati nella pratica, come le tabelle hash o l'ordinamento rapido.

Ma ora in un grande progetto software, quando vogliamo renderlo più veloce, tutto ciò che facciamo è guardare singoli pezzi - alcuni loop annidati lì che possono essere sostituiti da una tabella hash più veloce, una ricerca lenta qui che può essere accelerata da una tecnica più elaborata, ma non calcoliamo mai la complessità di tutta la nostra pipeline.

C'è un modo per farlo? Oppure le persone in pratica si affidano semplicemente "localmente" a un algoritmo veloce, per rendere l'intera applicazione più veloce, anziché considerare globalmente l'applicazione nel suo insieme?

(Perché mi sembra non banale dimostrare che se si accumulano un gran numero di algoritmi che sono noti per essere molto veloci da soli, si finisce anche con un'applicazione veloce nel suo insieme.)

Lo sto chiedendo, perché ho il compito di accelerare un grande progetto scritto da qualcun altro, in cui molti algoritmi interagiscono e lavorano su dati di input, quindi non mi è chiaro come l'impatto di avere un singolo algoritmo più veloce su l'intera applicazione.


1) Ciò richiede un approccio di prova, per trovare i punti da migliorare. Test di benchmark, test di durabilità, test dinamici (monitorando le metriche di memoria / CPU di ciascun componente). 2) Dopo aver trovato i punti da migliorare, troverai la causa principale di tali punti. 3) Trova una soluzione per risolvere la causa principale, mantenendo la correttezza.
scambio eccessivo del

hai bisogno di alcuni strumenti per questi test menzionati al punto 1
scambio eccessivo del

1
L'analisi Big O non ti dice come funzionerà un algoritmo. Ti dice come ridimensioneranno le prestazioni , man mano che naumenta.
John Wu,

Risposte:


5

I grandi progetti software sono costituiti da molti componenti diversi e non tutti sono in genere un collo di bottiglia. Al contrario: per quasi tutti i programmi che ho visto nella mia vita in cui le basse prestazioni erano un problema, si applicava il principio di Pareto : oltre l'80% dei miglioramenti delle prestazioni può essere ottenuto ottimizzando meno del 20% del codice (in realtà, I penso che i numeri fossero spesso più del 95% al ​​5%).

Quindi iniziare a guardare singoli pezzi è spesso l'approccio migliore. Questo è il motivo per cui la profilazione (come spiegato nella risposta di David Arno ) va bene, poiché ti aiuta a identificare il 5% del codice menzionato in cui l'ottimizzazione ti darà il "massimo vantaggio per il dollaro". L'ottimizzazione di "l'intera applicazione" comporta un certo rischio di ingegnerizzazione eccessiva e se si ottimizza il 95% anche di un fattore 10, spesso non si avrebbe alcun effetto misurabile. Nota anche che la profilazione ti dice molto di più di qualsiasi ipotetica stima della complessità dell'algoritmo, dal momento che un semplice algoritmo che richiede passaggi O (N ^ 3) può essere ancora più veloce di un algoritmo complesso che richiede O (N log (N)) fintanto che N è abbastanza piccolo.

Dopo che la profilazione ha rivelato i punti caldi, è possibile ottimizzarli. Naturalmente, un "hot spot" può essere più grande di una o due righe di codice, a volte è necessario sostituire un intero componente per renderlo più veloce, ma in genere sarà comunque una piccola parte della base di codice in un programma più grande .

Le tecniche di ottimizzazione tipiche includono

  • migliorare l'uso di algoritmi e strutture di dati

  • messa a punto del primo

  • micro-ottimizzazioni in alcuni punti caldi reali

  • ricodifica di sezioni critiche utilizzando il codice assembly o CUDA

Nota che queste tecniche stanno lavorando su diversi livelli di astrazione, alcuni dei quali visualizzano un componente più "nel suo insieme" rispetto ad altri. Quindi dipende da cosa intendi per "tutto ciò che facciamo è guardare singoli pezzi" - se avevi in ​​mente solo micro-ottimizzazioni, non sono d'accordo sul fatto che "noi" lavoriamo solo su quello. Ma se intendi applicare quelle ottimizzazioni su larga scala su parti o componenti isolati, allora "noi" probabilmente stiamo lavorando sulle parti giuste e dovresti mettere in discussione le tue aspettative.


13

Il modo standard, provato e testato è di profilare il codice . Si esegue un'analisi dinamica del sistema in esecuzione per misurare i tempi, l'utilizzo della memoria, ecc. Quindi analizzare i risultati per trovare i colli di bottiglia delle prestazioni.

Tali strozzature vengono quindi riscritte sperimentalmente e il risultato viene nuovamente profilato per determinare che sono stati raggiunti un aumento di velocità, una riduzione dell'uso della memoria ecc. Questo processo viene quindi ripetuto fino a quando non si ottiene un guadagno in termini di prestazioni accettabile.


1
Questo risolve il problema delle prestazioni, motivo per cui lo facciamo, ma non risponde alla domanda originale. Penso che in particolare nel caso peggiore la complessità dello spazio o del tempo sarebbe meglio capire usando uno strumento statico di analisi del programma, che potrebbe mancare. I test delle prestazioni sono ottimi per scenari specifici, ma non ti dicono molto sulle peggiori situazioni possibili.
Frank Hileman,

3
@FrankHileman Penso che il punto qui sia che le prestazioni siano una preoccupazione pratica e possano essere misurate solo praticamente. Non usi la matematica per trovare il collo di bottiglia del tuo software, anche se potresti risolverlo una volta trovato usando la matematica (algoritmi).
Carattere jolly

In una nota correlata, nella presentazione di diapositive di una volta (diapositive di vetro), c'era un'intera tecnologia pretesa su come calcolare minuziosamente la densità media di una diapositiva lanterna per determinare matematicamente la luminosità della luce da usare. Completamente inutile: se l'immagine non si presenta bene, si ottiene una luce più luminosa!
Carattere jolly

@Wildcard Sebbene le prestazioni possano essere misurate solo in fase di esecuzione, possono essere previste staticamente. Una cattiva scelta di una struttura di dati può apparire soddisfacente, per quanto riguarda le prestazioni, nei test delle prestazioni, ma fallire miseramente in casi limite che potrebbero essere previsti in un'analisi statica. Questo è lo stesso motivo per cui analizziamo le analisi della complessità peggiore per le strutture di dati in generale.
Frank Hileman,

@Wildcard: hai ragione, tuttavia Frank ha anche ragione nel dire che questo post non risponde alla domanda.
Doc Brown,

3

Sebbene le altre risposte siano corrette e forniscano una guida, penso che manchino un passo. In un sistema complesso come quello con cui stai lavorando ora, comprendere i diversi componenti che compongono il sistema è la chiave per capire perché qualcosa è lento.

Il mio primo passo sarebbe quello di mettere le mani su un diagramma di architettura dettagliato o crearne uno da solo. Scopri quali passaggi vengono eseguiti dai componenti del software e quanto tempo richiede ogni passaggio.

Inoltre, scopri come i componenti interagiscono tra loro. Questo può fare la differenza.

Ad esempio, ho visto il codice in C # in cui l'interfaccia tra due componenti stava passando un IEnumerable creato dal primo componente, che è stato poi elencato dal secondo componente. In C # questo richiede il cambio di contesto, che può essere costoso in determinate circostanze. Risolverlo non ha alcun impatto sull'algoritmo. Un semplice .ToList () si assicura che il risultato sia raccolto prima che il passaggio successivo risolva questo problema.

Un'altra cosa da considerare è l'impatto sul sistema su cui si sta eseguendo il codice. Le interazioni hardware possono ovviamente essere un fattore in sistemi complessi. Cerca Disk IO, allocazioni di memoria di grandi dimensioni e Network IO. A volte questi possono essere risolti in modo più efficiente modificando il sistema o addirittura sostituendo l'hardware.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.