it-swarm.com.de

Timer-Funktion zur Angabe der Zeit in Nanosekunden unter Verwendung von C ++

Ich möchte die Zeit berechnen, die eine API benötigt hat, um einen Wert zurückzugeben. Die Zeit, die für eine solche Aktion benötigt wird, liegt im Bereich von Nanosekunden. Da die API eine C++ - Klasse/-Funktion ist, verwende ich timer.h, um dasselbe zu berechnen:

  #include <ctime>
  #include <cstdio>

  using namespace std;

  int main(int argc, char** argv) {

      clock_t start;
      double diff;
      start = clock();
      diff = ( std::clock() - start ) / (double)CLOCKS_PER_SEC;
      cout<<"printf: "<< diff <<'\n';

      return 0;
  }

Der obige Code gibt die Zeit in Sekunden an. Wie bekomme ich dasselbe in Nanosekunden und mit größerer Präzision?

100
gagneet

Was andere über das wiederholte Ausführen der Funktion in einer Schleife geschrieben haben, ist richtig.

Für Linux (und BSD) möchten Sie clock_gettime () verwenden.

#include <sys/time.h>

int main()
{
   timespec ts;
   // clock_gettime(CLOCK_MONOTONIC, &ts); // Works on FreeBSD
   clock_gettime(CLOCK_REALTIME, &ts); // Works on Linux
}

Für Windows möchten Sie den QueryPerformanceCounter verwenden. Und hier ist mehr über QPC

Anscheinend gibt es ein bekanntes Problem mit QPC auf einigen Chipsätzen, so dass Sie möglicherweise sicherstellen möchten, dass Sie nicht über diesen Chipsatz verfügen. Zusätzlich können einige Dual-Core-AMDs auch ein Problem verursachen. Siehe den zweiten Beitrag von sebbbi, in dem er sagt:

QueryPerformanceCounter () und QueryPerformanceFrequency () bieten eine etwas bessere Auflösung, haben jedoch unterschiedliche Probleme. In Windows XP geben alle AMD Athlon X2 Dual-Core-CPUs den PC "zufällig" zurück (der PC springt manchmal etwas zurück), es sei denn, Sie installieren speziell das AMD Dual-Core-Treiberpaket, um das Problem zu beheben. Wir haben keine anderen Dual + Core-CPUs mit ähnlichen Problemen bemerkt (p4 dual, p4 ht, core2 dual, core2 quad, phenom quad).

EDIT 2013/07/16:

Es sieht so aus, als wäre die Wirksamkeit von QPC unter bestimmten Umständen umstritten (siehe http://msdn.Microsoft.com/en-us/library/windows/desktop/ee417693 (v = vs.85)). .aspx

... Während QueryPerformanceCounter und QueryPerformanceFrequency normalerweise für mehrere Prozessoren angepasst werden, können Fehler im BIOS oder in den Treibern dazu führen, dass diese Routinen unterschiedliche Werte zurückgeben, wenn der Thread von einem Prozessor auf einen anderen wechselt ...

In dieser StackOverflow-Antwort https://stackoverflow.com/a/4588605/34329 heißt es jedoch, dass QPC unter allen MS-Betriebssystemen nach Win XP Service Pack 2) einwandfrei funktionieren sollte.

Dieser Artikel zeigt, dass Windows 7 feststellen kann, ob der oder die Prozessoren eine invariante TSC haben, und auf einen externen Zeitgeber zurückgreift, wenn dies nicht der Fall ist. http://performancebydesign.blogspot.com/2012/03/high-resolution-clocks-and-timers-for.html Die Synchronisierung zwischen Prozessoren ist immer noch ein Problem.

Andere feine Lesung in Bezug auf Timer:

Weitere Einzelheiten finden Sie in den Kommentaren.

82
grieve

Diese neue Antwort verwendet die C++ 11-Funktion <chrono>. Während es andere Antworten gibt, die zeigen, wie man <chrono> Verwendet, zeigt keine, wie man <chrono> Mit der RDTSC -Funktion verwendet, die in mehreren der anderen Antworten hier erwähnt wurde. Also dachte ich, ich würde zeigen, wie man RDTSC mit <chrono> Benutzt. Zusätzlich werde ich zeigen, wie Sie den Testcode auf der Uhr templatisieren können, damit Sie schnell zwischen RDTSC und den integrierten Uhrfunktionen Ihres Systems wechseln können (die wahrscheinlich auf clock() basieren werden. , clock_gettime() und/oder QueryPerformanceCounter.

Beachten Sie, dass die Anweisung RDTSC x86-spezifisch ist. QueryPerformanceCounter ist nur für Windows. Und clock_gettime() ist nur POSIX. Im Folgenden stelle ich zwei neue Uhren vor: std::chrono::high_resolution_clock Und std::chrono::system_clock, Die, wenn Sie C++ 11 annehmen können, jetzt plattformübergreifend sind.

Zunächst erstellen Sie eine C++ 11-kompatible Uhr aus der Intel rdtsc Assembly-Anweisung. Ich nenne es x::clock:

#include <chrono>

namespace x
{

struct clock
{
    typedef unsigned long long                 rep;
    typedef std::ratio<1, 2'800'000'000>       period; // My machine is 2.8 GHz
    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));
    }
};

}  // x

