2010-02-19 10 views

risposta

4

Ho implementato un timer per situazioni come questa prima: in realtà ho finito con una classe con due diverse implementazioni, una per Windows e una per POSIX.

Il motivo era che Windows ha la funzione QueryPerformanceCounter() che consente di accedere a un orologio molto accurato, ideale per tali tempi.

Su POSIX tuttavia questo non è disponibile, quindi ho usato solo le classi boost.datetime per memorizzare le ore di inizio e di fine, quindi ho calcolato la durata da quelle. Offre un timer "ad alta risoluzione" ma la risoluzione non è definita e varia da piattaforma a piattaforma.

1

timer ad alta precisione sono specifici della piattaforma e così non sono specificati dallo standard C++, ma ci sono librerie disponibili. Vedi this question per una discussione.

0

Questo potrebbe essere un problema dipendente dal sistema operativo piuttosto che un problema di lingua.

Se siete su Windows, allora è possibile accedere a un timer millisecondo 10 ai 16 millisecondi attraverso GetTickCount() o GetTickCount64(). Chiamalo una volta all'inizio e una volta alla fine e sottrai.

Era quello che usavo prima se ricordo male. Anche la pagina collegata ha altre opzioni.

+0

fa GetTickCount() utilizzare QueryPerformanceCounter() sotto il cappuccio o? – Mithrax

+0

Che io non sappia. Ho aggiunto un collegamento alla pagina GetTickCount() e sembra che tu abbia altre opzioni, probabilmente migliori, basate su ciò che è presente. – John

+0

No. GetTickCount() non è accurato. Se si desidera un conteggio accurato, è necessario utilizzare QueryPerformanceCounter() (EDIT: per inaccurato intendo +/- 10 ms) –

0
#include <time.h> 

clock_t start, end; 
start = clock(); 
//Do stuff 
end = clock(); 

printf("Took: %f\n", (float)((end - start)/(float)CLOCKS_PER_SEC)); 
+0

Funzionerebbe ma la risoluzione sarà scarsa. –

+0

Questo non sarebbe effettivamente lavorare per misurare il tempo assoluto, in quanto 'clock()' restituisce solo il tempo di CPU che ** ** il codice ha preso. Pertanto, se si sostituisce '\\ Non stuff' con' usleep (1000000) 'printf tornerà 0.0000 secondi invece di 1 secondo. – CodingAway

3

Uso la mia versione della funzione time_it di Python. Il vantaggio di questa funzione è che ripete un calcolo tante volte quanto è necessario per ottenere risultati significativi. Se il calcolo è molto veloce, verrà ripetuto molte volte. Alla fine si ottiene il tempo medio di tutte le ripetizioni. Esso non utilizza alcuna funzionalità non standard:

#include <ctime> 

double clock_diff_to_sec(long clock_diff) 
{ 
    return double(clock_diff)/CLOCKS_PER_SEC; 
} 

template<class Proc> 
double time_it(Proc proc, int N=1) // returns time in microseconds 
{ 
    std::clock_t const start = std::clock(); 
    for(int i = 0; i < N; ++i) 
     proc(); 
    std::clock_t const end = std::clock(); 
    if(clock_diff_to_sec(end - start) < .2) 
     return time_it(proc, N * 5); 
    return clock_diff_to_sec(end - start) * (1e6/N); 
} 

Il seguente esempio utilizza la funzione time_it per misurare le prestazioni di diversi contenitori STL:

void dummy_op(int i) 
{ 
    if(i == -1) 
     std::cout << i << "\n"; 
} 

template<class Container> 
void test(Container const & c) 
{ 
    std::for_each(c.begin(), c.end(), &dummy_op); 
} 

template<class OutIt> 
void init(OutIt it) 
{ 
    for(int i = 0; i < 1000; ++i) 
     *it = i; 
} 

