QueryPerformanceCounter PMC oder TCS?





  • PIT__ schrieb:

    Mmacher schrieb:

    QueryPerformanceCounter() greift auf den TSC time stamp counter zu, der sich intern in der CPU (ab Pentium-Serie) befindet. Dieser wird mit dem Befehl "RDTSC" ausgelesen.

    das kann so nicht stimmen: es gibt ja die Funktion QueryPerformanceFrequency().

    Was ist das für ein Blödsinn? Was kann da nicht stimmen? 😮

    Es ist sehr wohl richtig was ich da geschrieben habe.
    Ich habe ja nicht behauptet, daß QueryPerformanceCounter() die einzige Funktion wäre, die auf TSC zugreifen kann.

    Auch beim Millisekunden-Timer gibt es jede Menge Funktionen, die auf 8250-Timer zugreifen können, und die ich nicht erwähnt habe.
    Aber das ist nicht der Sinn der Sache.



  • QPC verwendet normalerweise den ACPI/PM Timer afaik. Der TSC ist generell eine äußerst schlechte Idee auf einer multicore CPU...



  • Mmacher schrieb:

    Was ist das für ein Blödsinn? Was kann da nicht stimmen? 😮

    QueryPerformanceFrequency() gibt die Frequenz des PIT/HPET Zählers wieder - welche Frequenz sollte diese Funktion den bei rdtsc wiedergeben? Sicherlich nicht die aktuell Prozessor Geschwindigkeit oder die des Systembus bei APIC (das hätte sich wohl auch herumgesprochen wen es dem so wäre)



  • Ach leude,.. ihr seid die geilsten,... thx 😉



  • Hi,

    zwei Fragen hätte ich noch:

    a) Ab welcher Generation wird RDTSCP (read TSC and Processor ID) unterstützt
    b) Welcher Mnemonic gibt die Performance Frequency aus?

    grüße



  • zeusosc schrieb:

    a) Ab welcher Generation wird RDTSCP (read TSC and Processor ID) unterstützt

    Laut Wikipedia seit dem i586. Aber du willst das sowieso nicht benutzen.

    zeusosc schrieb:

    b) Welcher Mnemonic gibt die Performance Frequency aus?

    Mir scheint du verwechselst da was. QueryPerformanceFrequency mapped nicht einfach auf irgendeine ASM Instruction...



  • @ dot:

    QueryPerformanceCounter und QueryPerformanceFrequency mappen beide auf __imp_NtQueryPerformanceCounter.

    NTSTATUS NtQueryPerformanceCounter(
    __out PLARGE_INTEGER PerformanceCounter,
    __out_opt PLARGE_INTEGER PerformanceFrequency
    );

    Gibt es deine Instruction die PerformanceFrequency in asm direkt aus der CPU zu ermitteln? (Sollte doch eigentlich oder?)

    grüße



  • zeusosc schrieb:

    QueryPerformanceCounter und QueryPerformanceFrequency mappen beide auf __imp_NtQueryPerformanceCounter.

    Ja, aber was hat das mit RDTSC zu tun?

    zeusosc schrieb:

    Gibt es deine Instruction die PerformanceFrequency in asm direkt aus der CPU zu ermitteln? (Sollte doch eigentlich oder?)

    Dazu müsstest du erstmal überhaupt definieren was genau diese PerformanceFrequency deiner Meinung nach sein soll.



  • naja,..
    nach http://archive.gamedev.net/reference/programming/features/timing/
    greift QPC entweder auf PIT/PMT oder halt TSC zu, TSC->RDTSC,...
    und ich will sozusagen die Aktualisierungsfrequenz des TSC um den quotienten von Counterdifferenz und Frequenz in eine Zeit umzurechnen....

    grüüße und dank



  • Verwend doch einfach QueryPerformanceCounter(). Den TSC würd ich besser nicht zur Zeitmessung verwenden. Das war früher mal vielleicht ein gangbarer Weg, aber in Zeiten von Multiprozessorsystemen und Dynamic Frequency Scaling ist das eher keine gute Idee.

    Was genau willst du denn eigentlich anstellen mit der Zeit?



  • Ich möchte die Laufzeit eines Threads 0,5µs genau messen. 🙂
    Eine Implementation mittles QPC/QPF habe ich schon,....

    Grüüße



  • zeusosc schrieb:

    Ich möchte die Laufzeit eines Threads 0,5µs genau messen. 🙂

    Das wird in dieser Genauigkeit wohl zumindest wahnsinnig aufwändig bis praktisch unmöglich. Abgesehen davon gibts das was du willst wohl schon fertig, nennt sich Profiler 😉



  • Mit der genauigkeit sollte es nach genannten Link kein problem geben, das Reaktionsvermögen des Tasks/threads schon eher, welche je nach LAST und Priorisierung latenzen bis zum nächsten QPC Call erzeugen.

    Immerhin sind 0,5µs 2Mhz,...

    Profiler??? bitte Link

    grüßße



  • Eben, du laufst ja nicht allein auf der Maschine, d.h. du misst zumindest ab und zu mit sehr hoher Wahrscheinlichkeit mal alles was sonst noch drankommt mit, und die ganzen Kontextswitches allein brauchen schon ganz sicher weit mehr als 0,5µs. Da bewegen wir uns eher im ms Bereich...

    http://en.wikipedia.org/wiki/Profiling_(computer_programming)
    http://developer.amd.com/tools/CodeAnalyst/Pages/default.aspx



  • (thx, link schaue ich mir nachher an)

    Also: Der Counter muss auf 0,5µs genau sein,... nicht der Call zum Auslesen dessen,... das ist mit QPC/QPF ja schon gewährleistet.

    Mich interessiert dennoch wie ich aus der CPU prozessorspezifisch einen PMC und dessen Frequenz auslesen kann...

    grüße und bis nachher



  • zeusosc schrieb:

    Ich möchte die Laufzeit eines Threads 0,5µs genau messen. 🙂

    Wenn du die Laufzeit messen willst, lies den PC am anfang und am ende des Threads aus.



  • zeusosc schrieb:

    Mich interessiert dennoch wie ich aus der CPU prozessorspezifisch einen PMC und dessen Frequenz auslesen kann...

    Diese Counter sind alle nicht Teil der CPU sondern irgendwelche Bausteine am Mainboard. D.h. du musst erstmal schaun ob die überhaupt vorhanden sind und dann suchst du dir das Beste was du finden kannst oder so. Auslesen läuft dann eben z.B. über Memory Mapped I/O oder irgendwelche Interrupt Handler oder was weiß ich, hängt vom jeweiligen Baustein ab.



  • @500ns:

    ich hatte nur auf die frage geantwortet, was ich denn "eigentlich" vorhätte.

    Meine eigentliche frage ist also noch nicht beantwortet.
    Ich werde diese aber nochmal in einem satz umformulieren:

    "Wie sieht die ASM implementantion des QPC/QPF aus?"

    Seid gegrüßt und danke für eure gedult...

    ----------
    not casesensitive....



  • Auf meinem System sieht es so aus:
    QPC:

    0000000076D6C210  sub         rsp,28h  
    [b]0000000076D6C214  test        byte ptr [7FFE02EDh],1  [/b]
    0000000076D6C21C  mov         r9,rcx  
    0000000076D6C21F  je          0000000076DDB660  
    0000000076D6C225  mov         r8,qword ptr [7FFE03B8h]  
    [b]0000000076D6C22D  rdtsc  [/b]
    0000000076D6C22F  movzx       ecx,byte ptr [7FFE02EDh]  
    0000000076D6C237  shl         rdx,20h  
    0000000076D6C23B  or          rax,rdx  
    0000000076D6C23E  shr         ecx,2  
    0000000076D6C241  add         rax,r8  
    0000000076D6C244  shr         rax,cl  
    0000000076D6C247  mov         qword ptr [r9],rax  
    0000000076D6C24A  mov         eax,1  
    0000000076D6C24F  add         rsp,28h  
    0000000076D6C253  ret
    

    Es gibt also wohl ein System-Bit (7FFE02EDh), welches definiert, ob rdtsc verwendet wird oder nicht. Falls nicht, so wird dieser Code ausgeführt:

    0000000076D91620  mov         r10,rcx  
    0000000076D91623  mov         eax,2Eh  
    0000000076D91628  syscall  
    0000000076D9162A  ret
    

    QPF (vereinfacht, zuvor werden noch einige andere Register gesetzt):

    0000000076D91620  mov         r10,rcx  
    0000000076D91623  mov         eax,2Eh  
    0000000076D91628  syscall  
    0000000076D9162A  ret
    

    PS: Das kannst Du auch selber nachvollziehen, indem Du in VS Ctrl-F11 während dem Debuggen drückst...


Anmelden zum Antworten