System - Genaue Zeitmessung



  • [Edit]:
    Dieser Thread hatte eingentlich nichts mit Zeitmessung zu tun. Irgenwie sind wir aber zu diesem Thema übergegangen.

    Deshalb habe ich Beiträge, die nicht zu diesem Thema passen entfernt.
    Dadurch möchte ich eine bessere Lesbarkeit erreichen.

    Ich bitte hierfür um Verständnis.

    [/Edit]

    [ Dieser Beitrag wurde am 14.04.2002 um 23:32 Uhr von AndreasW editiert. ]

    [ Dieser Beitrag wurde am 30.06.2002 um 18:32 Uhr von Jansen editiert. ]



  • hm,

    ich konnt es ja nicht testen, aber so ähnlich vielleicht:

    void __fastcall TForm1::Serial1RxChar(TObject *Sender)
    { //oder in Timer1
    const int BufSize=17;
    char Buf[BufSize];
    // [Edit]
    String Datensatz="";
    // [/Edit]
    
    int anz,i;
    SYSTEMTIME time;
    GetSystemTime(&time);
    String Time=(String)time.wDay+"."+time.wMonth+"."+time.wYear+"  "+time.wHour+":"+
                ":"+time.wMinute+":"+time.wSecond+":"+time.wMilliseconds;
    anz=Serial1->ReceiveData(Buf,BufSize);
    
    for (int i=0;i<anz;i++)Datensatz+=IntToHex(Buf[i],2)+"  ";
    
    Memo2->Lines->Add(Datensatz+"  --  "+Time);
    }
    

    [ Dieser Beitrag wurde am 04.04.2002 um 18:03 Uhr von AndreasW editiert. ]



  • Hallo Andreas W.
    ich habe es gestestet aber er mag den Datensatz nicht was meinten Sie mit der Variablen und was ist sie ?
    Die millisekunden werden genauso wie bei mir angezeigt nur in 100 oder 50er Schritten.
    Wie kann ich denn Millisekunden von 0- unendlich Zählen ?
    Das Datum und die Zeit ist esrt einmal nicht so wichtig aber die genauen Millisekunden das ich sehen kann wann Daten reinkommen und deren Pausen. Vielleicht mit dem Timer aber ich habe keine Ahnung.
    Hat den jemand noch, zu meinem eigendlichen Problem mit dem Array, einen Vorschlag ?
    Vielen Dank



  • Hi,

    sorry, hab den letzten Beitrag noch mal geändert.

    Datensatz ist einfach nur ein String.

    hm, die Millisekunden..

    von Volkard hab ich da mal was gesehen. Sogar noch genauer.
    Ich stöber mal ein wenig..



  • extrem hochauflösende Zeitmessungen mit dem Assemblerbefehl rtdsc. Aber für diese Zwecke, also mikrosekunden oder so reicht QueryPerformanceCounter() bereits vollkommen aus.



  • Hallo und Danke,
    es funktioniert aber noch nicht so ganz,

    [Edit: gekürzt [/Edit]

    Den QueryPerformanceCounter() wo kann ich den den herunterladen oder
    Programmieren ?

    Vielen dank

    [ Dieser Beitrag wurde am 14.04.2002 um 23:39 Uhr von AndreasW editiert. ]



  • Den QueryPerformanceCounter() wo kann ich den den herunterladen oder Programmieren ?

    Ist Teil der WinAPI.
    #include <windows.h>
    und die Funktion ist da.
    Die genaue Verwendung findest Du dann in der Onlinehilfe.



  • Hi,

    extrem hochauflösende Zeitmessungen mit dem Assemblerbefehl rtdsc.

    hast du noch ein Beispiel dazu ?

    [Edit] gelöscht [/Edit]

    [ Dieser Beitrag wurde am 14.04.2002 um 23:41 Uhr von AndreasW editiert. ]



  • Sorry aber heut ist echt nicht mein Tag,
    wie kann ich den QueryPerformanceCounter() (mit #include <windows.h> )
    einfügen , wie sieht der Quellcode dafür aus?
    Mit:

    Memo1->Lines->Add(QueryPerformanceCounter());

    (er verlangt nach Parametern nach large integer)

    geht es nicht.
    Vielen Dank



  • zu QueryPerformanceCounter (so oder so ähnlich sollte es gehen):

    LARGE_INTEGER start_ticks, ende_ticks, frequenz;
    
    double tick_diff     = 0;
    start_ticks.QuadPart = 0;
    ende_ticks.QuadPart  = 0;
    
    QueryPerformanceCounter(&start_ticks);
    QueryPerformanceFrequency(&frequenz);
    
    // ... hier irgendwas machen ...
    
    QueryPerformanceCounter(&ende_ticks);
    
    // benötigte zeit berechnen
    tick_diff = ((double) ende_ticks.QuadPart - (double) start_ticks.QuadPart) / frequenz.QuadPart;
    


  • Hallo,
    könnten Sie das noch einmal erläutern mit dem Counter ich habe es probiert es funktioniert nicht so recht , was meinen Sie mit hier was machen und benötigte Zeit berechnen ?
    Könnten Sie es mal im Quellcode mit Button1 und Edit1 uns zeigen ?
    Ich danke Ihnen.
    M.Müler



  • hm,

    hier mal ein Beispiel, das die tatsächliche Taktfrequenz eines Timers
    ermittelt.

    Nimm ein Timer, Ein Editfeld und ein button aufs Formular.
    Dann sowas:

    //---------------------------------------------------------------------------
    #include <vcl.h>
    #pragma hdrstop
    
    #include "Unit1.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    LARGE_INTEGER start_ticks, ende_ticks, frequenz;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
    {
    Timer1->Enabled=false;
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Timer1Timer(TObject *Sender)
    {
    QueryPerformanceCounter(&ende_ticks);
    Edit1->Text=(String)(((double)ende_ticks.QuadPart-(double)start_ticks.QuadPart)/frequenz.QuadPart);
    start_ticks.QuadPart = 0;
    ende_ticks.QuadPart  = 0;
    
    QueryPerformanceCounter(&start_ticks);
    QueryPerformanceFrequency(&frequenz);
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    Timer1->Interval=1000;
    Timer1->Enabled^=1;
    if(Timer1->Enabled)
        {
        QueryPerformanceCounter(&start_ticks);
        QueryPerformanceFrequency(&frequenz);
        }
    }
    //---------------------------------------------------------------------------
    

    bei mir braucht der Timer zum Beipspiel bei einem Interval von 1000:

    1,0446278013376 Sec

    der Timer ist also um ca 0,044628 Sec langsamer als er sein sollte.

    [ Dieser Beitrag wurde am 05.04.2002 um 10:51 Uhr von AndreasW editiert. ]



  • ein beispiel-projekt für bcb5 habe ich mal hier hochgeladen... beispiel heisst listview.zip

    [ Dieser Beitrag wurde am 05.04.2002 um 11:42 Uhr von Sunday editiert. ]



  • //weiß nicht, wie man mit dem Borland feine Funktionen mit 
    //inlineassembler drin baut. Ungefähr so:
    inline long long rdtsc()
    {
      asm rdtsc;
    }
    ...
    void test()
    {
      long long start=rdtsc();
      cout<<"world"<<endl;
      long end=rdtsc();
      cout<<"einmal world kostet <<end-start<<" takte!\n";
    }
    


  • der Thread wär was für die FAQ, da die Frage nach genauer Zeitmessung schon öfters aufgetreten is und nun ja wirklich beantwortet ist!

    [Edit:] Den Beitrag von mir, der nach diesem Beitrag folgte, hab ich aus versehen gelöscht. Sorry.

    [ Dieser Beitrag wurde am 05.04.2002 um 22:35 Uhr von AndreasW editiert. ]



  • Netter Versuch.
    Eigentlich meinte ich, daß der returnwert der Funktion in edx/eax landet. Daher kein mov in ne globale Var nötig.
    Aber egal.
    Dein Compiler kennt den assemblerbefehl rdtsc noch net? Naja, das macht's gemeiner. Dann mußte wohl so vorgehen, wie Du gerade machst.
    Aber auch dann würd ich lieber in ne lokale Variable moven und die dann normal mit C-Mitteln returnen.
    ps: jo, bin am fertigen Code für den Borland interessiert. Der müßte dann echt in die Faq, denn so einfach scheint der net zu sein.

    [Edit]
    Volkard bezieht sich auf ein Versuch von mir den asm-Timer auf Borland umzusetzen. Dieser Versuch ist ähnlich gewesen, wie der nächste Versuch. Leider ist mir dieser Beitrag aber abhanden gekommen.
    [/Edit]

    [ Dieser Beitrag wurde am 14.04.2002 um 23:46 Uhr von AndreasW editiert. ]



  • joh, kennt er nicht.

    Ich versuchs mal Lokal. Vielleicht gehts dann ja.



  • Und laß das sub da weg!!!
    Die Methode rdtsc() funktioniert sinnvollerweise so wie clock() auch.
    Sich damit ein start und stop zu basteln ist Sache von reinem C++, da soll kein asm mehr zu sehen sein.



  • Borland hat doch den Typ __int64, oder?
    Dann nimm den als returnwert.
    Also probier nochmal nur
    inline __int64 rdtsc()
    {
    dw 310fh //falls das für den befehl rdtsc steht
    }



  • hm,
    ich hab das mal umgebaut. Genau wie das Beispiel auf der ersten Seite.

    //---------------------------------------------------------------------------
    #include <vcl.h>
    #pragma hdrstop
    #pragma inline
    #include "Unit1.h"
    #include <stdlib.h>
    
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    LARGE_INTEGER rdtsc();
    LARGE_INTEGER  frequenz;
    LARGE_INTEGER Start;
    LARGE_INTEGER Stop;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)               {}
    //---------------------------------------------------------------------------
    
    LARGE_INTEGER rdtsc()
    {
    DWord TimerHigh;
    DWord TimerLow;
    asm
        {
        dw 310Fh
        mov TimerLow, eax
        mov TimerHigh, edx
        }
    LARGE_INTEGER temp;
    temp.u.LowPart=TimerLow;
    temp.u.HighPart=TimerHigh;
    return ( temp);
    }
    //--------------------------------------------------------------
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    Timer1->Interval=1000;
    Timer1->Enabled^=1;
    if(Timer1->Enabled)
        {
    QueryPerformanceFrequency(&frequenz);
    Start=rdtsc();
        }
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Timer1Timer(TObject *Sender)
    {
    QueryPerformanceFrequency(&frequenz);
     Stop=rdtsc();
    double result=((double)Stop.QuadPart- (double)Start.QuadPart)/frequenz.QuadPart;
    Edit1->Text=result;
    Start=rdtsc();
    }
    //---------------------------------------------------------------------------
    

    es kommen allerdings andere Werte raus:

    durchschnittlich 613,708391860407

    weiss jemand warum ?

    [ Dieser Beitrag wurde am 05.04.2002 um 17:42 Uhr von AndreasW editiert. ]

    [ Dieser Beitrag wurde am 05.04.2002 um 22:37 Uhr von AndreasW editiert. ]

    [ Dieser Beitrag wurde am 14.04.2002 um 23:48 Uhr von AndreasW editiert. ]


Anmelden zum Antworten