int main(int argc, char ** argv) 
{ 
    { 
     std::vector<int> c; 
     init(std::back_inserter(c)); 
     std::cout << "vector: " 
        << time_it(boost::bind(&test<std::vector<int> >, c)) << "\n"; 
    }  
    { 
     std::list<int> c; 
     init(std::back_inserter(c)); 
     std::cout << "list: " 
        << time_it(boost::bind(&test<std::list<int> >, c)) << "\n"; 
    } 
    { 
     std::deque<int> c; 
     init(std::back_inserter(c)); 
     std::cout << "deque: " 
        << time_it(boost::bind(&test<std::deque<int> >, c)) << "\n"; 
    } 
    { 
     std::set<int> c; 
     init(std::inserter(c, c.begin())); 
     std::cout << "set: " 
        << time_it(boost::bind(&test<std::set<int> >, c)) << "\n"; 
    } 
    { 
     std::tr1::unordered_set<int> c; 
     init(std::inserter(c, c.begin())); 
     std::cout << "unordered_set: " 
      << time_it(boost::bind(&test<std::tr1::unordered_set<int> >, c)) << "\n"; 
    }  
} 

Nel caso qualcuno è curioso ecco l'uscita I get (compilato con VS2008 nella modalità di rilascio):

vettore: 8,7168

lista: 27,776

deque: 91,52

set: 103,04

unordered_set: 29.76

+0

Molto interessante. Sia per la funzione di cronometraggio che per l'intuizione sul diverso contenitore! Grazie. – Morlock

+0

@Morlock - Grazie! Vorrei prendere i tempi con un pizzico di sale, 'std :: deque' si comporta terribilmente in questa prova, ma sono sicuro che in un generale impostazione non è così male. – Manuel

3

Ho utilizzato boost::timer per misurare la durata di un'operazione. Fornisce un modo molto semplice per eseguire la misurazione e allo stesso tempo è indipendente dalla piattaforma. Ecco un esempio:

boost::timer myTimer; 
doOperation(); 
std::cout << myTimer.elapsed(); 

P.S. Per superare errori di precisione, sarebbe bello misurare le operazioni che richiedono alcuni secondi. Soprattutto quando stai cercando di confrontare diverse alternative. Se vuoi misurare qualcosa che richiede pochissimo tempo, prova a metterlo in un loop. Per esempio eseguire l'operazione di 1000 volte, e poi dividere il tempo totale per 1000.

0

Si possono trovare utile this classe.

Utilizzando Raii idioma, si stampa il testo dato in costruzione quando distruttore viene chiamato, riempiendo trascorso segnaposto tempo con il giusto valore.

Esempio di utilizzo:

int main() 
{ 
    trace_elapsed_time t("Elapsed time: %ts.\n"); 
    usleep(1.005 * 1e6); 
} 

uscita:

Elapsed time: 1.00509s. 
1

umilmente presentare la mia micro-benchmarking mini-library (on Github). E 'super semplice - l'unico vantaggio che ha su rotolare il proprio è che ha già il codice del timer ad alte prestazioni realizzato per Windows e Linux, e astrae il boilerplate fastidioso.

Basta passare una funzione (o lambda), il numero di volte che deve essere chiamato per prova di esecuzione (valore predefinito: 1) e il numero di esecuzioni di test (valore predefinito: 100). La prova più veloce (misurato in millisecondi frazionari) viene restituito:

// Example that times the compare-and-swap atomic operation from C++11 
// Sample GCC command: g++ -std=c++11 -DNDEBUG -O3 -lrt main.cpp microbench/systemtime.cpp -o bench 
#include "microbench/microbench.h" 

#include <cstdio> 
#include <atomic> 

int main() 
{ 
    std::atomic<int> x(0); 
    int y = 0; 

    printf("CAS takes %.4fms to execute 100000 iterations\n", 
     moodycamel::microbench(
      [&]() { x.compare_exchange_strong(y, 0); }, /* function to benchmark */ 
      100000, /* iterations per test run */ 
      100 /* test runs */ 
     ) 
    ); 

    // Result: Clocks in at 1.2ms (12ns per CAS operation) in my environment 

    return 0; 
} 
Problemi correlati