Dieser Takt zählt nur die CPU-Zyklen und speichert sie in einer 64-Bit-Ganzzahl ohne Vorzeichen. Möglicherweise müssen Sie die Assemblersyntax für Ihren Compiler anpassen. Oder Ihr Compiler bietet möglicherweise eine Eigenschaft an, die Sie stattdessen verwenden können (z. B. now() {return __rdtsc();}).

Um eine Uhr zu bauen, müssen Sie ihr die Darstellung (Speichertyp) geben. Sie müssen auch die Taktperiode angeben, bei der es sich um eine Kompilierungszeitkonstante handeln muss, obwohl Ihr Computer möglicherweise die Taktgeschwindigkeit in verschiedenen Leistungsmodi ändert. Und von diesen können Sie leicht die "native" Zeitdauer und den Zeitpunkt Ihrer Uhr in Bezug auf diese Grundlagen definieren.

Wenn Sie nur die Anzahl der Taktstriche ausgeben möchten, spielt es keine Rolle, welche Zahl Sie für die Taktperiode angeben. Diese Konstante ist nur dann von Bedeutung, wenn Sie die Anzahl der Taktstriche in Echtzeiteinheiten wie Nanosekunden umrechnen möchten. Und in diesem Fall ist die Umrechnung in Nanosekunden (Millisekunden, was auch immer) umso genauer, je genauer Sie in der Lage sind, die Taktrate anzugeben.

Unten ist ein Beispielcode, der die Verwendung von x::clock Zeigt. Eigentlich habe ich den Code auf der Uhr als Vorlage verwendet, um zu zeigen, wie Sie viele verschiedene Uhren mit genau der gleichen Syntax verwenden können. Dieser spezielle Test zeigt, wie hoch der Loop-Overhead ist, wenn Sie die gewünschte Zeit in einem Loop ausführen:

#include <iostream>

template <class clock>
void
test_empty_loop()
{
    // Define real time units
    typedef std::chrono::duration<unsigned long long, std::pico> picoseconds;
    // or:
    // typedef std::chrono::nanoseconds nanoseconds;
    // Define double-based unit of clock tick
    typedef std::chrono::duration<double, typename clock::period> Cycle;
    using std::chrono::duration_cast;
    const int N = 100000000;
    // Do it
    auto t0 = clock::now();
    for (int j = 0; j < N; ++j)
        asm volatile("");
    auto t1 = clock::now();
    // Get the clock ticks per iteration
    auto ticks_per_iter = Cycle(t1-t0)/N;
    std::cout << ticks_per_iter.count() << " clock ticks per iteration\n";
    // Convert to real time units
    std::cout << duration_cast<picoseconds>(ticks_per_iter).count()
              << "ps per iteration\n";
}

