24

Ich mache ein Programm zum Ausführen von Simulationen in Python, mit einer wxPython-Schnittstelle. Im Programm können Sie eine Simulation erstellen, die das Programm für Sie rendert (berechnet). Rendering kann manchmal sehr zeitaufwendig sein.Multiprocessing oder Multithreading?

Wenn der Benutzer eine Simulation startet und einen Anfangszustand definiert, möchte ich, dass das Programm die Simulation kontinuierlich im Hintergrund rendert, während der Benutzer möglicherweise verschiedene Dinge im Programm ausführt. So ähnlich wie eine YouTube-Leiste, die voll ist: Sie können die Simulation nur bis zu dem Punkt abspielen, der gerendert wurde.

Sollte ich mehrere Prozesse oder mehrere Threads verwenden oder was? Die Leute sagten mir, ich solle das Paket multiprocessing verwenden, ich habe es überprüft und es sieht gut aus, aber ich habe auch gehört, dass Prozesse im Gegensatz zu Threads nicht viele Informationen teilen können (und ich denke, dass mein Programm viele Informationen teilen muss) .) Außerdem habe ich auch von Stackless Python gehört: Ist das eine separate Option? Ich habe keine Ahnung.

Bitte beraten.

+0

Ich mache mir Sorgen um Ihr "Ich denke, dass mein Programm eine Menge Informationen teilen muss" - Sie meinen, Sie wissen es noch nicht ?? Vielleicht solltest du mehr Designarbeit leisten. Das Multiprocessing-Modul ist locker mit dem Threading-Modul kompatibel, daher sollte das Umschalten kein großer Aufwand sein. Aber hüte dich vor GIL, was mich zu Multiprocessing machen würde. – CyberFonic

Antwort

1

Ich bevorzuge immer mehrere Threads zur Vereinfachung, aber es gibt ein echtes Problem mit Affinität. Es gibt keine Möglichkeit (von der ich weiß), Pythons Threading-Implementierung anzuweisen, sich an einen bestimmten Prozessor zu binden. Dies mag kein Problem für Sie sein, es klingt nicht so, wie es sein sollte. Es sei denn, Sie haben einen guten Grund, es nicht zu tun, es klingt, als ob Ihr Problem mit Pythons Threading-Implementierung leicht gelöst werden kann.

Wenn Sie sich für die Verarbeitung entschieden haben, kann die gemeinsame Nutzung von Informationen zwischen Unterprozessen auf verschiedene Arten erfolgen: tcp/udp-Verbindungen, gemeinsam genutzter Speicher oder Pipes. Es fügt einige Overhead und Komplexität hinzu.

+1

+1: Threading ist ein sehr, sehr natürliches Format für die Arbeit mit ereignisgesteuerten GUIs, und es hilft Ihnen, den Schmerz der Kommunikation zwischen den Prozessen zu vermeiden (es sei denn, Ihre Informationsfreigabe ist für die eingeschränkten Optionen von Shane gut geeignet). – ojrac

+1

1. Würden Threads automatisch alle Kerne in der CPU nutzen? 2. Hast du eine Idee, wie Stackless in all das passt? –

+0

Die Sache über Threads ist, dass sie "im Allgemeinen" unter der Kontrolle des Betriebssystems stehen, und alle OSs sind ziemlich gut darin, die Lasten über die CPUs zu verteilen. Dies ist im Allgemeinen das gewünschte Verhalten. Sie können sich jedoch Szenarien vorstellen, in denen Sie eine einzelne Task an eine einzelne CPU senden möchten. –

18

„Ich habe es überprüft, und es sieht gut aus, aber ich habe auch gehört, dass die Prozesse, im Gegensatz zu Fäden, nicht viele Informationen teilen können ...“

Dies ist nur teilweise wahr ist.

Threads sind Teil eines Prozesses - Threads teilen Speicher trivially. Das ist genauso ein Problem wie eine Hilfe - zwei Threads, die sich gegenseitig ignorieren, können den Speicher überschreiben und ernste Probleme verursachen.

Prozesse teilen jedoch Informationen durch eine Vielzahl von Mechanismen. Eine Posix-Pipeline (a | b) bedeutet, dass Prozess a und Prozess b Informationen teilen - a schreibt sie und b liest sie. Das funktioniert sehr gut für viele Dinge.

Das Betriebssystem weist Ihre Prozesse jedem verfügbaren Kern so schnell zu, wie Sie sie erstellen. Das funktioniert für viele Dinge sehr gut.

Stackless Python hat nichts mit dieser Diskussion zu tun - es ist schneller und hat eine andere Thread-Planung. Aber ich denke nicht, dass Threads der beste Weg dafür sind.

"Ich denke, dass mein Programm eine Menge Informationen teilen muss."

