Für eine bestimmte Dauer schlafen

7

Ich verstehe die Sleep-Funktion so, dass sie "mindestens Semantik" folgt, d. h. sleep (5) garantiert, dass der Thread für 5 Sekunden schläft, aber je nach anderen Faktoren kann er für mehr als 5 Sekunden blockiert bleiben. Gibt es eine Möglichkeit, genau für einen bestimmten Zeitraum zu schlafen (ohne beschäftigt zu warten).

    
Raam 06.03.2011, 08:07
quelle

7 Antworten

14

Wie andere bereits gesagt haben, müssen Sie wirklich ein Echtzeit-Betriebssystem verwenden, um dies zu erreichen. Präzise Software-Timing ist ziemlich schwierig.

Allerdings ... obwohl nicht perfekt, können Sie viel bessere Ergebnisse erzielen als "normal", indem Sie einfach die Priorität des Prozesses erhöhen, der ein besseres Timing benötigt . In Windows können Sie dies mit der Funktion SetPriorityClass erreichen. Wenn Sie die Priorität auf die höchste Stufe ( REALTIME_PRIORITY_CLASS: 0x00000100 ) setzen, erhalten Sie viel bessere Timing-Ergebnisse. Wiederum - das wird nicht perfekt sein, wie du es verlangst.

Dies ist wahrscheinlich auch auf anderen Plattformen als Windows möglich, aber ich hatte nie Grund, es zu tun, also habe ich es nicht getestet.

EDIT: Nach dem Kommentar von Andy T, wenn Ihre App Multi-Threading ist, müssen Sie auch auf die Priorität achten, die den Threads zugewiesen ist. Für Windows ist dies dokumentiert hier .

Etwas Hintergrund ...

