2011-01-11 12 views
5

In realtà, sto cercando una buona funzione che misuri accuratamente i cicli temporali per una determinata funzione C# nel sistema operativo Windows. Ho provato a queste funzioni, ma entrambi non ottengo misura accurata:Qual è il modo migliore per misurare i cicli temporali per una funzione C#?

DateTime StartTime = DateTime.Now;  
TimeSpan ts = DateTime.Now.Subtract(StartTime); 
Stopwatch stopWatch = new Stopwatch(); 
stopWatch.Start(); 
//code to be measured 
stopWatch.Stop(); 
TimeSpan ts = stopWatch.Elapsed; 

Davvero, ogni volta che li chiamo, mi danno il tempo differente per la stessa funzione

Per favore, se qualcuno sa modo migliore per misurare il tempo in modo accurato, per favore aiutatemi e grazie mille alot

risposta

7

Il cronometro è il modo consigliato per misurare il tempo necessario per una funzione da eseguire. Non sarà mai più la stessa dall'inizio alla fine a causa di vari fattori software e hardware, motivo per cui l'analisi delle prestazioni viene solitamente eseguita su un numero elevato di esecuzioni e il tempo medio viene calcolato.

+0

Grazie per la tua risposta ... Invece di prendere tempo medio lungo un numero elevato di esecuzioni, hai sentito in qualche modo di misurare solo i cicli di clock del mio processo di codice senza essere influenzato da altri processi? – Duaa

4

"mi danno un orario diverso per la stessa funzione" - è previsto. Le cose fluttuano perché non sei l'unico processo in esecuzione su un sistema.

Esegui il codice che desideri temporizzare su un grande loop per ridurre al minimo le fluttuazioni (dividi il tempo totale per il numero di cicli).

Stopwatch è un timer preciso ed è più che adeguato per la maggior parte delle situazioni.

const int numLoops = 1000000; // ...or whatever number is appropriate 

Stopwatch stopWatch = new Stopwatch(); 
stopWatch.Start(); 

for (int i = 0; i < numLoops; i++) 
{ 
    // code to be timed... 
} 

stopWatch.Stop(); 
TimeSpan elapsedTotal = stopWatch.Elapsed; 
double timeMs = elapsedTotal.TotalMilliseconds/numLoops; 
+0

+1 e ho sempre impostato la priorità del processo/filetto corrente al massimo durante la misurazione. –

+0

Grazie per la tua risposta, ma non penso di poter ripetere il mio codice in 1000000 volte, perché il mio codice è lungo, sarà troppo tempo ad aspettare ... C'è un modo per misurare solo i cicli di clock del mio processo di codice senza essere influenzato da altri processi? – Duaa

+0

riduci la dimensione del loop diciamo 1000, o 10000 –

1

Il gold-standard è quello di utilizzare StopWatch. È un timer ad alta risoluzione e funziona molto bene.

Io suggerirei di controllare il tempo trascorso utilizzando .Elapsed.TotalMilliSeconds come si ottiene un double piuttosto che .Elapsed.MilliSeconds che vi dà un int. Questo potrebbe farti perdere i risultati.

Inoltre, è possibile che durante i test di temporizzazione si verifichino raccolte di dati inutili che possono modificare in modo significativo il tempo risultante. È utile controllare il conteggio delle raccolte GC prima e dopo il test di cronometraggio e scartare il risultato se si sono verificate raccolte di dati inutili.

In caso contrario i risultati possono variare semplicemente perché altri thread e processi assumono la CPU e altre risorse di sistema durante i test. Non c'è molto che puoi fare qui ad eccezione di eseguire i tuoi test più volte e analizzare statisticamente i tuoi risultati calcolando media & intervalli di deviazioni standard ecc.

Spero che questo aiuti.

+0

Grazie per la tua risposta ... Invece di prendere tempo medio lungo un gran numero di corse, hai sentito in qualche modo di misurare solo i cicli di clock del mio processo di codice senza essere influenzato da altri processi? – Duaa

+0

@Duaa - AFAIK non c'è modo di garantire che questo è il caso in quanto è necessario i processi del sistema operativo per consentire l'esecuzione del codice in primo luogo. Se potessi fermarli, il tuo codice si fermerebbe anche tu e non saresti in grado di fare i tempi. Devi consentire gli altri processi e thread nei tuoi test. Questo è il motivo per cui è necessario utilizzare le statistiche. – Enigmativity

+0

Grazie per la vostra risposta – Duaa

1