Mit diesem Code wird zunächst eine "Echtzeit" -Einheit erstellt, in der die Ergebnisse angezeigt werden. Ich habe Pikosekunden ausgewählt, aber Sie können beliebige Einheiten auswählen, entweder ganzzahlig oder auf Gleitkommabasis. Als Beispiel gibt es eine vorgefertigte std::chrono::nanoseconds - Einheit, die ich hätte verwenden können.

Als weiteres Beispiel möchte ich die durchschnittliche Anzahl der Taktzyklen pro Iteration als Gleitkommazahl ausgeben. Daher erstelle ich eine weitere Dauer auf der Basis von double, die die gleichen Einheiten aufweist wie der Tick der Uhr (genannt Cycle in der Code).

Die Schleife wird mit Aufrufen von clock::now() auf beiden Seiten zeitgesteuert. Wenn Sie den von dieser Funktion zurückgegebenen Typ benennen möchten, ist dies:

typename clock::time_point t0 = clock::now();

(Wie im Beispiel x::clock deutlich gezeigt, gilt dies auch für die vom System gelieferten Uhren).

Um eine Dauer in Form von Gleitkommatakten zu erhalten, subtrahiert man lediglich die beiden Zeitpunkte und dividiert diese Dauer durch die Anzahl der Iterationen, um den Wert pro Iteration zu erhalten.

Sie können die Zählung in jeder beliebigen Dauer mithilfe der count() member-Funktion abrufen. Dies gibt die interne Darstellung zurück. Schließlich verwende ich std::chrono::duration_cast, Um die Dauer Cycle in die Dauer picoseconds umzuwandeln und auszudrucken.

Die Verwendung dieses Codes ist einfach:

int main()
{
    std::cout << "\nUsing rdtsc:\n";
    test_empty_loop<x::clock>();

    std::cout << "\nUsing std::chrono::high_resolution_clock:\n";
    test_empty_loop<std::chrono::high_resolution_clock>();

    std::cout << "\nUsing std::chrono::system_clock:\n";
    test_empty_loop<std::chrono::system_clock>();
}

Oben übe ich den Test mit unserem hausgemachten x::clock Und vergleiche diese Ergebnisse mit zwei der vom System gelieferten Uhren: std::chrono::high_resolution_clock Und std::chrono::system_clock. Für mich druckt dies aus:

Using rdtsc:
1.72632 clock ticks per iteration
616ps per iteration

Using std::chrono::high_resolution_clock:
0.620105 clock ticks per iteration
620ps per iteration

Using std::chrono::system_clock:
0.00062457 clock ticks per iteration
624ps per iteration

Dies zeigt, dass jede dieser Uhren eine andere Tick-Periode hat, da die Ticks pro Iteration für jede Uhr sehr unterschiedlich sind. Bei Umrechnung in eine bekannte Zeiteinheit (z. B. Pikosekunden) erhalte ich jedoch für jede Uhr ungefähr das gleiche Ergebnis (Ihre Laufleistung kann variieren).

Beachten Sie, dass mein Code völlig frei von "magischen Konversionskonstanten" ist. Tatsächlich gibt es im gesamten Beispiel nur zwei magische Zahlen:

  1. Die Taktrate meiner Maschine, um x::clock Zu definieren.
  2. Die Anzahl der zu testenden Iterationen. Wenn das Ändern dieser Anzahl zu starken Abweichungen Ihrer Ergebnisse führt, sollten Sie die Anzahl der Iterationen wahrscheinlich erhöhen oder Ihren Computer während des Tests von konkurrierenden Prozessen entleeren.
68
Howard Hinnant

Bei dieser Genauigkeit ist es besser, im CPU-Tick zu argumentieren, als im Systemaufruf wie clock () . Und vergessen Sie nicht, dass es so gut wie unmöglich ist, eine Anweisung mit einer Genauigkeit von mehr als einer Nanosekunde auszuführen.

Trotzdem ist so ähnlich ein Anfang:

Hier ist der tatsächliche Code zum Abrufen der Anzahl von 80 x 86 CPU-Takten, die seit dem letzten Start der CPU verstrichen sind. Es wird auf Pentium und höher funktionieren (386/486 wird nicht unterstützt). Dieser Code ist tatsächlich MS Visual C++ -spezifisch, kann aber wahrscheinlich sehr einfach auf andere portiert werden, sofern er Inline-Assembly unterstützt.

