timer mit 33ms interval



  • Hi,

    wie kann ich in C++ einen timer mit 33ms interval implementieren mit moeglichst hoher genauigkeit (+- 5ms) ? Ich verwende c++ und windows 10...
    ich habe zuvor CreateTimerQueue() verwendet, dieser ist aber relativ ungenau, wie auch folgender artikel bestraetigt.

    hat jemand eine idee wie ich das timing besser hin bekomme ohne der winapi?

    habe dazu folgende infos gelesen:
    http://www.virtualdub.org/blog/pivot/entry.php?id=272
    http://www.geisswerks.com/ryan/FAQS/timing.html



  • Fast alle Timer unter Windows werden im Heartbeat Interrupt geprüft und "ausgelöst". Mir ist nur eine Ausnahme bekannt, und das sind Waitable Timer mit absoluter Deadline. Mag sein dass es da noch weitere gibt (ich kenne speziell die neueren Dinge der WinAPI nicht alle auswendig), aber ich kenne halt keine - müsstest du selbst googeln.

    Was man aber machen kann, ist die Frequenz des Heartbeat Interrupt zu erhöhen. Per Default ist der nämlich auf Desktop Windows Versionen so 10-15 ms, und das ist für dich dann zu ungenau. Auf ca. 1 ms kann man es aber problemlos mit timeBeginPeriod(1) stellen. Ab Windows 8.1 hat das auch kaum schlimme Auswirkungen auf die Performance oder den Stromverbrauch. (Und auf älteren Windows Versionen tut sich performancemässig auch nicht SO viel, bleibt im einstelligen Prozentbereich was man dabei verliert. Was Stromverbrauch angeht hab ich nie gemessen - war mir immer zu aufwendig.) Bzw. auf vielen Systemen geht sogar 0.5 ms, aber dazu muss man Funktionen verwenden an die man normalerweise nur per LoadLibrary + GetProcAddress drankommt - ist normalerweise den Aufwand nicht wert.

    ps: In dem von dir verlinkten Artikel auf virtualdub.org steht ja eh eine gut funktionierende Möglichkeit beschrieben. Was stört dich daran?



  • Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C++ (alle ISO-Standards) in das Forum WinAPI verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • hustbaer schrieb:

    Fast alle Timer unter Windows werden im Heartbeat Interrupt geprüft und "ausgelöst".

    Wo finde ich Informationen dazu? "cpu heartbeat interrupt", "windows heartbeat interrupt" und "os heartbeat interrupt" hat zu nichts geführt.



  • ps: In dem von dir verlinkten Artikel auf virtualdub.org steht ja eh eine gut funktionierende Möglichkeit beschrieben. Was stört dich daran?

    @hustbaer: meinst du wie folgt?

    // reference: https://randomascii.wordpress.com/2013/04/02/sleep-variation-investigated/

    #include <Windows.h>
    #include <stdio.h>
    
    // Link with the winmm library for timeBeginPeriod
    #pragma comment(lib, “winmm.lib”)
    
    // Return the time in seconds as a double.
    double GetTime()
    {
        LARGE_INTEGER frequency;
        QueryPerformanceFrequency(&frequency);
        LARGE_INTEGER time;
        QueryPerformanceCounter(&time);
        return time.QuadPart / double(frequency.QuadPart);
    }
    
    // Sleep the specified number of milliseconds.
    void BusyWait(double msTime)
    {
        double endTime = GetTime() + msTime * 0.001;
        while (GetTime() < endTime)
            ;
    }
    
    int main(int argc, char* argv[])
    {
        timeBeginPeriod(1);
        SetThreadPriority(GetCurrentThread(),
                    THREAD_PRIORITY_TIME_CRITICAL);
    
        const int kCount = 2000;
        double start = GetTime();
        for (int i = 0; i < kCount; ++i)
        {
            Sleep(1);
            BusyWait(0.9);
        }
        double elapsed = GetTime() – start;
        printf(“%f ms per tick.\n”, elapsed * 1000.0 / kCount);
    }
    


  • Der PerformanceTimer ist eine gute Wahl.

    Priorität hochsetzen ist wichtig. Es macht natürlich dann auch Sinn
    die BasePriority anzuheben.

    timeBeginPeriod(1) wirkt sich m.E. nicht für BusyWait() aus sondern
    eher auf z.B. Sleep() aus. Sleep macht für exaktes Timing wenig Sinn.

    Da BusyWait() nicht auf einem periodischen Timer basiert, kann man sich
    timeBeginPeriod() sowie das Linken gegen winmm.lib sparen.

    timeBeginPeriod() würde sich ohnehin auf das gesammte System auswirken
    und wäre eher nachteilig für den EINEN Messthread der wichtig wäre.

    Ich würde sagen, das man sich auf modernen CPUs zugunsten eines exakten
    Timings BusyWait() leisten sollte, auch wenn es Resourcen kostet.


Anmelden zum Antworten