Per me è importante un tempismo accurato e ho studiato i 3 tipi di orologi specificati in C++ 11, ovvero , steady_clock
e high_resolution_clock
. La mia preoccupazione iniziale era verificare se ci sono differenze nell'overhead delle chiamate ai diversi tipi di clock e controllare la risoluzione di ciascun tipo di orologio. Ecco il mio programma di esempio:C++ 11 orologi: g ++ steady_clock :: is_steady == false?
#include <chrono>
#include <cstdio>
using namespace std;
using namespace std::chrono;
int main(int argc, char **argv)
{
size_t N = 1e6;
if(2 == argc) {
sscanf(argv[1], "%zu", &N);
}
#if defined(hrc)
typedef high_resolution_clock clock;
#warning "High resolution clock"
#elif defined(sc)
typedef steady_clock clock;
#warning "Steady clock"
#elif defined(sys)
typedef system_clock clock;
#warning "System clock"
#endif
const double resolution = double(clock::period::num)/double(clock::period::den);
printf("clock::period: %lf us.\n", resolution*1e6);
printf("clock::is_steady: %s\n", clock::is_steady ? "yes" : "no");
printf("Calling clock::now() %zu times...\n", N);
// first, warm up
for(size_t i=0; i<100; ++i) {
time_point<clock> t = clock::now();
}
// loop N times
time_point<clock> start = clock::now();
for(size_t i=0; i<N; ++i) {
time_point<clock> t = clock::now();
}
time_point<clock> end = clock::now();
// display duration
duration<double> time_span = duration_cast<duration<double>>(end-start);
const double sec = time_span.count();
const double ns_it = sec*1e9/N;
printf("That took %lf seconds. That's %lf ns/iteration.\n", sec, ns_it);
return 0;
}
compilo con
$ g++-4.7 -std=c++11 -Dhrc chrono.cpp -o hrc_chrono
chrono.cpp:15:2: warning: #warning "High resolution clock" [-Wcpp]
$ g++-4.7 -std=c++11 -Dsys chrono.cpp -o sys_chrono
chrono.cpp:15:2: warning: #warning "System clock" [-Wcpp]
$ g++-4.7 -std=c++11 -Dsc chrono.cpp -o sc_chrono
chrono.cpp:15:2: warning: #warning "Steady clock" [-Wcpp]
ho compilato con G ++ 4.7.2, e corse su
- SUSE Linux, il kernel v3.1.10 , CPU i7
- Sistema embedded Angstrom Linux, kernel v3.1.10, MCU Tegra 2 (ARM Cortex A9).
La prima cosa sorprendente è che i 3 tipi di orologio sono apparentemente sinonimi. Hanno tutti lo stesso periodo (1 microsecondo) e il tempo/chiamata è praticamente lo stesso. Che senso ha specificare 3 tipi di orologi se sono tutti uguali? È solo perché l'implementazione G ++ di chrono
non è ancora matura? O forse il kernel 3.1.10 ha solo un orologio accessibile all'utente?
La seconda sorpresa, e questo è enorme, è che steady_clock :: is_steady == false. Sono abbastanza certo che, per definizione, quella proprietà dovrebbe essere vera. Cosa dà ?? Come posso aggirarlo (vale a dire, ottenere un orologio costante)?
Se è possibile eseguire il programma semplice su altre piattaforme/compilatori, sarei molto interessato a conoscere i risultati. Se qualcuno si chiede, è di circa 25 ns/iterazione sul mio Core i7, e 1000 ns/iterazione del Tegra 2.
Umm, sì. Sto solo compilando il codice 3 volte, una volta per ogni tipo di orologio, che è specificato dal flag '-DXXX'. L'ultimo argomento per 'g ++' è solo il nomefile dell'eseguibile, che non importa una leccata. (anche se ho riflettuto sia sul tipo di orologio che sul fatto che il programma stia esercitando la libreria chrono.) –
Mi spiace, ho completamente letto male la riga di comando –