inline __int64 GetCpuClocks()
{

    // Counter
    struct { int32 low, high; } counter;

    // Use RDTSC instruction to get clocks count
    __asm Push EAX
    __asm Push EDX
    __asm __emit 0fh __asm __emit 031h // RDTSC
    __asm mov counter.low, EAX
    __asm mov counter.high, EDX
    __asm pop EDX
    __asm pop EAX

    // Return result
    return *(__int64 *)(&counter);

}

Diese Funktion hat auch den Vorteil, dass sie extrem schnell ist - für die Ausführung sind normalerweise nicht mehr als 50 CPU-Zyklen erforderlich.

nter Verwendung der Timing-Figuren :
Wenn Sie die Anzahl der Uhren in die tatsächlich verstrichene Zeit umrechnen müssen, teilen Sie die Ergebnisse durch die Taktrate Ihres Chips. Denken Sie daran, dass sich die "Nenn" -GHz wahrscheinlich geringfügig von der tatsächlichen Geschwindigkeit Ihres Chips unterscheidet. Um die tatsächliche Geschwindigkeit Ihres Chips zu überprüfen, können Sie verschiedene sehr gute Dienstprogramme oder den Win32-Aufruf QueryPerformanceFrequency () verwenden.

27
VonC

Um dies richtig zu machen, können Sie eine von zwei Möglichkeiten wählen, entweder mit RDTSC oder mit clock_gettime(). Die Sekunde ist ungefähr 2-mal schneller und hat den Vorteil, die richtige absolute Zeit anzugeben. Beachten Sie, dass Sie RDTSC wie angegeben verwenden müssen, um ordnungsgemäß zu funktionieren (andere Kommentare auf dieser Seite weisen Fehler auf und können auf bestimmten Prozessoren zu falschen Timing-Werten führen).

inline uint64_t rdtsc()
{
    uint32_t lo, hi;
    __asm__ __volatile__ (
      "xorl %%eax, %%eax\n"
      "cpuid\n"
      "rdtsc\n"
      : "=a" (lo), "=d" (hi)
      :
      : "%ebx", "%ecx" );
    return (uint64_t)hi << 32 | lo;
}

und für clock_gettime: (ich habe die Mikrosekundenauflösung willkürlich gewählt)

#include <time.h>
#include <sys/timeb.h>
// needs -lrt (real-time lib)
// 1970-01-01 Epoch UTC time, 1 mcs resolution (divide by 1M to get time_t)
uint64_t ClockGetTime()
{
    timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);
    return (uint64_t)ts.tv_sec * 1000000LL + (uint64_t)ts.tv_nsec / 1000LL;
}

das Timing und die Werte erzeugt:

Absolute values:
rdtsc           = 4571567254267600
clock_gettime   = 1278605535506855

Processing time: (10000000 runs)
rdtsc           = 2292547353
clock_gettime   = 1031119636
23
Marius

Ich benutze das Folgende, um die gewünschten Ergebnisse zu erzielen:

#include <time.h>
#include <iostream>
using namespace std;

int main (int argc, char** argv)
{
    // reset the clock
    timespec tS;
    tS.tv_sec = 0;
    tS.tv_nsec = 0;
    clock_settime(CLOCK_PROCESS_CPUTIME_ID, &tS);
    ...
    ... <code to check for the time to be put here>
    ...
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tS);
    cout << "Time taken is: " << tS.tv_sec << " " << tS.tv_nsec << endl;

    return 0;
}
22
gagneet

Für C++ 11 ist hier ein einfacher Wrapper:

#include <iostream>
#include <chrono>

class Timer
{
public:
    Timer() : beg_(clock_::now()) {}
    void reset() { beg_ = clock_::now(); }
    double elapsed() const {
        return std::chrono::duration_cast<second_>
            (clock_::now() - beg_).count(); }

private:
    typedef std::chrono::high_resolution_clock clock_;
    typedef std::chrono::duration<double, std::ratio<1> > second_;
    std::chrono::time_point<clock_> beg_;
};