Sie sollten dies zuerst lösen. Bestimmen Sie dann, wie Prozesse um den Informationsfluss strukturiert werden sollen. Eine "Pipeline" ist sehr einfach und natürlich zu machen; Jede Shell wird die Pipeline trivial erstellen.

Ein "Server" ist eine andere Architektur, bei der mehrere Client-Prozesse Informationen auf einem zentralen Server abrufen und/oder bereitstellen. Dies ist eine großartige Möglichkeit, Informationen zu teilen. Sie können die WSGI-Referenzimplementierung verwenden, um einen einfachen, zuverlässigen Server zu erstellen.

14
  • Stackless: verwendet 1 CPU. "Tasklets" müssen freiwillig nachgeben. Die Vorkaufsoption funktioniert nicht immer.
  • Gewinde: verwendet 1 CPU. Native Threads teilen die Zeit zufällig nach dem Ausführen von 20-100 Python-Opcodes.
  • Multi: verwendet mehrere CPU

aktualisieren

Indepth Analyse

Verwendung für eine einfache Zeit eingefädelt. Wenn Sie jedoch C-Routinen aufrufen, die eine lange Zeit vor dem Zurückgeben dauern, dann ist dies möglicherweise keine Wahl, wenn Ihre C-Routine die Sperre nicht freigibt.

Verwenden Sie Multiprocessing, wenn es sehr begrenzt durch CPU-Leistung ist und Sie maximale Reaktionszeit benötigen.

Verwenden Sie nicht stackless, ich hatte es segfault zuvor und Threads sind ziemlich gleichwertig, es sei denn, Sie verwenden Hunderte von ihnen oder mehr.

+5

Das ist das erste Mal, dass ich jemanden sagen hörte, Threading sei einfach. IMO-Thread-Code ist sehr schwer gut zu schreiben. –

5

Mit CPython können mehrere Threads wegen der GIL nicht gleichzeitig ausgeführt werden: link text.

Ich denke, es ist immer noch möglich, dass Threads Ihre Anwendung, z. Ein Thread blockiert möglicherweise E/A, während ein anderer etwas Arbeit leistet.

Wenn Sie noch nie Threads verwendet haben, schlage ich vor, dass Sie sie zuerst ausprobieren. Es wird in jeder anderen Sprache nützlich sein, und Sie werden eine Menge Ressourcen im Internet finden. Dann, wenn Sie erkennen, dass Sie mehr Parallelität benötigen, können Sie immer noch zu Prozessen wechseln.

10

Ein Prozess hat seinen eigenen Speicherplatz. Es erschwert den Austausch von Informationen, macht das Programm aber sicherer (weniger Bedarf für explizite Synchronisation). Davon abgesehen können sich Prozesse im Nur-Lese-Modus denselben Speicher teilen.

Ein Thread ist billiger zu erstellen oder zu töten, aber der Hauptunterschied ist, dass er Speicher mit anderen Threads im selben Prozess teilt. Dies ist manchmal riskant, und ein Absturz des Prozesses würde alle Threads beenden.

Ein Vorteil der Verwendung mehrerer Prozesse über mehrere Threads besteht darin, dass es einfacher ist, Ihr Programm so zu skalieren, dass es mit mehreren Computern arbeitet, die über Netzwerkprotokolle kommunizieren.

Zum Beispiel könnten Sie möglicherweise 16 Prozesse auf 8 Dual-Core-Rechnern ausführen, aber keinen Vorteil von mehr als 4 Threads auf einem Quad-Core-Rechner haben. Wenn die Menge an Informationen, die Sie kommunizieren müssen, gering ist, kann eine Mehrfachverarbeitung sinnvoller sein.

Wie für den Youtube-Stil, den Sie beschrieben haben, würde ich sagen, dass Multiprozessing vorschlägt. Wenn Sie MVC-Ansätzen folgen, sollte Ihre GUI nicht auch das Modell enthalten (Berechnungsergebnis). Mit dem Multiprozess können Sie dann mit einem Arbeitsmanager kommunizieren, der angeben kann, welche Daten bereits verfügbar sind.

+0

"Prozesse können den gleichen Speicher im schreibgeschützten Modus teilen" Ich denke, dass das für mich sehr nützlich sein wird. Wie mache ich das? –

+0

Wenn Sie auf den meisten UNIX-Systemen einen Prozess forkieren (einen von dem anderen erstellen), sollten sie dieselben Lese-Seiten teilen, bis sie schreiben. Es spart das Laden des Programmcodes. Aber es ist nicht so nützlich wie eine Programmiertechnik. – Uri

+0

Leider ist das unter Windows nicht der Fall (Windows hat keine os.fork verfügbar). –

14

