Domanda

Profilatura in C++ numero scricchiolio codice con entrambi gprof e kcachegrind dà risultati simili per le funzioni che contribuiscono di più al tempo di esecuzione (50-80% a seconda dell'input), ma per le funzioni tra il 10-30% entrambi questi strumenti danno risultati diversi.Significa che uno di loro non è affidabile?Cosa sarebbe yo fare qui?

È stato utile?

Soluzione

gprof in realtà è abbastanza primitiva.Ecco quello che fa.1) campioni il contatore di programma, a velocità costante e racconta di come molti campioni di terra in ogni funzione (esclusiva di tempo).2) conta quante volte la funzione chiama qualsiasi funzione B.Dal che si può scoprire come molte volte ogni funzione è stata chiamata in totale, e ciò che è la media esclusiva di tempo è stato.Per ottenere la media di tempo inclusivo di ogni funzione si propaga esclusivo volta verso l'alto nel grafico di chiamata.

Se sei in attesa di questo per avere un qualche tipo di precisione, si deve essere consapevoli di alcuni problemi.Prima, conta solo CPU-tempo-in-processo, il che significa che è cieco di I/O o altre chiamate di sistema.Secondo, la ricorsione si confonde.Terzo, la premessa che funzioni sempre rispettare un tempo medio di esecuzione, non importa quando sono chiamati o che li chiama, è molto sospetto.Di seguito, il concetto che funzioni (e la loro chiamata grafico) sono di che cosa avete bisogno di sapere circa, piuttosto che di linee di codice, è semplicemente un popolare ipotesi, niente di più.Quinto, la nozione che la precisione di misura è anche pertinenti per la ricerca di "colli di bottiglia" è anche a popolare ipotesi, niente di più.

Callgrind può funzionare a livello di linee - questo è un bene.Purtroppo condivide gli altri problemi.

Se il tuo obiettivo è trovare dei "colli di bottiglia" (invece di ottenere in generale, le misure), si dovrebbe dare un'occhiata all'orologio da parete tempo stack campionatori report per cento-da-line, come Zoom.La ragione è semplice, ma forse non conosce.

Si supponga di avere un programma con un sacco di funzioni chiamando l'un l'altro che prende un totale di 10 secondi.Inoltre, c'è un sampler campioni, non solo il contatore di programma, ma l'intero stack di chiamate, e si fa tutto il tempo, a velocità costante, come 100 volte al secondo.(Ignorare altri processi per ora).

Quindi alla fine hai 1000 campioni dello stack di chiamate.Scegli una qualsiasi riga di codice L che appare in più di uno di loro.Suppongo che si possa in qualche modo ottimizzare la linea, evitando, così, la rimozione di esso, o il passaggio a un veramente, ma veramente, processore veloce.

Che cosa sarebbe successo a quei campioni?

Dal momento che la linea di codice L ora prende (essenzialmente) nessun tempo, nessun campione può colpire, in modo che i campioni sarebbe solo scompaiono, riducendo il numero totale di campioni, e quindi il tempo totale!Infatti la durata complessiva sarà ridotta la frazione di tempo che L era stato nello stack, che è all'incirca la frazione di campioni che lo conteneva.

Non voglio entrare troppo nel statistico, ma molte persone pensano che avete bisogno di un sacco di campioni, perché pensano che la precisione di misura è importante.Non lo è, se il motivo per cui stai facendo questo per scoprire cosa correggere per ottenere un aumento di velocità.L'enfasi è sulla ricerca cosa correggere, non misura si.La linea L è in pila per qualche frazione F di tempo, giusto?Così ogni campione ha una probabilità F di colpo, giusto?Come lanciare una moneta.C'è una teoria di questo, chiamato Regola di Successione.Si dice che (sotto semplificando, ma in generale ipotesi), se si lancia una moneta N volte, e vedere le "teste" S volte, è possibile stimare la correttezza della moneta F (in media) (S+1)/(N+2).Così, se si prende come pochi come tre campioni, e vedere L su due di loro, sai che F è? Naturalmente non. Ma si fare sapere in media è (2+1)/(3+2) o 60%.Quindi, questo è come si può salvare (in media) da "ottimizzazione di distanza" linea di L.E, naturalmente, lo stack campioni ha mostrato esattamente se la linea L (il "collo di bottiglia"**) è.Non e ' davvero importante, ma non è che si misura a due o tre cifre decimali?

BTW, è immune a tutti gli altri problemi di cui sopra.

**Continuo a mettere le virgolette intorno a "collo di bottiglia" perché è ciò che rende la maggior parte del software lento, non ha nulla in comune con il collo di una bottiglia.Una migliore metafora è un "scarico" - qualcosa che inutile spreco di tempo.

Altri suggerimenti

dati di sincronizzazione di gprof è statistica (letto in dettagli di profilazione documenti ).

D'altra parte, KCacheGrind utilizza valgrind che in realtà interpreta tutto il codice.

Quindi KCacheGrind può essere "più precisa" (a scapito di ulteriori spese generali) se la CPU modellato da valgrind è vicino al vostro CPU reali.

Quale scegliere dipende anche da che tipo di spese generali si può gestire. Nella mia esperienza, gprof aggiunge un carico minore di esecuzione (tempo di esecuzione che è), ma è più invadente (cioè -pg aggiunge il codice per tutti e di ciascuno delle vostre funzioni). Quindi, a seconda della situazione, o l'altro è più appropriata.

Per i dati "migliori" gprof, eseguire il codice più a lungo (e sulla più ampia gamma di dati di test si può). Più ne hai, meglio le misure saranno statisticamente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top