Vor einiger Zeit habe ich SetPriorityClass verwendet, um die Priorität einer Anwendung zu erhöhen, bei der ich eine Echtzeitanalyse von High-Speed-Video durchführte, und ich konnte keinen Frame verpassen. Die Bilder kamen mit einer sehr regulären (mit externem Framegrabber HW) Frequenz von 300 Bildern pro Sekunde (fps) auf dem PC an, die einen HW-Interrupt auf jeden Frame ausstrahlte, den ich dann bediente. Da das Timing sehr wichtig war, habe ich eine Menge Statistiken über das Interrupt-Timing gesammelt (mit QueryPerformanceCounter Zeug, um zu sehen, wie schlimm die Situation wirklich war, und war entsetzt über die resultierenden Distributionen. Ich habe die Statistiken nicht griffbereit, aber Windows hat den Interrupt immer dann bedient, wenn es sich bei normaler Priorität so anfühlt. Die Histogramme waren sehr unordentlich, wobei das stdev breiter war als meine ~ 3ms Periode. Häufig würde ich riesige Lücken von 200 ms oder mehr in der Interrupt-Wartung haben (erinnere mich, dass der Interrupt ungefähr alle 3 ms ausgelöst wurde) !! dh: HW-Interrupts sind FAR von genau! Du bist festgefahren mit dem, was das Betriebssystem für dich tun möchte.

Allerdings - als ich die Einstellung REALTIME_PRIORITY_CLASS entdeckt und mit dieser Priorität bewertet habe, war sie signifikant besser und die Verteilung des Serviceintervalls war extrem eng. Ich könnte 10 Minuten mit 300 fps laufen und keinen einzigen Frame verpassen. Gemessene Interrupt-Service-Perioden waren ziemlich genau 1/300 s mit einer engen Verteilung.

Versuchen Sie auch, die anderen Dinge, die das Betriebssystem tut, zu minimieren, um die Wahrscheinlichkeit zu verbessern, dass Ihr Timing in der App besser funktioniert, wenn es darauf ankommt. zB: kein Hintergrund-Video-Transcoding oder Disk-De-Fragging oder irgendetwas, während Sie versuchen, präzises Timing mit anderem Code zu bekommen !!

Zusammenfassend:

  1. Wenn Sie das wirklich brauchen, gehen Sie mit einem Echtzeit-OS
  2. Wenn Sie kein Echtzeit-Betriebssystem verwenden können (unmöglich oder unpraktisch), wird die Erhöhung Ihrer Prozesspriorität wahrscheinlich Ihr Timing um einiges verbessern, genau wie bei mir
  3. HW Interrupts werden es nicht tun ... das OS muss sich noch entscheiden, sie zu bedienen!
  4. Stellen Sie sicher, dass nicht viele andere Prozesse ausgeführt werden, die um die Aufmerksamkeit des Betriebssystems konkurrieren
  5. Wenn Ihnen das Timing wirklich wichtig ist, testen Sie es. Obwohl es nicht einfach ist, Code genau nach zu erstellen , ist es sehr einfach, diese Abweichung zu messen. Die Hochleistungszähler in PCs (was Sie mit QueryPerformanceCounter erhalten) sind extrem gut.

Da es hilfreich sein kann (auch wenn es ein bisschen außerhalb des Themas ist), hier ist eine kleine Klasse, die ich vor langer Zeit geschrieben habe, um die Hochleistungszähler auf einem Windows-Rechner zu verwenden. Es kann für Ihre Tests nützlich sein:

CHiResTimer.h

%Vor%

CHiResTimer.cpp

%Vor%     
Russ 06.03.2011, 09:27
quelle
5

Nein.

Der Grund, warum es "zumindest Semantik" ist, ist, dass nach diesen 5 Sekunden ein anderer Thread beschäftigt ist.

Jeder Thread erhält eine Zeitscheibe vom Betriebssystem. Das Betriebssystem steuert die Reihenfolge, in der die Threads ausgeführt werden.

Wenn Sie einen Thread in den Ruhezustand versetzen, setzt das Betriebssystem den Thread in eine Warteliste. Wenn der Timer abgelaufen ist, "weckt" das Betriebssystem den Thread.
Dies bedeutet, dass der Thread wieder zur Liste der aktiven Threads hinzugefügt wird, es ist jedoch nicht garantiert, dass t an erster Stelle hinzugefügt wird. (Was ist, wenn 100 Fäden in dieser bestimmten Sekunde erwachen müssen? Wer wird zuerst gehen?)

    
Yochai Timmer 06.03.2011 08:17
quelle
4

Während Standard-Linux kein Echtzeit-Betriebssystem ist, achten die Kernel-Entwickler genau darauf, wie lange ein Prozess mit hoher Priorität verhungern würde, während Kernel-Sperren gehalten werden. Daher ist ein Standard-Linux-Kernel normalerweise für viele Soft-Realtime-Anwendungen gut genug.

Sie können Ihren Prozess als Echtzeitaufgabe mit dem sched_setscheduler(2) -Aufruf planen, indem Sie entweder SCHED_FIFO oder SCHED_RR verwenden. Die beiden haben leichte Unterschiede in der Semantik, aber es kann genug sein zu wissen, dass eine SCHED_RR -Aufgabe den Prozessor aufgrund von Zeitscheiben eventuell an eine andere Aufgabe mit der gleichen Priorität abgibt, während eine SCHED_FIFO -Aufgabe nur die CPU an die CPU abgibt eine andere Aufgabe mit der gleichen Priorität aufgrund blockierender E / A oder eines expliziten Aufrufs von sched_yield(2) .

Seien Sie vorsichtig, wenn Sie geplante Echtzeitaufgaben verwenden. Da sie immer Vorrang vor Standardaufgaben haben, können Sie leicht feststellen, dass Sie eine Endlosschleife programmieren, die niemals die CPU verlässt und Administratoren daran hindert, ssh zu verwenden, um den Prozess zu beenden. Es kann also nicht schaden, ein sshd mit einer höheren Echtzeitpriorität auszuführen, zumindest bis du sicher bist, dass du die schlimmsten Bugs behoben hast.

Es gibt verschiedene Linux-Versionen, an denen gearbeitet wurde, um Hardware-Echtzeit-Garantien zu bieten. RTLinux hat kommerzielle Unterstützung ; Xenomai und RTAI sind konkurrierende Implementierungen von Echtzeit-Erweiterungen für Linux, aber ich weiß nichts anderes über sie.

    
sarnold 06.03.2011 10:23
quelle
2

Nun, Sie versuchen, ein schwieriges Problem anzugehen, und genau Timing ist nicht machbar: das Beste, was Sie tun können ist Hardware-Interrupts , und die Implementierung hängt sowohl von der zugrunde liegenden Hardware als auch von Ihrem Betriebssystem ab (Sie benötigen nämlich ein Echtzeit-Betriebssystem , welches die meisten normalen Desktop-Betriebssysteme nicht sind). Was ist Ihre genaue Zielplattform?

    
Greg 06.03.2011 08:14
quelle
2

Wie vorherige Beantworter sagten: Es gibt keine Möglichkeit, genau zu sein (einige vorgeschlagene Echtzeit-Os oder Hardware-Interrupts und selbst diese sind nicht exakt ). Ich denke, was Sie suchen, ist etwas genauer als die Funktion sleep () und Sie finden, dass abhängig von Ihrem Betriebssystem in z. die Windows-Funktion Sleep () oder unter GNU die Funktion nanosleep ().

  

Ссылка

     

Ссылка

Beide geben Ihnen Präzision innerhalb weniger Millisekunden.

    
Bernd Elkemann 06.03.2011 08:23
quelle
0

Nein. Weil Sie immer davon abhängig sind, dass das Betriebssystem Threads zum richtigen Zeitpunkt aufruft.

    
Kevin 06.03.2011 08:11
quelle
0

Es gibt keine Möglichkeit, für einen bestimmten Zeitraum unter Verwendung von Standard C zu schlafen. Sie benötigen mindestens eine Bibliothek eines Drittanbieters, die eine größere Granularität bietet, und Sie benötigen möglicherweise auch einen speziellen Betriebssystemkernel wie die Echtzeit Linux-Kernel.

Hier ist zum Beispiel eine Diskussion darüber, wie nah Sie an Win32-Systemen herankommen können .

Dies ist keine C-Frage.

    
Michael Dillon 06.03.2011 09:22
quelle

Tags und Links