System - Genaue Zeitmessung



  • Hi,

    ich hab noch mal mit Volkard gesprochen.
    Die Funktion:
    QueryPerformanceFrequency(&frequenz);

    passt nicht zu dem asm-Timer.

    Somit muss die Taktfrequenz des jeweiligen Rechners ermittelt werden.
    Ich hab nun mal ne Klasse geschrieben, die anscheinend recht gut funktioniert.

    Hier mal die Klasse:

    // Header
    //---------------------------------------------------------------------------
    #ifndef ASMTimerH
    #define ASMTimerH
    #include <stdlib.h>
    //--------------------------
    class TASMTimer_RESULT
    { public:
    __int64 start;
    __int64 stop;
    double frequenz;
    double result;
    };
    //----------------------------------
    class TASMTimer
    {
    private:
    TASMTimer_RESULT RESULT;
    __int64 start;
    __int64 stop;
    double frequenz;
    protected:
    double Taktfrequenz(); // gibt die Taktfrequenz des Rechners zurück;
    __int64 rdtsc(); // zeit nehmen
    public:
    void Start();
    TASMTimer_RESULT  Stop();
    TASMTimer();
    };
    //---------------------------------------------------------------------------
    #endif
    //#####################################################
    // cpp-Datei
    //---------------------------------------------------------------------------
    #include <vcl.h>
    #pragma hdrstop
    #pragma inline
    #include "ASMTimer.h"
    
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    //-------------------------------------------------------
    TASMTimer::TASMTimer()
    {
    frequenz=Taktfrequenz();
    }
    
    double TASMTimer::Taktfrequenz()
    {
    DWORD TimeHI ;
    DWORD TimeLO;
    SetPriorityClass(GetCurrentProcess, REALTIME_PRIORITY_CLASS);
    SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_TIME_CRITICAL);
    
    Sleep(10);
    asm
        {
        dw 310Fh
        mov TimeLO, eax
        mov TimeHI, edx
        }
    Sleep(500);
    asm
        {
        dw 310Fh
        sub eax, TimeLO
        sbb edx, TimeHI
        mov TimeLO, eax
        mov TimeHI, edx
        }
    SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_NORMAL);
    SetPriorityClass(GetCurrentProcess, NORMAL_PRIORITY_CLASS);
    return TimeLO*(1000/500);
    }
    //--------------------------------------------------------------
    __int64 TASMTimer::rdtsc(){ asm  {dw 310Fh } }
    //---------------------------------------------------------------------------
    void TASMTimer::Start(){start=rdtsc();}
    //------------------------------------------------------------------
    TASMTimer_RESULT TASMTimer::Stop()
    {
    stop=rdtsc();
    RESULT.start=start;
    RESULT.stop=stop;
    RESULT.frequenz=frequenz;
    RESULT.result=((double)(RESULT.stop-RESULT.start)/RESULT.frequenz);
    return RESULT;
    }
    //-----------------------------------------------------------------------
    

    hm, jetzt noch ein Beispiel-Projekt, um die Verwendung zu demonstrieren:

    // Header
    //---------------------------------------------------------------------------
    #ifndef Unit1H
    #define Unit1H
    //---------------------------------------------------------------------------
    #include <Classes.hpp>
    #include <Controls.hpp>
    #include <StdCtrls.hpp>
    #include <Forms.hpp>
    #include <ExtCtrls.hpp>
    #include "ASMTimer.h"
    //---------------------------------------------------------------------------
    class TForm1 : public TForm
    {
    __published:    // Komponenten, die von der IDE verwaltet werden
        TButton *Button1;
        TButton *Button2;
        TEdit *Edit1;
        TEdit *Edit2;
        TTimer *Timer1;
        TMemo *Memo1;
        void __fastcall Button1Click(TObject *Sender);
        void __fastcall Timer1Timer(TObject *Sender);
    private:
    TASMTimer MyTimer;
    public:
        __fastcall TForm1(TComponent* Owner);
    };
    //---------------------------------------------------------------------------
    extern PACKAGE TForm1 *Form1;
    //---------------------------------------------------------------------------
    #endif
    //###############################################
    // cpp-Datei
    //---------------------------------------------------------------------------
    #include <vcl.h>
    #pragma hdrstop
    #include "Unit1.h"
    #include <stdlib.h>
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
        {
        }
    //--------------------------------------------------------------
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    Timer1->Interval=1000;
    Timer1->Enabled^=1;
    if(Timer1->Enabled)
        {
        MyTimer.Start();
        }
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Timer1Timer(TObject *Sender)
    {
    TASMTimer_RESULT Timer_Result=MyTimer.Stop();
    Edit1->Text=Timer_Result.result;
     MyTimer.Start();
    
    }
    //---------------------------------------------------------------------------
    

    Nachtrag:

    bedenkt bitte, das die Klasse ca 0.000000145730847400532 sec (0.145 Microsekunden) braucht um die Methoden aufzurufen.
    Je nach dem wie genau es denn sein soll, muss der genaue Wert ermittelt und abgezogen werden. Dann kann sogar im Pikosekundenbereich gemessen werden.

    Nun, aber wer braucht denn schon sowas images/smiles/icon_rolleyes.gif
    Für den Microsekundenbereich kann dieses durchaus vernachlässigt werden.

    [ Dieser Beitrag wurde am 07.04.2002 um 20:25 Uhr von AndreasW editiert. ]



  • Hallo,
    ich habe versucht Ihren Code in ein neues Projekt einzufügen aber mir ist nach den Fehlermeldungen ( Undefiniertes Symbol MyTimer oder TASMTimer_RESULT) nun nicht klar wie ich es richtig einfügen soll.
    Ich habe ein neues Projekt mit Edit, Timer und Button und über Datei neu eine Headerdatei einfügt und die oberen CPP und Header Dateien was mach ich mit denen ?
    Sorry aber ich bin noch Anfänger auf dem Gebiet.
    Deshalb vielen Dank für Ihre Hilfe !!!!
    Gruß Boarder



  • Hi,
    wir sind hier alle per du images/smiles/icon_wink.gif

    1. ein Verzeichnis anlegen, in das der Timer abgelegt werden soll.
    2. Die erste Header unter "ASMTimer.h" in diesem Verzeichnis speichern
    3. Die erste cpp-Datei mit den Methoden des Timers in die Datei "ASMTimer.cpp" speichern.

    damit hast du schon mal den Timer auf der Platte.
    dann:
    4. Neues Projekt erstellen.
    5. Auf Projekt/ Dem Projekt hinzufügen... klicken und die "ASMTimer.cpp"- Datei auswählen
    6. In der Header der Unit, in der der Timer benutz werden soll:

    #include "ASMTimer.h"

    einfügen.

    Dann kann der Timer, so wie in diesem Beisiel benutzt werden oder nach eigenen wünschen.



  • Übrigens, sorry, daß wir hier ein wenig vom Thema abgewichen sind.
    Der ASMTimer noch der andere Timer auf der 2.Seite kann dein Problem wirklich lösen. Diese Timer messen ja lediglich eine Zeitdifferenz.

    Du brauchst ja die absolute Zeit in Millisekunden.

    Wie weit bist du denn mit deiner Problemlösung ?

    [ Dieser Beitrag wurde am 07.04.2002 um 18:49 Uhr von AndreasW editiert. ]



  • Doch, kann man doch aus Differenzen und Summen wieder absolutieren.



  • hm,
    da haste recht images/smiles/icon_rolleyes.gif



  • Original erstellt von volkard:
    **```cpp
    //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";
    }

    so, ich hab mich, aufgrund Volkards Tip im Chat, nochmal hiermit beschäftigt.

    #pragma inline
    //..
      __int64 rdtsc(){ asm  {dw 310Fh}  } 
    
    void test()
    {
      long long start=rdtsc();
      cout<<"world"<<endl;
      long end=rdtsc();
      cout<<"einmal world kostet <<end-start<<" takte!\n";
    

    wäre wohl die kürzeste Version des Timers. Die Zeitdifferenz ergibt sich dann aus:

    (end-start)/frequenz des Prozessors

    ich habe die obere Klasse dementsprechend abgeändert.

    [ Dieser Beitrag wurde am 07.04.2002 um 20:29 Uhr von AndreasW editiert. ]



  • Hallo,
    wollte mir mal die Timer von Sundy anschauen aber wo find ich die, ebenfall das Bsp von molooo ?
    Bis dann wann

    FAQ un Forum hab ich durchsucht.





  • hm,
    @Boarder:

    In der Zeile:

    __int64 TASMTimer::rdtsc(){ asm {dw 310Fh } }

    kommt diese Warnung. DIese kannst du aber ignorieren. Spielt keine Rolle, da asm den Wert zurückgibt.

    Ansonsten müsste der Timer funktionieren. Er wurde auch bereits auf anderen Rechnern getestet. Es waren keine Fehler festzustellen.


Anmelden zum Antworten