Prioritäten bei Threads
Input/Output. Dateien lesen, schreiben, Speicher allokieren (ist in Python nicht zu vermeiden), im Grunde jeder Systemaufruf der das Potential hat, lange auf die Bank geschoben zu werden. Wenn du logging betreibst, dann ist das unnoetig. Das kannst du auch aufsammeln und zB genauso wie die Nutzdaten an deinen zweiten Prozess uebergeben. Das ist dann nur noch ein Aufruf, und eine PIPE (welche der Queue unterliegt) sollte kein Problem darstellen.
- noisefloor
- User
- Beiträge: 3856
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
Hallo,
IO = jegliche Art von Eingabe / Ausgabe Operation, IO steht für Input/Output. IO ist halt immer um ein vielfaches langsamer als die CPU. Sprich: viel IO bremst das Programm.
Gruß, noisefloor
IO = jegliche Art von Eingabe / Ausgabe Operation, IO steht für Input/Output. IO ist halt immer um ein vielfaches langsamer als die CPU. Sprich: viel IO bremst das Programm.
Gruß, noisefloor
Das ist so nicht richtig. IO ist auch das beschreiben oder lesen von einer Pipe, und das ist zB komplett im Speicher und dem Kernel abgehandelt. Es kostet den Uebertritt in den Kernel, und der muss/soll dann natuerlich auch den wartenden Prozess/Thread aufwecken - aber das ist keine grosse, vor allem aber auch nicht unberechenbare Verzoegerung, wenn man das System ausreichend austariert hat.noisefloor hat geschrieben: ↑Montag 14. Januar 2019, 19:50 IO = jegliche Art von Eingabe / Ausgabe Operation, IO steht für Input/Output. IO ist halt immer um ein vielfaches langsamer als die CPU. Sprich: viel IO bremst das Programm.
Sonst koennten Echtzeit-Prozesse/Threads kaum sinnvolle Arbeit leisten - nur, wenn alles, was sie machen, auch in ihnen berechnet wuerde. Aber zB ein Roboter, der Sensordaten lesen und Aktuatoren bewegen soll, muss das in RT machen, bekommt ja aber Daten zugeliefert von langsamen und ggf. latentz-behafteten Systemen wie einer Kartierung oder aehnlichem.
__blackjack__ hat geschrieben: ↑Montag 14. Januar 2019, 16:06 @Muntliger: Jetzt verschiebt sich das zu was auch immer in ``channel_logger_count.info(str(setpoint))`` gemacht wird. Logger können ja beliebig komplizierte Dinge tun.
Ja, an der Geschwindigkeit ändert sich etwas, das ist aber nicht der Punkt. Eine Schleife ist kürzer, leichter lesbar, besser wartbar und damit weniger fehleranfällig. Wenn Du manuelles „loop unrolling“ machen willst, dann ist Python an der Stelle die falsche Programmiersprache.
Was Du auch sein lassen solltest ist das Vergleichen mit literalen Wahrheitswerten. Wobei ``is`` auch erst in aktuellen Python 3-Versionen überhaupt erst erlaubt ist. Und die beiden verschachtelten ``if``-Bedingungen hätte ich auch in *eine* gesteckt.
Ok, hab das jetzt alls Schleife gemacht - Danke für den Tipp
was hab ich für eine alternative als der Vergleich mit "is True" oder "is False"?
'is True' oder 'is False' sowieso niemals. Eigentlich brachst du niemals mit True oder False vergleichen, denn da kommt dann ja auch nur wieder True oder False raus. Also statt
kannst du gleich
schreiben. Fuer
dann
Code: Alles auswählen
if condition == True:
Code: Alles auswählen
if condition:
Code: Alles auswählen
if condition == False:
Code: Alles auswählen
if not condition:
Ich kann das Problem nicht finden.
Momentan füre ich nur diesen Code aus mit höchster Priorität (nice -10):
einige andere Codes laufen auf (nice 0)
alle 2-3 Sekunden dauert ein "Zyklus" mehr alls 5ms.
Meistens jedoch nur 1,3ms.
Bei einer Prio von -10 sollte doch dieser Codeteil immer gleich lang benötigen.
Wenn ich per TOP die CPU anschaue ist sie auf 72% idle.
Momentan füre ich nur diesen Code aus mit höchster Priorität (nice -10):
einige andere Codes laufen auf (nice 0)
Code: Alles auswählen
while True:
last = (time.time() * 1000) - now # speedtest
now = (time.time() * 1000) # speedtest
if last > 5:
print last
time.sleep(0.001)
Meistens jedoch nur 1,3ms.
Bei einer Prio von -10 sollte doch dieser Codeteil immer gleich lang benötigen.
Wenn ich per TOP die CPU anschaue ist sie auf 72% idle.
Und mit nice erreichst du keine Echtzeit-Priorität. Dazu kannst du das Tool chrt benutzen. Die Prioritäten sind dort anders nummeriert als bei nice. Je höher, je wichtiger. Ich würde dir mal SCHED_FIFO & 80 empfehlen.
ABER ACHTUNG: das ist alles Makulatur, wenn du die Ausführungen zu IO nicht beherzigst. Denn dann kann eine Operation dich beliebig lahm legen.
ABER ACHTUNG: das ist alles Makulatur, wenn du die Ausführungen zu IO nicht beherzigst. Denn dann kann eine Operation dich beliebig lahm legen.
Ok ich verstehe - hab das mal mit diesem Beispiel getestet:
Code: Alles auswählen
from time import time
start = time()
for i in range(10000):
print(i)
print('run time for printing:' + str(time() - start))
start = time()
for _ in range(10000):
pass
print('run time for no printing:' + str(time() - start))
Code: Alles auswählen
run time for printing:1.39491295815
run time for no printing:0.0173499584198
Link vergessen: https://www.cyberciti.biz/faq/howto-set ... y-process/
Und die Sache ist nicht ganz so einfach. Es geht nicht darum, das print zu benutzen mehr Zeit braucht als nichts zu machen. Das ist keine Erkenntnis. Es geht darum, ob die Wiederholungen des sleeps eine vorhersehbare Wartezeit produzieren. Dazu solltest du zb mit time.monotonic die tatsächliche Schlafenszeit messen. Und den Maximalen wert bestimmen. Und den ausgeben, aber erst nach längerer Laufzeit, und am besten unter Stress (Stress-ng —matrix 4 zb )
Allerdings its Python für sowas nicht ideal, weil man keine Kontrolle über SpeicheranForderung hat. Die allocation sollte bei einem simplen Programm das im Grunde immer das gleiche tut - warten, I2C, Interprozesskommunikation - stabil sein. Weil immer der gleiche Speicher angefordert, und dann freigegeben wird.
Ggf aber ist trotzdem der garbage collector Teil des Problems. Dann würde ich den mal prophylaktisch immer erzwingen zu laufen, damit dessen Arbeit immer gleich bleibt.
Wenn das alles nichts bringt, bleibt nur der Umstieg auf C/C++ für den I2C-Teil.
Allerdings its Python für sowas nicht ideal, weil man keine Kontrolle über SpeicheranForderung hat. Die allocation sollte bei einem simplen Programm das im Grunde immer das gleiche tut - warten, I2C, Interprozesskommunikation - stabil sein. Weil immer der gleiche Speicher angefordert, und dann freigegeben wird.
Ggf aber ist trotzdem der garbage collector Teil des Problems. Dann würde ich den mal prophylaktisch immer erzwingen zu laufen, damit dessen Arbeit immer gleich bleibt.
Wenn das alles nichts bringt, bleibt nur der Umstieg auf C/C++ für den I2C-Teil.
Und noch ein Nachtrag: print ist IO. Und braucht nicht nur “normal” lange. Sondern kann unter Umständen beliebig lange blockieren, weil der empfangene Prozess (das Terminal) nicht bereit ist, die Daten anzunehmen.
Solche Funktionen habe ich für jeden Kanal.
Gibt es eine bessere Lösung für einen "Hilfsmerker"?
Code: Alles auswählen
def channel3_active():
global ch3_active_hm
if data.channel3_active and ch3_active_hm:
ch3_active_hm = False
conf_logger.info('channel 3 - ACTIVATE')
print('channel 3 - ACTIVATE')
else:
pass
if not data.channel3_active and not ch3_active_hm:
ch3_active_hm = True
conf_logger.info('channel 3 - DEACTIVATE')
print('channel 3 - DEACTIVATE')
else:
pass
Das «else: pass» ist unsinnig. Globale Variablen nicht verwenden. Eine Funktion für alle Kanäle mit einem Parameter für die Kanalnummer wäre besser. `data` kommt aus dem nichts und sollte wohl auch ein Parameter sein, wahrscheinlich eine Liste mit einem Eintrag pro Kanal, am besten Instanzen einer Kanal-Klasse.
Aber ohne den gesamten Code zu kennen, kann man da halt schlecht helfen.
Aber ohne den gesamten Code zu kennen, kann man da halt schlecht helfen.
Das ist im "langsamen" Teil.
Hab's nun so gemacht:
Hab's nun so gemacht:
Code: Alles auswählen
def channel6_active():
global ch6_active_hm
if data.channel6_active and ch6_active_hm:
ch6_active_hm = False
conf_logger.info('channel 6 - ACTIVATE')
if not data.channel6_active and not ch6_active_hm:
ch6_active_hm = True
conf_logger.info('channel 6 - DEACTIVATE')
Hab den Code mal Online gestellt - bin für jeden Tipp dankbar.
Jetzt schonmal vielen Dank - ihr habt mir schon sehr weiter geholfen.
So macht das Python - lernen Spaß
http://gofile.me/3n8Ri/tTCe22Xs4
Jetzt schonmal vielen Dank - ihr habt mir schon sehr weiter geholfen.
So macht das Python - lernen Spaß
http://gofile.me/3n8Ri/tTCe22Xs4