Multi Threading mit Kernzuweisung bzw. Periodisierung möglich?

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Hallo zusammen,

    ich bin gerade dabei ein etwas umfangreicheres Programm in Python zu schreiben (viele Bausteine und so)

    Währenddessen laufen mehrere Prozesse und while schleifen zur Datenerfassung parallel.

    Also zb Thread 1 Erfasse Daten DHT22 in einer while mit 5s sleep am ende.

    Thread 2 erfasse Daten von Lichtsensor in einer while true schleife ebenso versetzt

    thread 3 aktualisiere LCD Display in while True mit 0.5s Sleep usw.

    soweit funktioniert das ganze auch.

    nun möchte ich parallel aber zb über einen weiteren Thread ein Video auf einen server streamen oder ein video ansehen was auch immer.

    Auf jedenfalls eine Aufgabe mit erhöhter Priorität ausführen.

    Da er bei den Threads aber immer durchwechselt kommt es zu ruckeln und Aussetzern.

    meine Frage daher, ist es möglich für den Stream (zb VLC Mediaplayer ... player.play()

    einen eigenen CPU kern zu reservieren oder diesen irgendwie anderweitig zu priorisieren?

    Ich könnte auch eine separate py Datei dafür anlegen und diese über os.system (oder subprocess) starten.

    hat jemand eine Idee?

    vielen Dank vorab und grüße :)

  • Multi Threading mit Kernzuweisung bzw. Periodisierung möglich?? Schau mal ob du hier fündig wirst!

  • Zur hilfreichsten Antwort springen
  • Du kannst auch versuchen den nice Wert für den vlc Player (oder andere Prozesse) zu verändern.

    < man nice >, < man renice >

    Der nice Wert, eine Ganzzahl zwischen -20 und (+) 19, wird z.B. in < top > angezeigt (Spalte NI)

    < nice -5 vlc > startet vlc mit einer höheren Priorität

    < nice 5 vlc > mit einer niedrigeren

    Servus !

    RTFM = Read The Factory Manual, oder so

  • hey ihr beiden vielen dank erstmal!

    Das mit dem passenden Problem kann ich nachvollziehen scheint quasi niemand zu haben xD

    CPU affinity klingt nach der sehr komplexen, stabilen aber unflexiblen lösung... wenn ich doch wieder umswitchen möchte scheint es komplex zj werden oder täusche ich mich hier?

    Das mit den nice werten find ich erstmal nice! Auf den ersten Blick kann ich diese auch im script immer wieder anpassen oder?

    Kann ich die nice werte auch im python regeln?

    Wenn nicht nicht schlimm aber dann spare ich mir zeit beim "warum klappt das nicht!!!???" XD

    Zur info am Rande es wird ein FM DAB+ radio mit funk, amp2 karte und alles geht über 1 2 Zeilen display und einen Drehencoder.

    Automatischer sendersuchlauf etc klappt schon aber dazu findet leider nur lösungen mit GUI und das passt halt nicht :)

    • Hilfreichste Antwort

    Hallo,

    Zitat

    einen eigenen CPU kern zu reservieren oder diesen irgendwie anderweitig zu priorisieren?

    Nein. Bei Threads entscheidet der Scheduler des Kernels, wer wann wo dran ist. Und innerhalb von Threads in Python entscheidet Python, wann der Wechsel zwischen Threads passiert.

    Ist dir klar, dass Threads in Python _nicht_ parallel laufen, zumindest nicht in CPython? Das Stichwort ist GIL, was bedingt, dass Threads in CPython wechselweise nacheinander laufen. Echte Nebenläufigkeit würdest du auf Mehrkern-CPUs mit dem Multiprocessing Modul bekommen.

    Wenn du viel I/O hast und wenig Rechenzeit brauchst, dann kann ggf. auch asyncio ein Weg sein.

    Zitat

    Ich könnte auch eine separate py Datei dafür anlegen und diese über os.system (oder subprocess) starten.

    Ist in 99% der Fälle falsch - innerhalb von Python importiert man andere Modul und nutzt dann deren Klassen / Methode. `os.system` ist veraltet, das steht auch wörtlich in der Python-Doku.

    Außerhalb von Python, also auf Betriebssystemeebene, kannst du Prozesse mit `nice` Priorisieren, mit `chrt` hast du erweitertn Zugriff auf Prioritäten, mit `taskset` kannst du ein Programm einem Kern zuordnen und mit `ionice` kannst du die I/O Priorität ändern.

    Und natürlich gilt auch: je leistungsschwächer dein Rechner ist und je mehr darauf gleichzeitig läuft, desto weniger Rechenzeit bekommt dein Programm, egal, was du einstellt.

    Gruß, noisefloor

  • guten Morgen Noisefloor,

    Danke für die frühe Antwort.

    Das man Funktionen, Klassen und methoden importiert usw. Ist mir klar davon hab ich schon gefühlte 50 :D.

    Die idee dahinter war eher die von dir erläutertete Problematik der Threads zu umgehen indem man einen Hintergrund Prozess schafft. Aber vermutlich fällt der auch ins Threading nehme ich an... (alles nacheinander aber eben sehr schnell)

    Das os.system veraltet ist habe ich bereits gelesen da subprocess. Wohl die neuere / flexiblete Variante ist die 4 module von os.system vereint. Hier schien für die ersten tests os.system aber erstmal einfacher zum ausführen einer einzelnen cmd zeile?

    An dieser sei aber gesagt das ich doe Vorteile von Subprocess noch nicht wirklich verstanden habe. Vielleicht könntest Du mir das nochmal klarer machen :)


    Das multiprocessing tool klingt sehr interessant!!

    Mein Raspi 3a+ hat ja einen Quadcore (btw sind das simulierte oder echte 4 Kerne?)

    Das heisst hier könnte ich theoretisch festlegen füre diese Anwendung nir auf kern0 aus, die andere auf kern 1 usw.?

    Wie verhält sich das wenn ein unterprogramm (nicht selbstgeschrieben) immer mit 5 Prozessen arbeitet?

    Vielen Dank schonmal! :)

    Ich werde mich jetz erstmal mit den genannten Begriffen weiter durchgooglen. Direkte Antworten sind aber meist hilfreicher :)

    Hättest du denn noch eine idee wie man das ganze am vernünftigsten / stabilsten usw. Angeht? Am ende soll es 24/7 headless laufen können Vielen Dank schonmal! :)

  • Hallo,

    welcher Prozess wann dran ist entscheidet auch der Scheduler des Kernels. Aber darauf kann man ja Einfluss nehmen, siehe oben. Plus das du Prozesse einem der vier physischen Kerne zuweisen kannst.

    Echte Nebenläufigkeit geht grundsätzlich auch mit Threads - nur halt nicht bei CPython, wegen des o.g. GIL. Andere Programmiersprachen und auch anderen Python-Implementierungen können das.

    Zitat

    Hättest du denn noch eine idee wie man das ganze am vernünftigsten / stabilsten usw. Angeht?

    In dem man fehlerfrei programmiert und das alles ausgiebig testet?

    Gruß, noisefloor

  • Hi Noisefloor super danke wieder mal! :)

    In dem man fehlerfrei programmiert und das alles ausgiebig testet?

    Das mache ich denke ich ganz gut :)

    alle möglichen Datentypen usw. alles klar definieren und if Daten OK anfragen vorausschicken.

    Echte Nebenläufigkeit geht grundsätzlich auch mit Threads - nur halt nicht bei CPython, wegen des o.g. GIL. Andere Programmiersprachen und auch anderen Python-Implementierungen können das.

    Welche Sprache könntest du mir denn empfehlen? Kann man eine Python Implementierung die das kann ins Raspi packen?

    Bzw. wie kann man das verstehen? ich dachte bisher das Python im Grunde in C geschrieben ist und daher immer auf C baut...

    Ich bin leider wissbegierig :)

    Hab aber auch soeben meinen 1000Seiten Python Schinken entgegen genommen...

    schönen Nachmittag!

    Ich werd mich mal mit den og. OS Befehlen (nice, chrt, tskset) und multiprocesing befassen.

    UUUND in Zukunft subprocess nutzen :danke_ATDE: :danke_ATDE:

  • Hallo,

    Zitat

    ich dachte bisher das Python im Grunde in C geschrieben ist und daher immer auf C baut...

    Ist es ja auch. Aber ist ist halt eine eigene Programmiersprache.

    IronPython und Jython haben keinen GIL - in wie fern diese Projekt aber noch Leben / relevant sind -> keine Ahnung.

    Eine Sprache, die Nebenläufigkeit sehr einfach eingebaut hat, ist Go - was aber _nicht_ heißt, dass das, was du vorhast, mit Go in irgendeiner Form einfacher ist.

    Grundsätzlich geht das auch alles mit Python und grundsätzlich ist nebenläufige Programmierung nicht trivial, wenn man ein paar mehr Prozesse / Threads braucht.

    Außerdem kommt beim I/O-basierten Sachen ja auch dazu, dass das das Lesen und Senden der Daten Zeit braucht, d.h. der limitierende Faktor ist (auch die Hardware). Der Raspi ist ja sowieso keine Leistingsrakate, aber er ist sicherlich auch nicht dafür bekannt, ultraschnelle Schnittstellen zu haben.

    Plus dein Programm teilt sich die Resourcen mit allen Prozessen, die sonst noch auf dem Pi laufen - je weniger das ist, desto besser.

    Die könntest auch einfach mal deinen Programmcode zeigen - vielleicht sind da auch Teile drin, die einfach nur CPU-Zeit verbrennen.

    Gruß, noisefloor

  • Wobei das GIL auch nicht alle Parallelität verhindert. Das wird auch bei bestimmten Aktionen in CPython freigegeben. Und wenn das was parallel laufen soll mit `subprocess` gestartet wurde, hat man ja einen anderen *Prozess* in dem Code ausgeführt wird. Das gleiche gilt für Python-Code der direkt mit dem `multiprocessing`-Modul gestartet wurde, oder indirekt über `concurrent.futures` über einen `ProcessPoolExecutor`.

    “Dawn, n.: The time when men of reason go to bed.” — Ambrose Bierce, “The Devil's Dictionary”

  • Damit machst du mich neugierig ?

    Da ich jetzt keine 3 import Dateien mit insgesamt ca 30 funktionen posten will.

    Ich mache möglichst viel über Funktionen, klassen unt entsprechende returns. Jede Funktion prüft Ihren part im Vorfeld auf ausführbarkeit und gibt im Zweifel derzeit eine 0 zurück. (Ich weiß 0 heisst eigentlich ok) die 0 ist noch ein Platzhalter später sollen hier fehlercodes rein die auf dem LCD ausgegeben werden :).

    Da die Ergebnisse also eigentlichen aufgaben der meisten Funktionen niemals 0 ist passt das gabz gut :D

    Ansonsten achte ich darauf möglichst wenig verschiedene Variablen gleichzeitig zu haben bzw. redundante Daten im Speicher zu vermeiden.

    Ein richtiger Banause bin ich im kommentieren xD dafür sind die Funktionen und übergaben sauber benannt.

    über ratschläge worauf man achten sollte usw. Bin ich trotzdem immer dankbar :)

    Habe auch erdt vor 2 oder 3 Monaten angefangen mit längerer Pause und mich davor eigentlich nur mit VBA beschäftigt ^^

    Gibt ja foren um besser zu werden :)

  • Hi Noisefloor,

    Die könntest auch einfach mal deinen Programmcode zeigen - vielleicht sind da auch Teile drin, die einfach nur CPU-Zeit verbrennen.

    Im Prinzip ist es eine if kette zur initialisierung die unter anderem 3 Threads startet mit simplen while schleifen und 3 - 20 sekunden intervall.

    Hier werden einfach nur sensoren abgeklopft. Im anschluss die Daten umgerechnet / stringst geteilt und formatiert und dann schnalzt er das über eine get request mit parametern in der url auf einen server.


    Aber!

    Außerdem kommt beim I/O-basierten Sachen ja auch dazu, dass das das Lesen und Senden der Daten Zeit braucht, d.h. der limitierende Faktor ist (auch die Hardware). Der Raspi ist ja sowieso keine Leistingsrakate, aber er ist sicherlich auch nicht dafür bekannt, ultraschnelle Schnittstellen zu haben.

    Plus dein Programm teilt sich die Resourcen mit allen Prozessen, die sonst noch auf dem Pi laufen - je weniger das ist, desto besser.

    ich habe 3 interrupts bzw 3 pins, deren funktion läuft aber nur einmal und setzt die Parameter für eine dauernde while schleife anders.

    Und

    Beim Booten wird ein WLAN hotspot über GSM / LAN als Quelle gehostet. Könnte mir vorstellen das der auch einiges zieht.

    Das geht mit dem sim7600 modul angeschlossen über USB Und mit ... mir kommt der name nicht eine Hotspot software recht bekannt mit GUI über die IP HOST AP kann das sein?

    Aber im idle ist ser pi eigentlich sehr ruhig.


    Bevor das player zeug startet mache ich noch einen virtuellen Chrome auf und ziehe einen html sourcecode mit selenium aber hier word alles beendet bevor es zum datenstream kommt.


    Viele Grüße :)

  • Mir kam gerade noch der einfall... wie wäre es denn wenn ich einen Pico oder ein Arduino dazu schalte um zb die Interrupts und das updaten des LCD umzusetzen?

    Da könnte man doch sicherlich über I2c oder RxTx ein paar variablen rüberjagen oder?

    Oder evtl den DHT22 auslesen prozess ... einen teil der threads eben. :/

  • Das mit den 0-Rückgabewerten bzw. allgemein spezielle Fehlerrückgabewerte klingt nicht so sauber. Ausnahmen wurden erfunden um das zu umgehen, dass man a) aufpassen muss das Fehlerwerte nicht gültige Werte sein können, und b) das man einerseits nicht immer alle Rückgabewerte explizit prüfen muss, andererseits aber auch keine Ausnahmen unbemerkt durchrutschen.

    “Dawn, n.: The time when men of reason go to bed.” — Ambrose Bierce, “The Devil's Dictionary”

  • Das mit den 0-Rückgabewerten bzw. allgemein spezielle Fehlerrückgabewerte klingt nicht so sauber. Ausnahmen wurden erfunden um das zu umgehen, dass man a) aufpassen muss das Fehlerwerte nicht gültige Werte sein können, und b) das man einerseits nicht immer alle Rückgabewerte explizit prüfen muss, andererseits aber auch keine Ausnahmen unbemerkt durchrutschen.

    Ja da gebe ich dir Recht. Das wäre aus code sicht sicherlich sauberer.

    Das Problem hierbei das ich immer wieder hatte Wenn ein sensor mal unerwartet irgendwas ausgespuckt hat hat es gedauert die funktion zu finden die sich daran aufhängt. Deswegen habe ich if's zb. Wenn daten nicht woe erwsrtet dann print fehler in funktion xy + datensatz und ein return.

    Dementsprechend beginnen die meisten Funktionen mit wenn != 0 bzw zukünftig mit if not error in.

    So dachte ich kann ich einen fehler beim "entwickeln" einfacher detektieren. Und trotzdem einen sauberen Ablauf halten da die while schleifen im basis programm weiter ihre runde ziehen.


    Oder ist das trotzdem total verkehrt? ?

  • Gibt es aktuell überhaupt in deinem System Probleme mit der Leistung weil du etwas priorisieren willst? Was ich so herauslese sollte ja eigentlich für den Raspberry keine große Hürde sein. Ein paar Werte erfassen und ein Display aktualisieren ist ja kein wirklicher Aufwand.

    Wenn du wirklich Leistungsprobleme hast, dann ist es sehr wahrscheinlich dass dein Python Programm nicht gut durchdacht ist (das meine ich nicht als Kritik). Es wäre sehr hilfreich wenn du deinen Code einmal teilen würdest. Du musst ihn ja nicht hier im Forum posten, sondern könntest ihn bei Github (auch für ein eigenes Backup) ablegen.

    Ich persönlich bin auch schon in einige Fettnäpfchen getreten die nicht ganz offensichtlich sind. Bei sehr komplexen Python Lösungen nutze ich gerne https://nuitka.net die Ergebnisse sind oft abhängig von den Bedingungen sehr viel schneller. Ich bin mir jetzt nicht sicher betreffend Threads in Python, ich habe ewig nicht mehr damit gearbeitet. Aber ein Python Programm mit fiktiv 100 Threads bleibt trotzdem nur ein einzige Prozess. Wenn du wirklich ein Programm über mehrere Kerne laufen lassen willst gibt es spezielle Bibliotheken die das ermöglichen. Dann hast du voneinander unabhängige einzelne Programme die miteinander kommunizieren. Bedeutet aber natürlich auch einiges an Overhead. Da muss man abwägen ob dieser Overhead lohnend ist. Wenn du in diesem Bereich aber keine Expertise besitzt, dann lass es. Es würde nur in Frust enden, da wir hier über eine sehr komplexe Sache reden über die man ganze Bücher schreiben könnte.

    BTW Schau mal in die Entwicklerecke vom Django Projekt. Die Entwickler dort haben hunderte Beiträge zum Scaling in Python veröffentlicht. Da kannst du auch erfahren welche Möglichkeiten du hast. Aber wie gesagt es ist absolute Experten Kost.

  • hi intergeek,

    Nuitka werd ich mal anschauen danke!

    Naja das es wirkliche Leistungs Probleme sind kann ich mir so gesehen auch nicht vorstellen.

    Ich vermute nunmal das sich die threads ansammeln und wenn dann final eine Zahl x zwischen 2 streaming anfragen steht eine Verzögerung stattfindet.

    Mit einem eigenen Kern rein dafür könnte ich das zumindest mal ausschließen.

    Das bisschen sensor ist auch eigentlich nicht wild letzenendes wird aber ja ein mediastream gehostet, selbiger zugleich gestreamt, während ein Mobilfunk wlan hotspot gehostet wird.

    Und dann noch Interrupts und threads. Da das alles gleichzeitig kommt kann sich da einiges aufsummieren denke ich was dann einen Rückstau erzeugt.

    Das ruckelnd kommt ja im Zeitintervall ähnlich wie die Abfragen der sensoren.

  • Schau mal während alles läuft die Auslastung des Systems an, z.B mit Top/htop. Wenn die Last dort nicht hoch ist, dann schau dir mal das Dateisystem an. Wenn die Daten von einer Speicherkarte oder langsamen Medium kommen, dann kann das schon ausreichen das an irgendeiner Stelle etwas blockiert wird bis der lese oder Schreibvorgang beendet ist.

    Welches System nutzt du? Du könntest mal DietPi anschauen, im Gegensatz zu Raspbian oder RaspberryOs ist es sehr schlank. In meiner Orgel habe ich Lxde mir etwa 100mb Ramverbrauch.

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!