Oder für C++ 03 unter * nix,

class Timer
{
public:
    Timer() { clock_gettime(CLOCK_REALTIME, &beg_); }

    double elapsed() {
        clock_gettime(CLOCK_REALTIME, &end_);
        return end_.tv_sec - beg_.tv_sec +
            (end_.tv_nsec - beg_.tv_nsec) / 1000000000.;
    }

    void reset() { clock_gettime(CLOCK_REALTIME, &beg_); }

private:
    timespec beg_, end_;
};

Anwendungsbeispiel:

int main()
{
    Timer tmr;
    double t = tmr.elapsed();
    std::cout << t << std::endl;

    tmr.reset();
    t = tmr.elapsed();
    std::cout << t << std::endl;
    return 0;
}

Von https://Gist.github.com/gongzhitaao/7062087

8
gongzhitaao

Wenn Sie wissen möchten, wie lange es dauert, eine Funktion aufzurufen, möchten Sie dies im Allgemeinen mehrmals als nur einmal tun. Wenn Sie Ihre Funktion nur einmal aufrufen und die Ausführung sehr kurz ist, haben Sie immer noch den Overhead, die Timerfunktionen aufzurufen, und Sie wissen nicht, wie lange dies dauert.

Wenn Sie beispielsweise schätzen, dass die Ausführung Ihrer Funktion 800 ns dauert, rufen Sie sie zehn Millionen Mal in einer Schleife auf (dies dauert dann ungefähr 8 Sekunden). Teilen Sie die Gesamtzeit durch zehn Millionen, um die Zeit pro Anruf zu erhalten.

5
Greg Hewgill

Sie können die folgende Funktion verwenden, wenn gcc unter x86-Prozessoren ausgeführt wird:

unsigned long long rdtsc()
{
  #define rdtsc(low, high) \
         __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))

  unsigned int low, high;
  rdtsc(low, high);
  return ((ulonglong)high << 32) | low;
}

mit Digital Mars C++:

unsigned long long rdtsc()
{
   _asm
   {
        rdtsc
   }
}

das liest den Hochleistungstimer auf dem Chip. Ich benutze dies bei der Profilerstellung.

5
Walter Bright

Sie können Embedded Profiler (kostenlos für Windows und Linux) verwenden, das eine Schnittstelle zu einem Multiplattform-Timer (in einer Prozessor-Zykluszahl) hat und Ihnen eine Anzahl von Zyklen pro Sekunde geben kann:

EProfilerTimer timer;
timer.Start();

... // Your code here

const uint64_t number_of_elapsed_cycles = timer.Stop();
const uint64_t nano_seconds_elapsed =
    mumber_of_elapsed_cycles / (double) timer.GetCyclesPerSecond() * 1000000000;

Die Neuberechnung der Zykluszahl auf die Zeit ist möglicherweise ein gefährlicher Vorgang bei modernen Prozessoren, bei denen die CPU-Frequenz dynamisch geändert werden kann. Um sicherzustellen, dass die konvertierten Zeiten korrekt sind, muss die Prozessorfrequenz vor der Profilerstellung festgelegt werden.

3
Mi-La

Ich verwende Borland Code, hier ist der Code, den ti_hund mir manchmal negativ angibt, aber das Timing ist ziemlich gut.

#include <dos.h>

void main() 
{
struct  time t;
int Hour,Min,Sec,Hun;
gettime(&t);
Hour=t.ti_hour;
Min=t.ti_min;
Sec=t.ti_sec;
Hun=t.ti_hund;
printf("Start time is: %2d:%02d:%02d.%02d\n",
   t.ti_hour, t.ti_min, t.ti_sec, t.ti_hund);
....
your code to time
...

// read the time here remove Hours and min if the time is in sec

gettime(&t);
printf("\nTid Hour:%d Min:%d Sec:%d  Hundreds:%d\n",t.ti_hour-Hour,
                             t.ti_min-Min,t.ti_sec-Sec,t.ti_hund-Hun);
printf("\n\nAlt Ferdig Press a Key\n\n");
getch();
} // end main
3
Paul J Moesman

