Multiprocessing shared memory

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
DivineTraveler
User
Beiträge: 7
Registriert: Montag 3. Januar 2022, 22:18

Hallo liebe Leute,

ich suche hier schon wie ein bekloppter nach einer Lösung für mein Problem. Ich habe schon viel über Queues, shared memory etc. durchforstet und es einfach noch nicht hinbekommen.

Was ich vor habe:
1 Hauptscript der laufend Daten von mehreren anderen Scripts bekommt und verarbeiten kann.

Mein Vorhaben:
Script 2 produziert in einer While-Schleife laufend Daten und speichert 2 Werte in die variablen "cH" und "cM".
Script 1 (Hauptscript) kann jederzeit (wenn benötigt) auf cH und cM zugreifen.

Multiprocessing habe ich schon gemeistert aber das Thema (shared_memory.ShareableList()) z.B. noch nicht. Da benötige ich Hilfe.
Mir würde ein einfaches Beispiel reichen, indem ganz einfach auf einen "Memory Share" von mehreren Scripts aus zugegriffen werden kann.


Schöne Grüße
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

So macht man das nicht. Sondern benutzt einfach eine Queue, mit der das eine Skript das andere füttert. Deine cH und cM sind dann einfach ein Tupel in dieser Queue. Und das Skript liest die eben bei Bedarf.
DivineTraveler
User
Beiträge: 7
Registriert: Montag 3. Januar 2022, 22:18

Hey danke erstmal für die Antwort.

In welchen Script wird die Queue erstellt ? Im Main Script oder in den der nur die Daten erzeugt?
DivineTraveler
User
Beiträge: 7
Registriert: Montag 3. Januar 2022, 22:18

Leute,

ich brauch da echt Hilfe...

1. Wo und wie genau erstelle die Queue?
2. Wie greife ich in den unterschiedlichen Scripts darauf zu?


Was ich bis jetzt habe:

Code: Alles auswählen

from multiprocessing import Queue
queue = Queue()

def states():
	    while 1:
            	statesData = [variablex, variabley]
            	queue.put(statesData)
            	print(queue.get())



Wie komme ich jetzt an diese Queue in einem anderen Script dran?

Gruß,
Divine
Sirius3
User
Beiträge: 18279
Registriert: Sonntag 21. Oktober 2012, 17:20

Lies nochmal die Dokumentation zu multiprocessing durch. Es ist dazu da, mehrere Funktionen parallel auszuführen, nicht Skripte.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Multiprocessing erlaubt die Aufteilung EINES Programms auf verschiedene Prozesse. Es ist nicht als generischer Interprozess-Kommunikations-Mechanismus gedacht.

Wenn deine Skripte unabhängig voneinander gestartet werden sollen, dann brauchst du da etwas anderes. Aber nur weil du das im Moment so machst, heißt das nicht, dass es so sein muss. Um das beurteilen zu können, musst du mal weiter ausholen, was dein eigentliches Problem ist.
Benutzeravatar
noisefloor
User
Beiträge: 4196
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

und selbst wenn du SharedMemory benutzen würdest, müsstest du jedem Skript eine Instanz übergeben, genau so wie bei eine Queue.

Wenn mehrere Skripten, die unabhänig voneinander gestartet werden, miteinander kommunizieren müssen, ist i.d.R. der einfachste Weg eine Datei oder eine Datenbank. Was aber _nicht_ heißt, dass das immer der sinnvollste Weg ist.

Gruß, noisefloor
DivineTraveler
User
Beiträge: 7
Registriert: Montag 3. Januar 2022, 22:18

Wäre denn multiprocessing in Zusammenhang mit redis eine Idee? Ist das schnell und performant genug?
Sirius3
User
Beiträge: 18279
Registriert: Sonntag 21. Oktober 2012, 17:20

Was bringst du denn jetzt redis ins Spiel? `multiprocessing` bringt doch alles für die Kommunikation mit.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du hast immer noch strikt vermieden, deinen eigentlichen Anwendungsfall zu beschreiben. Darum ist eine Frage nach “performant genug” natürlich nicht beantwortbar. Vielleicht geht es ja um high Speed trading, und da zählt jede Microsekunde. Oder eine Gartenbewässerung. Da nicht.

Unter der (ebenfalls unbestätigten) Annahme, mehrere Skripte sind wirklich das richtige, würde ich zu einer middleware wie nanomsg oder zeromq greifen. Redis ist auch ok, aber im Grunde schon Overkill.
DivineTraveler
User
Beiträge: 7
Registriert: Montag 3. Januar 2022, 22:18

Danke für die Antworten. Anbei noch eine Skizze welches Konstrukt ich mir vorstelle.

Skizze:
https://ibb.co/kJBQFV0
Sirius3
User
Beiträge: 18279
Registriert: Sonntag 21. Oktober 2012, 17:20

