Ich habe ein 60 GB SciPy Array (Matrix), das ich zwischen mehr als 5 multiprocessing
Process
Objekten teilen muss . Ich habe numpy-sharedmem gesehen und diese Diskussion auf der SciPy-Liste gelesen . Es scheint zwei Ansätze zu geben - numpy-sharedmem
und die Verwendung von a multiprocessing.RawArray()
und die Zuordnung von NumPy dtype
s zu ctype
s. Nun numpy-sharedmem
scheint der richtige Weg zu sein, aber ich habe noch kein gutes Referenzbeispiel gesehen. Ich brauche keine Sperren, da das Array (eigentlich eine Matrix) schreibgeschützt ist. Aufgrund seiner Größe möchte ich jetzt eine Kopie vermeiden. Es klingt so, als ob die richtige Methode darin besteht, die einzige Kopie des Arrays als sharedmem
Array zu erstellen und sie dann an die Process
Objekte zu übergeben. Einige spezifische Fragen:
Was ist der beste Weg, um die Sharedmem-Handles tatsächlich an Subes zu übergeben
Process()
? Benötige ich eine Warteschlange, um nur ein Array weiterzugeben? Wäre eine Pfeife besser? Kann ich es einfach als Argument an denProcess()
Init der Unterklasse übergeben (wo ich davon ausgehe, dass es eingelegt ist)?In der Diskussion, die ich oben verlinkt habe, wird erwähnt, dass es
numpy-sharedmem
nicht 64-Bit-sicher ist. Ich verwende definitiv einige Strukturen, die nicht mit 32-Bit adressierbar sind.Gibt es Kompromisse bei der
RawArray()
Herangehensweise? Langsamer, fehlerhafter?Benötige ich eine Zuordnung von Typ zu Typ für die Methode numpy-sharedmem?
Hat jemand ein Beispiel für OpenSource-Code, der dies tut? Ich bin sehr praktisch und es ist schwierig, dies zum Laufen zu bringen, ohne ein gutes Beispiel zu haben.
Wenn ich zusätzliche Informationen zur Verfügung stellen kann, um dies für andere zu klären, kommentieren Sie diese bitte und ich werde sie hinzufügen. Vielen Dank!
Dies muss unter Ubuntu Linux und möglicherweise Mac OS ausgeführt werden, aber die Portabilität ist kein großes Problem.
multiprocessing
für jeden Prozess eine Kopie des Ganzen erstellen.target_function
). Das Betriebssystem kopiert Teile des Speichers des Elternteils nur nach Änderung in den Speicher des Kindes.Antworten:
@ Velimir Mlaker gab eine tolle Antwort. Ich dachte, ich könnte ein paar Kommentare und ein kleines Beispiel hinzufügen.
(Ich konnte nicht viel Dokumentation zu sharedmem finden - dies sind die Ergebnisse meiner eigenen Experimente.)
target
undargs
für verwendenProcess
. Dies ist möglicherweise besser als die Verwendung einer globalen Variablen.Beispiel
Ausgabe
Diese verwandte Frage könnte nützlich sein.
quelle
Wenn Sie unter Linux (oder einem POSIX-kompatiblen System) arbeiten, können Sie dieses Array als globale Variable definieren.
multiprocessing
wird unterfork()
Linux verwendet, wenn ein neuer untergeordneter Prozess gestartet wird. Ein neu erzeugter untergeordneter Prozess teilt den Speicher automatisch mit seinem übergeordneten Prozess, solange er ihn nicht ändert ( Copy-on-Write- Mechanismus).Da Sie sagen "Ich brauche keine Sperren, da das Array (eigentlich eine Matrix) schreibgeschützt ist", wäre es ein sehr einfacher und dennoch äußerst effizienter Ansatz, dieses Verhalten auszunutzen: Alle untergeordneten Prozesse greifen darauf zu die gleichen Daten im physischen Speicher beim Lesen dieses großen numpy-Arrays.
Sie übergeben Sie Ihre Array nicht an den
Process()
Konstruktor, wird dieses anweisen ,multiprocessing
aufpickle
die Daten an das Kind, das in Ihrem Fall extrem ineffizient oder unmöglich wäre. Unter Linux ist direkt nachfork()
dem Kind eine exakte Kopie des Elternteils, die denselben physischen Speicher verwendet. Sie müssen also nur sicherstellen, dass die Python-Variable, die die Matrix enthält, über dietarget
Funktion, an die Sie übergeben, zugänglich istProcess()
. Dies können Sie normalerweise mit einer 'globalen' Variablen erreichen.Beispielcode:
Unter Windows - das nicht unterstützt
fork()
-multiprocessing
wird der Win32-API-Aufruf verwendetCreateProcess
. Es erstellt einen völlig neuen Prozess aus einer bestimmten ausführbaren Datei. Deshalb unter Windows eine ist erforderlich , um Beize Daten an das Kind , wenn ein Bedarf Daten , die während der Laufzeit des Mutter erstellt wurde.quelle
multiprocessing
Prozesse verwendet werden oder hängen bleiben ( In der Regel wird 1 / n eines Prozessors anstelle von n Prozessoren verwendet, wenn lineare Algebraoperationen an einem gemeinsam genutzten globalen Array / einer gemeinsam genutzten globalen Matrix ausgeführt werden. Der bekannte Multithread-Konflikt mit OpenBLAS scheint sich auf Pythonmultiprocessing
fork
, um die angegebenen Parameter zu übergebenProcess
, anstatt sie zu serialisieren? Das heißt, konnte das nichtfork
unmittelbar vor demchild
Aufruf auf den übergeordneten Prozess angewendet werden , sodass der Parameterwert weiterhin vom Betriebssystem verfügbar ist? Scheint effizienter zu sein als es zu serialisieren?fork()
dies unter Windows nicht verfügbar ist. Dies wurde in meiner Antwort und mehrfach in den Kommentaren angegeben. Ich weiß , dass dies Ihre erste Frage ist, und ich antwortete es vier Kommentare über diese : „Der Kompromiss ist auf beiden Plattformen standardmäßig die gleiche Methode der Parameterübergabe zu verwenden , für eine bessere Wartbarkeit und für gleiches Verhalten zu gewährleisten.“. Beide Möglichkeiten haben ihre Vor- und Nachteile, weshalb der Benutzer in Python 3 flexibler die Methode auswählen kann. Diese Diskussion ist ohne produktive Details nicht produktiv, was wir hier nicht tun sollten.Vielleicht interessiert Sie ein winziger Code, den ich geschrieben habe: github.com/vmlaker/benchmark-sharedmem
Die einzige Datei von Interesse ist
main.py
. Es ist ein Benchmark von numpy-sharedmem - der Code übergibt Arrays einfach (entwedernumpy
odersharedmem
) über Pipe an erzeugte Prozesse. Die Arbeiter rufen Sie einfachsum()
auf die Daten. Ich war nur daran interessiert, die Datenkommunikationszeiten zwischen den beiden Implementierungen zu vergleichen.Ich habe auch einen anderen, komplexeren Code geschrieben: github.com/vmlaker/sherlock .
Hier verwende ich das numpy-sharedmem- Modul für die Echtzeit-Bildverarbeitung mit OpenCV - die Bilder sind NumPy-Arrays gemäß der neueren OpenCV-
cv2
API. Die Bilder, eigentlich Referenzen davon, über das Dictionary - Objekt zwischen Prozessen gemeinsam erstellt vonmultiprocessing.Manager
(im Gegensatz zu verwenden Queue oder Rohr gegenüber .) Ich bin immer große Leistungsverbesserungen im Vergleich mit der Verwendung von Klar NumPy Arrays.Pipe vs. Queue :
Nach meiner Erfahrung ist IPC mit Pipe schneller als Queue. Und das ist sinnvoll, da Queue Sperren hinzufügt, um die Sicherheit für mehrere Hersteller / Verbraucher zu gewährleisten. Pipe nicht. Wenn Sie jedoch nur zwei Prozesse haben, die hin und her sprechen, ist es sicher, Pipe zu verwenden, oder, wie in den Dokumenten gelesen:
sharedmem
Sicherheit :Das Hauptproblem mit dem
sharedmem
Modul ist die Möglichkeit eines Speicherverlusts beim nicht ordnungsgemäßen Beenden des Programms. Dies wird in einer längeren Diskussion beschrieben hier . Obwohl Sturla am 10. April 2011 eine Korrektur für Speicherverluste erwähnt, habe ich seitdem immer noch Lecks festgestellt, bei denen beide Repos verwendet wurden, Sturla Moldens eigene auf GitHub ( github.com/sturlamolden/sharedmem-numpy ) und Chris Lee-Messers auf Bitbucket ( bitbucket.org/cleemesser/numpy-sharedmem ).quelle
sharedmem
klingt jedoch nach einer großen Sache. Irgendwelche Hinweise zur Lösung des Problems?sharedmem
Referenz die Bewahrer der beiden Open-Source-Repos des Moduls hinzugefügt .Wenn Ihr Array so groß ist, können Sie verwenden
numpy.memmap
. Wenn Sie beispielsweise ein Array auf der Festplatte gespeichert haben'test.array'
, können Sie auch im Schreibmodus simultane Prozesse verwenden, um auf die darin enthaltenen Daten zuzugreifen. Ihr Fall ist jedoch einfacher, da Sie nur den Lesemodus benötigen.Erstellen des Arrays:
Sie können dieses Array dann genauso füllen wie mit einem normalen Array. Beispielsweise:
Die Daten werden beim Löschen der Variablen auf der Festplatte gespeichert
a
.Später können Sie mehrere Prozesse verwenden, die auf die Daten zugreifen
test.array
:Verwandte Antworten:
Arbeiten mit Big Data in Python und Numpy, nicht genug RAM, wie kann man Teilergebnisse auf Disc speichern?
Ist es möglich, diskontinuierliche Daten auf der Festplatte einem Array mit Python zuzuordnen?
quelle
Es kann auch nützlich sein, die Dokumentation für pyro zu lesen, um Ihre Aufgabe entsprechend zu partitionieren und verschiedene Abschnitte auf verschiedenen Computern sowie auf verschiedenen Kernen auf demselben Computer auszuführen.
quelle
Warum nicht Multithreading verwenden? Ressourcen des Hauptprozesses können von seinen Threads nativ gemeinsam genutzt werden. Daher ist Multithreading offensichtlich eine bessere Möglichkeit, Objekte des Hauptprozesses gemeinsam zu nutzen.
Wenn Sie sich über den GIL-Mechanismus von Python Sorgen machen, können Sie vielleicht auf den
nogil
von zurückgreifennumba
.quelle