Wenn Sie eine Genauigkeit von weniger als einer Sekunde benötigen, müssen Sie systemspezifische Erweiterungen verwenden und dies anhand der Dokumentation des Betriebssystems überprüfen. POSIX unterstützt bis zu Mikrosekunden mit gettimeofday , aber nichts Genaueres, da Computer keine Frequenzen über 1 GHz hatten.

Wenn Sie Boost verwenden, können Sie boost :: posix_time aktivieren.

3

Nach der Methode von Brock Adams mit einer einfachen Klasse:

int get_cpu_ticks()
{
    LARGE_INTEGER ticks;
    QueryPerformanceFrequency(&ticks);
    return ticks.LowPart;
}

__int64 get_cpu_clocks()
{
    struct { int32 low, high; } counter;

    __asm cpuid
    __asm Push EDX
    __asm rdtsc
    __asm mov counter.low, EAX
    __asm mov counter.high, EDX
    __asm pop EDX
    __asm pop EAX

    return *(__int64 *)(&counter);
}

class cbench
{
public:
    cbench(const char *desc_in) 
         : desc(strdup(desc_in)), start(get_cpu_clocks()) { }
    ~cbench()
    {
        printf("%s took: %.4f ms\n", desc, (float)(get_cpu_clocks()-start)/get_cpu_ticks());
        if(desc) free(desc);
    }
private:
    char *desc;
    __int64 start;
};

Anwendungsbeispiel:

int main()
{
    {
        cbench c("test");
        ... code ...
    }
    return 0;
}

Ergebnis:

test dauerte: 0,0002 ms

Hat einige Funktionsaufrufe, sollte aber trotzdem mehr als schnell genug sein :)

3
Thomas

Minimalistische Copy & Paste-Struktur + Faulheit

Wenn die Idee ist, eine minimalistische Struktur zu haben, die Sie für schnelle Tests verwenden können, dann empfehle ich Ihnen einfach Kopieren und Einfügen irgendwo in Ihrer C++ - Datei direkt nach dem #include. Dies ist der einzige Fall, in dem ich die Formatierung im Allman-Stil opfere.

Sie können die Genauigkeit in der ersten Zeile der Struktur leicht anpassen. Mögliche Werte sind: nanoseconds, microseconds, milliseconds, seconds, minutes oder hours.

#include <chrono>
struct MeasureTime
{
    using precision = std::chrono::microseconds;
    std::vector<std::chrono::steady_clock::time_point> times;
    std::chrono::steady_clock::time_point oneLast;
    void p() {
        std::cout << "Mark " 
                << times.size()/2
                << ": " 
                << std::chrono::duration_cast<precision>(times.back() - oneLast).count() 
                << std::endl;
    }
    void m() {
        oneLast = times.back();
        times.Push_back(std::chrono::steady_clock::now());
    }
    void t() {
        m();
        p();
        m();
    }
    MeasureTime() {
        times.Push_back(std::chrono::steady_clock::now());
    }
};

Verwendung

MeasureTime m; // first time is already in memory
doFnc1();
m.t(); // Mark 1: next time, and print difference with previous mark
doFnc2();
m.t(); // Mark 2: next time, and print difference with previous mark
doStuff = doMoreStuff();
andDoItAgain = doStuff.aoeuaoeu();
m.t(); // prints 'Mark 3: 123123' etc...

Ergebnis der Standardausgabe

Mark 1: 123
Mark 2: 32
Mark 3: 433234

Wenn Sie eine Zusammenfassung nach der Ausführung wünschen

Wenn Sie den Bericht nachträglich haben möchten, weil beispielsweise Ihr Code dazwischen auch in die Standardausgabe schreibt. Fügen Sie dann der Struktur die folgende Funktion hinzu (kurz vor MeasureTime ()):