In diesem Jahr gab es auf der Pycon einen guten Vortrag über Multiprozessing.Die Nachricht zum Mitnehmen war "Verwenden Sie Multiprozessing nur, wenn Sie sicher sind, dass Sie ein Problem haben, das es lösen wird, das nicht mit Threads gelöst werden kann; andernfalls verwenden Sie Threads."

Prozesse haben viel Overhead, und alle Daten, die von Prozessen gemeinsam genutzt werden, müssen serialisierbar sein (dh pickleable).

Sie können die Folien und Video hier sehen: http://blip.tv/pycon-us-videos-2009-2010-2011/introduction-to-multiprocessing-in-python-1957019

http://us.pycon.org/2009/conference/schedule/event/31/

+3

Das ist bedauerlich, denn das ist fast das Gegenteil von dem, was Sie in anderen Sprachen tun würden, wo es möglich ist. Threads sind fehleranfällig und im Vergleich zu Prozessen begrenzt, und in Python erhalten Sie das GIL-Problem, um die Verletzung zu beleidigen. – Kylotan

+9

Während es zutrifft, dass mehrere Prozesse ein wenig Laufzeit-Overhead haben (obwohl das weniger wahr ist als vor fünf oder zehn Jahren), hat Threaded-Code sehr viel Programmieraufwand. Es braucht kluge Leute, um guten Thread-Code zu schreiben, und _sehr_ kluge Leute, um es zu debuggen. –

+1

Gibt es einen aktualisierten Link zu diesen Folien? Der aktuelle Link scheint nicht verfügbar zu sein. – Tyler

0

Es klingt wie Sie Threading wollen würde.

Die Art und Weise, wie Sie es beschrieben haben, klang so, als gäbe es nur eine einzige Sache, die eine Menge CPU benötigt ... den tatsächlichen Ablauf der Simulation.

Was Sie versuchen, ist mehr reaktionsschnelle Anzeigen, indem Benutzerinteraktion und Grafikupdates während der Simulation zulassen. Genau dafür wurde Pythons Threading entwickelt.

Was Sie NICHT bekommen wird, ist die Fähigkeit, mehrere Kerne/Prozessoren auf Ihrem System zu nutzen. Ich habe keine Ahnung, wie Ihre Simulation aussieht, aber wenn es CPU-intensiv ist, könnte es ein guter Kandidat für die Aufteilung sein. In diesem Fall können Sie mit Multiprocessing separate Teile der Simulation auf separaten Kernen/Prozessoren ausführen. Dies ist jedoch nicht trivial ... Sie benötigen nun eine Möglichkeit, Daten zwischen den Prozessen hin- und herzuübertragen, da die separaten Prozesse nicht einfach auf denselben Speicherplatz zugreifen können.

4

Wenn Sie eine längere Diskussion über Multi-Threading in Mozilla lesen möchten, werfen Sie einen Blick auf this discussion, die im Jahr 2000 begann. Die Diskussion beantwortet nicht unbedingt Ihre Frage. Es ist jedoch eine eingehende Diskussion, die ich für interessant und informativ halte, was meiner Meinung nach sehr wertvoll sein kann, weil Sie eine schwierige Frage gestellt haben. Hoffentlich hilft es Ihnen, eine informierte Entscheidung zu treffen.

Übrigens waren mehrere Mitglieder des Mozilla-Projekts (insbesondere Brendan Eich, Mozillas CTO und der Schöpfer von JavaScript) ziemlich kritisch gegenüber Multi-Threading. Ein Teil des Materials, das mit here, here, here und here bezeichnet ist, unterstützt eine solche Schlussfolgerung.

Hoffe, dass hilft und viel Glück.

1

Sehr verwirrt. Bastien Léonard hat zu Recht darauf hingewiesen, dass die GIL jede Fähigkeit, Threading auf irgendeine nützliche Weise zu verwenden, unterbinden wird. Seine Referenzzustände:

„Die Verwendung eines globalen Interpreter Lock in einer Sprache effektiv begrenzt die Menge an Parallelität erreichbar durch Gleichzeitigkeit eines einzelnen Interpreter Prozess mit mehreren Threads Wenn der Prozess fast ist rein, bestehend aus. interpretierte Code und macht keine Anrufe außerhalb von der Interpreter für längere Zeiträume (die die Sperre auf der GIL auf diesem Thread freigeben kann, während es verarbeitet), gibt es wahrscheinlich sehr geringe Steigerung der Geschwindigkeit beim Ausführen des Prozesses auf einem Multiprozessor-Rechner.Durch Signalisierung mit einem CPU-gebundenen Thread kann es können verursachen eine deutliche Verlangsamung, sogar auf einzelnen Prozessoren. "

Dies ist der Fall, Multi-Processing ist dann die vernünftige Wahl.Aus eigener Erfahrung hat Python + MT für den Benutzer keinen spürbaren Nutzen.