Thread Sheduling Änderungen von Windows XP nach Windows 7



  • Du solltest die Zeiten mit "QueryPerformanceCounter" messen. Sonst hast Du viel zu hohe Ungenauigkeiten.
    Auch empfehle ich Dir ein "timeBeginPeriod(1)" am Anfang der App aufzurufen. Das benötigt aber Admin-Rechte!



  • Hallo Jochen,

    also ich wieß jetzt nicht was das Problem mit der Zeitmessung zu tun hat es kommt ja nicht genau auf die Millisekunde drauf an auch eine ungenauigkeit von 50 ms stört micht nicht nur halt wenn die zeit sich verdoppelt oder verdreifacht und da sollte doch die Zeitmessung ausreichend sein.

    MfG



  • Mit der Zeitmessung hat es nichst zu tun... Ich würde Dir trotzdem raten eine genauere Methode zu nehmen die unabhängig von irgendwelchen Zeitservern ist...



  • Jochen Kalmbach schrieb:

    Du solltest die Zeiten mit "QueryPerformanceCounter" messen. Sonst hast Du viel zu hohe Ungenauigkeiten.
    Auch empfehle ich Dir ein "timeBeginPeriod(1)" am Anfang der App aufzurufen. Das benötigt aber Admin-Rechte!

    Was für einen Vorteil hätte er von timeBeginPeriod(1), wenn er QueryPerformanceCounter() verwendet, außer dass evtl. noch mehr Zeit für Contextswitches draufgeht? Für seine Zwecke sollte doch sogar schon GetTickCount() ausreichend sein!? Möglicherweise ist auch QueryThreadCycleTime() hilfreich!?



  • also mal zurück zum Thema.

    Welche Winapi aufrufe Kosten in Windows7 mehr zeit als ind XP?

    MfG



  • Destiniy schrieb:

    Welche Winapi aufrufe Kosten in Windows7 mehr zeit als ind XP?

    Hat dein Problem denn mit der Zeitdauer irgendwelcher API Calls zu tun? Falls ja: Wie hast du das herausgefunden? Wenn du richtig profiled hast, solltest du sowieso wissen, wo genau die Zeit vergeht!?



  • Hallo

    leider weiß ich noch nicht so genau wo die Zeit vergeht, da ich dafür erst mal mit Hilfe von Logs das Problem eingrwenzen muß. Und das dauert da bei jedem Versuch erst mal einer 300 km entfernt das Programm auf der Maschine laufen lassen muß. (3 h pro Versuch)

    ich vermute nur dass es API calls sind, da es ja auf Windows XP nicht auftritt:

    MfG



  • Hallo,

    also das Problem ist nicht das WaitForMultipleObjectsEx so lange braucht es kommt nur zu offt mit dem Event WAIT_IO_COMPLETION zurück kann es sein das Windows 7 die WSARecv Completition Routine viel öffter mit kleineren häppchen aufruft?

    MfG



  • dot schrieb:

    Was für einen Vorteil hätte er von timeBeginPeriod(1), wenn er QueryPerformanceCounter() verwendet

    Das eine hat mit dem anderen nichts zu tun...



  • Destiniy schrieb:

    also das Problem ist nicht das WaitForMultipleObjectsEx so lange braucht es kommt nur zu offt mit dem Event WAIT_IO_COMPLETION zurück kann es sein das Windows 7 die WSARecv Completition Routine viel öffter mit kleineren häppchen aufruft?

    Das ist leicht möglich.
    Und was genau bereitet dabei jetzt Probleme, wenn WaitForMultipleObjectsEx zu oft mit WAIT_IO_COMPLETION zurückkommt?



  • es scheint so als geht WAIT_IO_COMPLETION vor den anderen Events

    also das event auf das ich warte wird gesetzt, und bevor es ausgelöst wird kommen so 30 WAIT_IO_COMPLETION events vorher



  • Destiniy schrieb:

    es scheint so als geht WAIT_IO_COMPLETION vor den anderen Events

    also das event auf das ich warte wird gesetzt, und bevor es ausgelöst wird kommen so 30 WAIT_IO_COMPLETION events vorher

    Ja, ist ja auch ganz normal - wenn APCs anstehen und man "alertable" wartet, dann werden halt erstmal die APCs abgearbeitet.

    Die Frage ist: warum sind 30 APCs vor der "erwünschten" Nachricht ein Problem? Dauert das Abarbeiten der APCs so lange?
    Wenn ja dann hast du da ein grundlegendes Problem, nämlich dass weniger wichtige APCs abgesetzt werden, die dann wichtigere Ereignisse verzögern.

    U.u. könnte man sich mit einem Hack behelfen: wenn du die Abarbeitung von bestimmten Events bevorzugt machen willst, dann prüf einfach vor dem "alertable" WaitForMultipleObjectsEx mit einem "nicht alertable" WaitForMultipleObjectsEx nur diese bevorzugten Events.
    Also z.B. so:

    // Erst die wichtigen Events mit timeout = 0 und alertable = false prüfen
    // (Die wichtigen Events müssen dabei dir ersten in "allEvents" sein. Dadurch brauchen wir nur ein Array, und vor allem bedeutet dann der Returnwert immer das selbe,
    //  wir können also das selbe switch() verwenden egal welcher WaitForMultipleObjectsEx() das Ergebnis geliefert hat)
    DWORD rc = WaitForMultipleObjectsEx(importantEventsCount, allEvents, false, 0, false);
    // Wenn nichts wichtiges anliegt normal warten
    if (rc == WAIT_TIMEOUT)
        rc = WaitForMultipleObjectsEx(allEventsCount, allEvents, false, timeout, true);
    switch (rc)
    {
        ...
    

    p.s.: Falls das zu unerwünschten Nebeneffekten führt, z.B. andere Dinge zu arg verzögert, dann hilft vielleicht wenn das "importantEvents" WaitForMultipleObjectsEx nur bei jedem 2. Durchlauf gemacht wird. Wenn permanent APCs und "wichtige" Events anstehen würden die APCs dann nicht ausgehungert, sondern immer ein APC, ein Event, ein APC, ein Event etc. abgearbeitet.



  • Jochen Kalmbach schrieb:

    dot schrieb:

    Was für einen Vorteil hätte er von timeBeginPeriod(1), wenn er QueryPerformanceCounter() verwendet

    Das eine hat mit dem anderen nichts zu tun...

    Eben, da ich die API aber nur im Zusammenhang mit der Genauigkeit von gewissen Timern kenne und nur weiß, dass sie im Prinzip den Heartbeat des Schedulers erhöht, würde mich interessieren, was genau man in dem Fall hier davon hat bzw. haben könnte, rein aus Interesse.



  • Wenn man den Heartbeat des Schedulers erhöht, so erhöht sich automatisch auch die Reaktionszeit von Waitable-Objects... als ein WaitFor...Object wird somit "schneller"...
    Das ganze hängt natürlich auch noch von den anzahl der ReadyToRun Threads ab... also wenn _keine_ ReadyToRun sind, dann merkt man keinen Unterschied. Aber wenn es mehrere sind, dann kann es schon was ausmachen, da jeder Thread ja öfter unterbrochen wird.... aber es hat, wie Du ja auch sagtest, Nachteile, wenn sehr viele Threads laufen. Wenn man aber gescheit programmiert hat man mehr Vorteile als Nachteile; zumindest aus meiner Erfahrung... und ich mache schon lange unter Windows mit Echtzeitsteuerung rum... aber hier meistens mit Fibers, da hier das (User-Mode) Scheduling noch schneller ist 😉



  • Jochen Kalmbach schrieb:

    also wenn _keine_ ReadyToRun sind, dann merkt man keinen Unterschied.

    Hm.
    Müsste das nicht genauer heissen "wenn keine ReadyToRun Threads mit gleicher Priorität da sind"?
    Threads mit niedrigerer Priorität sollten - wenn ich das Windows' Scheduling richtig verstehe - sofort unterbrochen werden. Und Threads mit höherer laufen so oder so weiter.

    Sonst würden einem vielbeschäftigte Background Threads ja die ganze Performance weglutschen. Das wäre Übel.



  • Ja, mir "gleicher und höherer Prio".

    Wobei man sagen muss, dass die meisten Synchronisations-Objekte von *User-Mode* Threads signalisiert werden. Somit ann man nicht sagen, dass nieder priore Threads sofort unterbroichen werden, wenn das Ereignis eintritt. Weil das ereignis ja vielleicht schon viel früher eingetreten ist, aber der nieder priore Thread erst später drankommt um einen möglicherweise höher prioren thread zu signalisieren.... aber jetzt wird es mehr theoretisch und dann spielt natürlich auch noch das dynamische erhöhen der Prio für solche Dinge eine Rolle. Das geht ja aber nur bis prio 15... ab prio 16 gibt es keine dynamische Erhöhung um solche Fälle besser abhandeln zu können...

    Meine Threads laufen alle mit Prio 32 😉 und dann via Fibers gescheduled... dann muss man sich auch keine Sorgen um Synchronisation machen 😉



  • Entschuldigung, dass ich hier so reinplatze... ich versuche mich gerade in das Threading reinzuwursteln und lese hier von Jochens Ansatz...
    Verstehe ich das richtig, dass du mit den Fibers sozusagen Threadpools umsetzt, wobei in jedem Pool kooperatives scheduling betrieben wird? Irgendwie verstehe ich das gerade nur so diffus, weil ich mir nicht genau erklären kann, was nun der Vorteil oder besser Unterschied gegenüber der "sequentiellen" Abarbeitung von Tasks in solch einem Thread ist. Schließlich muss ein Fiber ja explizit ein anderes Fiber aktivieren, wenn der Wechsel stattfinden soll, zumindest wenn ich die Doku richtig lese. Das heißt, ich meine zu verstehen, dass Fibers sich nicht "schlafen legen" können, während sie auf ein Event warten und dann automatisch wieder geweckt werden, sollte das Event eintreten (sie sind ja nicht mehr "aktuell", sobald auf ein anderes Fiber geswitcht wird).
    Hast du eventuell etwas Zeit, um das System etwas genauer zu erläutern? Würde mich sehr freuen mal von solch praktikablen Ansätzen zu lesen.

    Viele Grüße,
    Deci



  • Das System ist ein komplettes "Tasking-System" welches auch eigene Methode für alle möglichen Dinge hat:
    - Sleep
    - Semaphore
    - MsgQueues
    - usw.
    Eben alles, was man so von einen Task erwartet.

    Der größter Vorteil ist, dass man sich *nicht* um das synchronieren von Threads kümmern muss (wenn man nur einen User-Mode-Thread hat). Damit betreiben wir Anlagen mit ca. 4000 I/Os und 20 seriellen Schnittstellen in Echtzeit.
    Man muss nur einige Dinge beachte (keine Zugriffe auf Dateisystem usw.) um hier relativ sicher zu sein. Das System erlaubt auch das zeitweise "ausbrechen" aus dem Fiber-Verbund und dann ein ausführen als "normaler" Thread, welches dann wieder alles erlaubt.



  • So ich habe jetzt nochmal neue Informationen.

    Wenn ich das Programm auf einen Core force funktioniert es schnell genug.

    Jetzt verstehe ich das nicht. Ich habe n Threads die ich auf m Processor Cores verteile. Wenn m>1 ist läuft das Programm zu langsam. Wonach sollte man schauen?

    MfG



  • @jochen:

    gibts zu dem fiber - thema noch mehr informationen als die eher allgemein gehaltenen in der msdn? hört sich sehr intressant an!

    was mich da auch intressieren würde ist (bitte korrigieren falls ichs falsch verstehe) folgendes:
    die synchronisation zwischen den threads wird ja dadurch unnötig da man mit den fibers im selben prozessraum arbeitet. wenn jetzt mehrere io - schnittstellen daten liefern müssen die ja auch irgendwo hin... und spätestens beim zusammenführen der daten muss doch dann auch wieder irgendwie synchronisiert werden? verlagert sich das problem dadurch nicht nur?

    sorry fürs offtopic werden.


Anmelden zum Antworten