Aktualisierte Antwort auf eine alte Frage:
In C ++ 11 können Sie portabel zum Timer mit der höchsten Auflösung gelangen mit:
#include <iostream>
#include <chrono>
#include "chrono_io"
int main()
{
typedef std::chrono::high_resolution_clock Clock;
auto t1 = Clock::now();
auto t2 = Clock::now();
std::cout << t2-t1 << '\n';
}
Beispielausgabe:
74 nanoseconds
„chrono_io“ ist eine Erweiterung E / A - Probleme mit diesen neuen Typen zu erleichtern und ist frei verfügbar hier .
Es gibt auch eine Implementierung von <chrono>
Boost (möglicherweise immer noch an der Spitze des Trunks, nicht sicher, ob es veröffentlicht wurde).
Aktualisieren
Dies ist eine Reaktion auf Bens Kommentar unten, dass nachfolgende Aufrufe std::chrono::high_resolution_clock
in VS11 mehrere Millisekunden dauern sollen. Unten finden Sie eine <chrono>
kompatible Problemumgehung. Es funktioniert jedoch nur auf Intel-Hardware. Sie müssen in die Inline-Assembly eintauchen (die Syntax variiert je nach Compiler) und die Taktrate der Maschine fest mit der Uhr verbinden:
#include <chrono>
struct clock
{
typedef unsigned long long rep;
typedef std::ratio<1, 2800000000> period;
typedef std::chrono::duration<rep, period> duration;
typedef std::chrono::time_point<clock> time_point;
static const bool is_steady = true;
static time_point now() noexcept
{
unsigned lo, hi;
asm volatile("rdtsc" : "=a" (lo), "=d" (hi));
return time_point(duration(static_cast<rep>(hi) << 32 | lo));
}
private:
static
unsigned
get_clock_speed()
{
int mib[] = {CTL_HW, HW_CPU_FREQ};
const std::size_t namelen = sizeof(mib)/sizeof(mib[0]);
unsigned freq;
size_t freq_len = sizeof(freq);
if (sysctl(mib, namelen, &freq, &freq_len, nullptr, 0) != 0)
return 0;
return freq;
}
static
bool
check_invariants()
{
static_assert(1 == period::num, "period must be 1/freq");
assert(get_clock_speed() == period::den);
static_assert(std::is_same<rep, duration::rep>::value,
"rep and duration::rep must be the same type");
static_assert(std::is_same<period, duration::period>::value,
"period and duration::period must be the same type");
static_assert(std::is_same<duration, time_point::duration>::value,
"duration and time_point::duration must be the same type");
return true;
}
static const bool invariants;
};
const bool clock::invariants = clock::check_invariants();
Es ist also nicht tragbar. Wenn Sie jedoch mit einer hochauflösenden Uhr auf Ihrer eigenen Intel-Hardware experimentieren möchten, wird sie nicht feiner. Seien Sie gewarnt, die heutigen Taktraten können sich dynamisch ändern (sie sind nicht wirklich eine Konstante für die Kompilierungszeit). Und mit einer Multiprozessor-Maschine können Sie sogar Zeitstempel von verschiedenen Prozessoren erhalten. Trotzdem funktionieren Experimente mit meiner Hardware ziemlich gut. Wenn Sie mit der Millisekundenauflösung nicht weiterkommen, kann dies eine Problemumgehung sein.
Diese Uhr hat eine Dauer in Bezug auf die Taktrate Ihrer CPU (wie Sie es gemeldet haben). Dh für mich tickt diese Uhr einmal alle 1 / 2.800.000.000 Sekunden. Wenn Sie möchten, können Sie dies (zum Beispiel) in Nanosekunden umwandeln mit:
using std::chrono::nanoseconds;
using std::chrono::duration_cast;
auto t0 = clock::now();
auto t1 = clock::now();
nanoseconds ns = duration_cast<nanoseconds>(t1-t0);
Die Umwandlung schneidet Bruchteile eines CPU-Zyklus ab, um die Nanosekunde zu bilden. Andere Rundungsmodi sind möglich, aber das ist ein anderes Thema.
Für mich ergibt dies eine Dauer von nur 18 Takt-Ticks, die auf 6 Nanosekunden verkürzt wird.
Ich habe der obigen Uhr eine "invariante Überprüfung" hinzugefügt, von der die wichtigste die Überprüfung ist, ob die clock::period
für die Maschine korrekt ist. Auch dies ist kein portabler Code, aber wenn Sie diese Uhr verwenden, haben Sie sich bereits dazu verpflichtet. Die get_clock_speed()
hier gezeigte private Funktion erhält unter OS X die maximale CPU-Frequenz, und diese sollte dieselbe Zahl sein wie der konstante Nenner von clock::period
.
Wenn Sie dies hinzufügen, sparen Sie ein wenig Zeit beim Debuggen, wenn Sie diesen Code auf Ihren neuen Computer portieren und vergessen, den Code clock::period
auf die Geschwindigkeit Ihres neuen Computers zu aktualisieren . Die gesamte Überprüfung erfolgt entweder zur Kompilierungszeit oder zum Start des Programms. Es hat also keinen Einfluss auf die Leistung von clock::now()
.