void s() { // summary
    int i = 0;
    std::chrono::steady_clock::time_point tprev;
    for(auto tcur : times)
    {
        if(i > 0)
        {
            std::cout << "Mark " << i << ": "
                    << std::chrono::duration_cast<precision>(tprev - tcur).count()
                    << std::endl;
        }
        tprev = tcur;
        ++i;
    }
}

Dann können Sie einfach Folgendes verwenden:

MeasureTime m;
doFnc1();
m.m();
doFnc2();
m.m();
doStuff = doMoreStuff();
andDoItAgain = doStuff.aoeuaoeu();
m.m();
m.s();

Dadurch werden alle Markierungen wie zuvor aufgeführt, aber erst dann, nachdem der andere Code ausgeführt wurde. Beachten Sie, dass Sie nicht sowohl m.s() als auch m.t() verwenden sollten.

2
Yeti

Wenn dies für Linux ist, habe ich die Funktion "gettimeofday" verwendet, die eine Struktur zurückgibt, die die Sekunden und Mikrosekunden seit der Epoche angibt. Sie können dann timersub verwenden, um die beiden zu subtrahieren, um den Zeitunterschied zu erhalten, und ihn in die gewünschte Zeitgenauigkeit umwandeln. Sie geben jedoch Nanosekunden an und es sieht so aus, als ob die Funktion clock_gettime () das ist, wonach Sie suchen. Es gibt die Zeit in Sekunden und Nanosekunden in die Struktur ein, in die Sie übergehen.

2
Will Mc

Hier ist ein Nice Boost Timer, der gut funktioniert:

//Stopwatch.hpp

#ifndef STOPWATCH_HPP
#define STOPWATCH_HPP

//Boost
#include <boost/chrono.hpp>
//Std
#include <cstdint>

class Stopwatch
{
public:
    Stopwatch();
    virtual         ~Stopwatch();
    void            Restart();
    std::uint64_t   Get_elapsed_ns();
    std::uint64_t   Get_elapsed_us();
    std::uint64_t   Get_elapsed_ms();
    std::uint64_t   Get_elapsed_s();
private:
    boost::chrono::high_resolution_clock::time_point _start_time;
};

#endif // STOPWATCH_HPP


//Stopwatch.cpp

#include "Stopwatch.hpp"

Stopwatch::Stopwatch():
    _start_time(boost::chrono::high_resolution_clock::now()) {}

Stopwatch::~Stopwatch() {}

void Stopwatch::Restart()
{
    _start_time = boost::chrono::high_resolution_clock::now();
}

std::uint64_t Stopwatch::Get_elapsed_ns()
{
    boost::chrono::nanoseconds nano_s = boost::chrono::duration_cast<boost::chrono::nanoseconds>(boost::chrono::high_resolution_clock::now() - _start_time);
    return static_cast<std::uint64_t>(nano_s.count());
}

std::uint64_t Stopwatch::Get_elapsed_us()
{
    boost::chrono::microseconds micro_s = boost::chrono::duration_cast<boost::chrono::microseconds>(boost::chrono::high_resolution_clock::now() - _start_time);
    return static_cast<std::uint64_t>(micro_s.count());
}

std::uint64_t Stopwatch::Get_elapsed_ms()
{
    boost::chrono::milliseconds milli_s = boost::chrono::duration_cast<boost::chrono::milliseconds>(boost::chrono::high_resolution_clock::now() - _start_time);
    return static_cast<std::uint64_t>(milli_s.count());
}

std::uint64_t Stopwatch::Get_elapsed_s()
{
    boost::chrono::seconds sec = boost::chrono::duration_cast<boost::chrono::seconds>(boost::chrono::high_resolution_clock::now() - _start_time);
    return static_cast<std::uint64_t>(sec.count());
}
2
Patrick K

Was denkst du darüber:

    int iceu_system_GetTimeNow(long long int *res)
    {
      static struct timespec buffer;
      // 
    #ifdef __CYGWIN__
      if (clock_gettime(CLOCK_REALTIME, &buffer))
        return 1;
    #else
      if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &buffer))
        return 1;
    #endif
      *res=(long long int)buffer.tv_sec * 1000000000LL + (long long int)buffer.tv_nsec;
      return 0;
    }
2
icegood