Q1: quali strumenti stai usando per la profilazione del codice (profiling, non benchmarking)?
Q2: per quanto tempo si lascia il codice in esecuzione (statistiche: quanti passaggi temporali)?
D3: Quanto sono grandi i casi (se il caso si adatta alla cache, il risolutore è più veloce degli ordini di grandezza, ma poi mi mancheranno i processi relativi alla memoria)?
Ecco un esempio di come lo faccio.
Separo il benchmarking (vedendo quanto tempo impiega) dalla profilazione (identificando come renderlo più veloce). Non è importante che il profiler sia veloce. È importante che ti dica cosa risolvere.
Non mi piace nemmeno la parola "profiling" perché evoca un'immagine simile a un istogramma, dove c'è una barra dei costi per ogni routine o "collo di bottiglia" perché implica che c'è solo un piccolo spazio nel codice che deve essere fisso. Entrambe queste cose implicano una sorta di tempistica e statistiche, per le quali si ritiene che la precisione sia importante. Non vale la pena rinunciare alla comprensione dell'accuratezza dei tempi.
L'utilizzo metodo che è pausa a caso, e c'è un caso di studio e slide-show completo qui . Parte della visione del mondo del collo di bottiglia del profiler è che se non trovi nulla, non c'è nulla da trovare, e se trovi qualcosa e ottieni una certa percentuale di accelerazione, dichiari la vittoria e esci. I fan del profiler non dicono quasi mai quanto accelerano e gli annunci mostrano solo problemi artificialmente concepiti per essere facili da trovare. La pausa casuale rileva i problemi, facili o difficili. Quindi risolvere un problema espone altri, in modo che il processo possa essere ripetuto, per ottenere una maggiore velocità.
Nella mia esperienza di numerosi esempi, ecco come procede: posso trovare un problema (facendo una pausa casuale) e risolverlo, ottenendo una velocità di alcuni percento, diciamo del 30% o 1,3x. Quindi posso farlo di nuovo, trovare un altro problema e risolverlo, ottenendo un altro aumento di velocità, forse meno del 30%, forse di più. Quindi posso farlo di nuovo, più volte fino a quando non riesco davvero a trovare nient'altro da risolvere. L'ultimo fattore di accelerazione è il prodotto corrente dei singoli fattori e può essere incredibilmente grande - in alcuni casi ordini di grandezza.
INSERITO: Giusto per illustrare quest'ultimo punto. C'è un esempio dettagliato qui , con slide show e tutti i file, che mostra come è stata raggiunta una velocità di 730x in una serie di rimozioni di problemi. La prima versione impiegava 2700 microsecondi per unità di lavoro. Il problema A è stato rimosso, portando il tempo a 1800 e aumentando le percentuali di problemi rimanenti di 1,5x (2700/1800). Quindi B è stato rimosso. Questo processo è proseguito attraverso sei iterazioni, determinando una velocità di quasi 3 ordini di grandezza. Ma la tecnica di profilazione deve essere davvero efficace, perché se uno di questi problemi non viene rilevato, ovvero se si raggiunge un punto in cui si ritiene erroneamente che non si possa fare più nulla, il processo si blocca.
INSERITO: Per dirla in altro modo, ecco un grafico del fattore di accelerazione totale man mano che vengono rimossi problemi successivi:
Quindi per Q1, per il benchmarking è sufficiente un semplice timer. Per la "profilazione" uso una pausa casuale.
D2: Gli do un carico di lavoro sufficiente (o semplicemente ci giro attorno) in modo che funzioni abbastanza a lungo da mettere in pausa.
D3: Assicura un carico di lavoro realisticamente elevato in modo da non perdere i problemi di cache. Questi verranno visualizzati come esempi nel codice che esegue il recupero della memoria.