Die Skizze zeigt doch nur, was Du schon im Text geschrieben hast. Wie findet die Verarbeitung im Hauptprogramm statt? Irgendwie mußt Du ja die Prozesse synchronisieren, damit das Hauptprogramm weiß, wann wo neue Daten ankommen. Werden immer alle Daten gebraucht, oder immer nur die aktuellsten?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Was macht dein Programm? Woher kommen die Scanner, wer startet die, wie verhaelt sich deren Lebenszeit zur Lebenszeit des Hauptprogramms, welche Daten erheben die, welche Daten liefern die, und und und. Was *macht* das System. Nicht *wie* macht es das.
DivineTraveler
User
Beiträge: 7
Registriert: Montag 3. Januar 2022, 22:18

Also Codeseitig habe ich da noch gar nichts gebaut, weil ich noch dabei bin mir das hier(https://docs.python.org/3/library/multi ... emory.html) anzuschauen.
Es geht mir nur darum, wie ich diesen memory share überhaupt aufsetze und nutze.

Mir würde schon ein kleines Beispiel helfen, in dem 1 Script Daten in einer while Schleife produziert und laufend in den Share speichert.

Code nur angerissen...:

Code: Alles auswählen

# Script 1
share = share....

dataFromScript2 = share[0]

print(dataFromScript2)

# Script 2 (läuft als multiprocess)
getData()
def getData():
    while 1:
        data = random.randrange(0, 9)
        
        # ---> PUT "data" in share
Sirius3
User
Beiträge: 18279
Registriert: Sonntag 21. Oktober 2012, 17:20

Du glaubst, dass shared-memory die Lösung ist, aber bevor Du hier Lösungen ausprobierst, mußt Du doch Dein Problem richtig beschreiben können.

Beantworte doch bitte meine und __deets__' Fragen.
DivineTraveler
User
Beiträge: 7
Registriert: Montag 3. Januar 2022, 22:18

Ok.

Ich bin ganz neu in Python und hab kein Plan was ich tue. Ich springe ins kalte Wasser.

Ich habe mich mal mit den Grundlagen der Pixelerkennung auseinander gesetzt:

Ganz einfaches (Beispiel):

Code: Alles auswählen

    
     s = pyautogui.screenshot(region=(0,0, 500, 500))
    for x in range(s.width):
        for y in range(s.height):
            if s.getpixel((x, y)) == (white[0], white[1], white[2]):
                return [x, y]

Jetzt habe ich einfach mehere Funktionen erstellt (func1.py, func2.py, func3.py und func4.py) wobei jede Funktion unterschiedliche Bereiche auf meinen Desktop scannt und Arrays erzeugt mit Farbwerten und Koordinaten.

In meinen Main Script (main.py) steht bisher nur:

Code: Alles auswählen

if __name__ == '__main__':
Jetzt möchte ich, dass meine Funktionen 1-4 als einzelne Prozesse gestartet werden (Da weiß ich schon wie es funktioniert). Sie laufen alle parallel.
Ich möchte jetzt in jeder Funktion arrays befüllen (mit den Pixeldaten) und diese dann in dem share speichern.

In der main.py möchte ich dann auf diese Arrays zugreifen können.

Code: Alles auswählen

if __name__ == '__main__':

	func1Array = sharedMemory(func1Array)

	func1Array[0] = Farbe eines Ordners auf dem Desktop
	func1Array[1] = Koordinaten eines Ordners auf dem Desktop

Mir ist klar, das die Performance auch damit zusammenhängt wie effektiv ich die einzelnen Scanner programmiere. Jetzt brauche ich die schnellste Möglichkeit,
auf diesen Share XY zuzugreifen. Ob das jetzt am Ende shared Memory vom multiprocessing ist oder über TCP via API auf einen Online Server übertragen wird und von dort aus einer Datei ausgelesen wird ist mir egal :lol: :lol: :lol:

Reicht das an Informationen?
Sirius3
User
Beiträge: 18279
Registriert: Sonntag 21. Oktober 2012, 17:20

Shared-Memory brauchst Du hier in erster Linie gar nicht.
Erster Schritt ist es, eine ganz normale Funktion zu schreiben, die ein Array bekommt und eben einen Rückgabewert hat, wie auch immer der aussieht.
Und dann testet man das Programm, ob es das tut, wie es soll.
Sollte es zu langsam sein, dann schaut man, welche Stelle besonders langsam ist.
Dort schaut man dann, ob es einen schnelleren Algorithmus gibt, was bei Bildbearbeitung mit sehr großer Wahrscheinlichkeit der Fall ist.
Z.b. nutzt numpy mit Intel MKL schon alle Kerne Deiner CPU automatisch, da hilft multiprocessing gar nichts.
Mit numba kann man auch sehr einfach parallele Schleifen entwickeln, auch ganz ohne shared memory und multiprocessing. Zudem kann man damit eventuelle Berechnungen auf die Grafikkarte auslagen.
Hat man das alles ausgereizt und glaubt immer noch, dass multiprocessing hilft, dann im ersten Schritt ohne shared memory. Und erst dann, wenn man nachgewiesen hat, dass ein Großteil der Zeit auf Speicherkopieren draufgeht, dann überlegt man, wie man diese Situation durch shared memory entschärfen kann.
Benutzeravatar
noisefloor
User
Beiträge: 4196
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

EDIT: Antwort entfernt - hatte nicht alle Posts gelesen... die Antwort ist obsolet.

Gruß, noisefloor
Antworten