Seite 1 von 1
threading.Event langsam
Verfasst: Donnerstag 10. September 2009, 16:33
von Hand
Hallo, der threading.Event Mechanismus ist ziemlich langsam sobald man den wait befehl mit einem Timeout versieht.
Code: Alles auswählen
import threading
import time
te = threading.Event()
def t1():
global te, t
time.sleep(1)
t=time.clock()
te.set()
def main():
global te, t
te.clear()
threading.Thread(target=t1).start()
te.wait(2.5)
print time.clock()-t
if __name__ == "__main__":
main()
Mit te.wait(2.5) dauert der Rücksprung um die 32ms
Mit te.wait() nur 0.2ms
Ist das ein Fehler in Python?
Verfasst: Donnerstag 10. September 2009, 17:18
von Hand
Hallo,
das Problem tritt auch bei threading.Condition auf sobald man einen Timeout setzt.
Verfasst: Donnerstag 10. September 2009, 21:35
von Zap
Wenn ich das richtig sehe hast du einen Fehler in der Verwendung von clock
Du musst es einmal aufrufen damit die Zeit sich von da auf den ersten Aufruf bezieht.
Code: Alles auswählen
In [18]: time.clock?
Type: builtin_function_or_method
Base Class: <type 'builtin_function_or_method'>
String Form: <built-in function clock>
Namespace: Interactive
Docstring:
clock() -> floating point number
Return the CPU time or real time since the start of the process or since
the first call to clock(). This has as much precision as the system
records.
Ich habe den Code bei mir mal gestartet und die Zeiten passen...
Verfasst: Freitag 11. September 2009, 08:54
von Hand
Hallo,
daran liegts nicht, als Zeit kommt da immer um die 30ms rause, auch wenn mans in einer Schleife laufen lässt.
Verfasst: Freitag 11. September 2009, 09:23
von Zap
Ok, du hast recht, bei mir sind es ~15ms.
Was für ein OS und welches Python nutzt du ?
Bei mir ist's Python 2.5 auf WinXP
Verfasst: Freitag 11. September 2009, 09:32
von Zap
Ich hab mal in die Sourcen von Python speziell "threading.py" geguckt und folgenden Kommentar in class "_Condition" Methode "wait" gefunden:
Code: Alles auswählen
def wait(self, timeout=None):
...
# Balancing act: We can't afford a pure busy loop, so we
# have to sleep; but if we sleep the whole timeout time,
# we'll be unresponsive. The scheme here sleeps very
# little at first, longer as time goes on, but never longer
# than 20 times per second (or the timeout time remaining).
Verfasst: Freitag 11. September 2009, 10:06
von b.esser-wisser
Aus hauptsächlich ästhetischen Gründen habe ich hab mir mal erlaubt dein Benchmarkprogramm zu ändern:
Code: Alles auswählen
#!/usr/bin/python
# coding:utf-8
import threading
import time
import Queue
import platform
def foo(te, q, time_func):
time.sleep(1)
# Startzeit 'rausbringen'
q.put(time_func())
te.set()
# Der thread soll nicht gleich abbrechen - sonst stoppen wir das evtl mit
time.sleep(0.5)
def main():
te = threading.Event()
t = 0.
q = Queue.Queue()
#time.clock scheint unter linux nicht sehr präzise zu sein:
t_func = time.time if platform.system() =="Linux" else time.clock
te.clear()
# wozu 'global'?
time_thread = threading.Thread(target=foo, args=(te, q, t_func,))
time_thread.start()
te.wait(2.5)
if not te.is_set(): print "Event time-out occured"
if t_func is time.clock: print time.clock() # RTFM!
else: print t_func() - q.get()
time_thread.join() # sauberes ende
if __name__ == "__main__":
main()
Auf meinem Eeepc (~600MHz, Ubuntu 9.04) schwanken die Zahlen ziemlich stark zw. 8ms und ~25ms.
hth. Jörg
Verfasst: Freitag 11. September 2009, 10:34
von EyDu
Das [mod]timeit[/mod]-Modul existiert.
Und wenn man schon per Hand so kleine Zeitinvervalle misst, dann sollte man nicht nur eine Messung durchführen sondern aus vielen den Mittelwert bilden. Und jetzt bitte tausend Messungen durchführen und einzeln Messen, sonder die Gesamtzeit von allen Messungen durch die Anzahl der Messungen dividieren. Die Timer sind nicht so genau, da diese eine relativ geringe Auflösung haben.
Verfasst: Samstag 12. September 2009, 00:30
von BlackJack
Und immer dran denken, das heutzutage die CPU-Leistung oft dynamisch geregelt wird und zum Beispiel erst nach einigen Sekunden Maximalstärke erreicht.
Verfasst: Samstag 12. September 2009, 00:48
von Hand
Zap hat geschrieben:Ok, du hast recht, bei mir sind es ~15ms.
Was für ein OS und welches Python nutzt du ?
Bei mir ist's Python 2.5 auf WinXP
WinXP SP3 Python 2.6
Ich pollo jetzt jede ms eine Variable in einer while..time.sleep Schleife, die vom anderen Thread geändert wird. Sehr unsauber, aber funktioniert ohne diese Schwankungen.
Für normale PC Programme sind die Schwankungen ja okay, aber für Echtzeitnahe Anwendungen tödlich.
Demnächst test ich das ganze mal mit dem "multiprocessing" Modul und Queues.
@b.esser-wisser:
Schöner Code, leider fehlt mir dazu oft die Zeit

Verfasst: Samstag 12. September 2009, 00:52
von Hand
Evtl währ Stackless Python auch noch ne Lösung, könnte das ganze zwar in c++ auslagern, dagegen wehre ich mich aber solangs anders geht