Mentre è possibile misurare il codice in cicli di clock, sarà comunque incline alla variabilità come la misurazione in secondi e sarà molto meno utile (perché i secondi sono altrettanto buoni, se non addirittura migliori, unità di misura rispetto ai cicli di clock). L'unico modo per ottenere una misurazione che non sia influenzato da altri processi è quello di garantire che nessuno sia in esecuzione, e non è possibile farlo su Windows - il sistema operativo stesso verrà sempre eseguito facendo alcune cose, perché non è un sistema operativo a processo singolo .

Il più vicino possibile raggiungere la misurazione che si desidera è creare e gestire il codice as described here. È quindi possibile visualizzare l'assembly x86 per il codice JIT per i metodi che si desidera impostare impostando un punto di interruzione all'inizio del codice e quindi passare attraverso. È possibile eseguire il rimando incrociato di ogni istruzione x86 con i relativi tempi di ciclo nei manuali dell'architettura Intel e aggiungerli per ottenere un conteggio accurato del ciclo.

Questo è, ovviamente, estremamente doloroso e sostanzialmente inutile. Potrebbe anche essere invalidato dalle modifiche al codice che fanno sì che il JIT adotti approcci leggermente diversi alla produzione di x86 dal tuo IL.

+0

Grazie per la vostra risposta – Duaa

0

Per echeggiare gli altri: la classe di cronometro è il modo migliore per farlo.

Per rispondere alle vostre domande sulla misurazione dei cicli di clock: il fatto che si stia utilizzando un sistema operativo multitasking su un processore moderno rende la misurazione dei cicli di clock quasi inutile. Un commutatore di contesto ha una buona possibilità di rimuovere il codice e i dati dalla cache del processore e il sistema operativo potrebbe decidere di sostituire il lavoro impostato nel frattempo.

Il processore può decidere di riordinare le istruzioni in base alle attese di cache o agli accessi alla memoria ed eseguire ciò che può mentre è in attesa. O potrebbe non esserlo se è nella cache.

Quindi, in breve, l'esecuzione di più esecuzioni e la loro mediazione è davvero l'unica strada da percorrere.

Per ottenere meno jitter nel tempo, è possibile elevare la priorità del thread/processo, ma ciò può comportare una serie di altri problemi (Bumping alla priorità in tempo reale e rimanere bloccati in un ciclo lungo sarà essenzialmente interrompere tutte le altre elaborazioni.Se si verifica un errore e si rimane bloccati in un ciclo infinito, l'unica scelta è il pulsante di ripristino) e non è consigliata affatto, soprattutto in un computer degli utenti o in un ambiente di produzione. E dal momento che non puoi farlo quando è importante, rende i parametri di riferimento che corri nella tua macchina, con eventuali modifiche prioritarie, non validi.

+0

Grazie per la vostra risposta – Duaa

1

È necessario il profiler per misurare l'esecuzione del codice (vedere What Are Some Good .NET Profilers? per avviare la ricerca).

Guardando i vostri commenti non è chiaro cosa si sta cercando di ottimizzare. In genere è necessario scendere per misurare i cicli di clock della CPU quando il codice viene eseguito migliaia di volte e limitato alla CPU, in altri casi il tempo di esecuzione per funzione di solito è sufficiente. Ma stai dicendo che il tuo codice è troppo lento per essere eseguito tante volte per calcolare il tempo medio con il cronometro.

È inoltre necessario capire se la CPU è il collo di bottiglia per l'applicazione o c'è qualcos'altro che lo rende lento. Guardare la CPU% in TaskManager può darti informazioni su di esso - meno del 100% di utilizzo della CPU praticamente garantisce che ci sia qualcos'altro (cioè attività di rete o del disco) che rallenta il programma.

In sostanza, fornire più dettagli sul tipo di codice che si tenta di misurare per soddisfare i propri obiettivi di prestazioni ti aiuterà molto più facilmente.

+0

Grazie per la vostra risposta ... quello che sto provando a misurare il suo tempo è un algoritmo di corrispondenza delle stringhe modificato che ho programmato in C# e voglio confrontare le sue prestazioni con altri algoritmi di corrispondenza delle stringhe, in particolare per il parametro di misurazione del tempo, per garantire che il mio algoritmo di corrispondenza delle stringhe modificato sia più veloce di altri ... grazie mille – Duaa

0

come utilizzare Environment.TickCount per acquisire l'inizio e la fine e quindi su TimeSpan.FromTicks()?

Problemi correlati