Frage

Also ich habe gerade dieses Gespräch gerade auf dem Python Globalen Interpreter Lock (GIL) http://blip.tv/ Datei / 2232410 .

Das Wesentliche ist, dass die GIL ein ziemlich gutes Design für einadrige Systeme (Python Wesentlichen verlässt die Fadenhandhabungs / Terminierung bis zum Betriebssystem). Aber dass dies Multi-Core-Systeme nach hinten losgehen ernsthaft auf und Sie am Ende mit IO intensiven Threads stark von CPU intensiven Threads blockiert werden, die Kosten der Kontextwechsel, das ctrl-C Problem [*] und so weiter.

So, da die GIL begrenzt uns im Grunde ein Python-Programm ausführen, auf einer CPU meines Gedanke ist, warum das nicht akzeptieren und einfach verwenden taskset auf Linux die Affinität des Programms zu einem bestimmten Core / CPU auf dem System zu setzen (vor allem in eine Situation mit mehreren Python-Anwendungen auf einem Multi-Core-System ausgeführt wird)?

So letztlich meine Frage ist: hat jemand versucht, mit taskset auf Linux mit Python-Anwendungen (vor allem, wenn mehrere Anwendungen auf einem Linux-System ausgeführt werden, so dass mehrere Kerne auf einen bestimmten Kern gebunden mit einer oder zwei Python-Anwendungen verwendet werden) und wenn ja, was waren die Ergebnisse? lohnt es sich, zu tun? Ist es alles noch schlimmer für bestimmte Workloads machen? Ich plane, dies zu tun und es teste (im Grunde sehen, ob das Programm mehr oder weniger Zeit in Anspruch nimmt laufen), aber würde gerne von anderen als zu Ihren Erfahrungen zu hören.

Zusatz: David Beazley (der Mann das Gespräch in der verknüpften Video geben) wies darauf hin, dass einige C / C ++ Erweiterungen manuell die GIL Sperre wieder freigeben und wenn diese Erweiterungen für Multi-Core (dh wissenschaftliche oder numerische Datenanalyse / etc optimiert sind .) dann nicht die Vorteile von Multi-Core für Zahlknirschens die Erweiterung immer effektiv wäre gelähmt, dass sie wesentlich zu einem einzigen Kern (und damit potenziell verlangsamen Ihr Programm nach unten) begrenzt sind. Auf der anderen Seite, wenn Sie nicht mit Erweiterungen wie diese

Der Grund, warum ich nicht das Multiprocessing-Modul bin ist, dass (in diesem Fall) Teil des Programms ist stark Netzwerk-I / O Bindung (HTTP-Requests) so einen Pool von Arbeitsthreads ist eine großartige Möglichkeit, die Leistung zu entlocken ein Feld, da ein Thread feuert eine HTTP-Anforderung und dann, da es auf der I wartet / O gibt die GIL und ein anderer Thread kann es tun ist Sache, so dass ein Teil des Programms leicht über 100 Fäden, ohne zu verletzen die CPU viel laufen und lassen ich tatsächlich nutzt die Netzwerk-Bandbreite, die verfügbar ist. Wie für stackless Python / etc bin ich nicht sonderlich daran interessiert, das Programm umzuschreiben oder meine Python-Stack zu ersetzen (Verfügbarkeit wäre auch ein Anliegen sein).

[*] Nur der Hauptthread kann Signale empfangen, wenn Sie also ein ctrl-C der Interpreter im Grunde Python senden versucht, den Haupt-Thread zu bekommen laufen, so kann er das Signal verarbeiten, aber da es nicht direkt steuern, die Gewinde ausgeführt wird (dies ist mit dem Betriebssystem links) es sagt das O Schalt Threads zu halten, bis sie schließlich den Haupt-Thread trifft (die, wenn Sie Pech haben, kann eine Weile dauern).

War es hilfreich?

Lösung

Ich habe noch nie von jemandem mit taskset für einen Performance-Gewinn mit Python gehört. Bedeutet nicht, es nicht in Ihrem Fall passieren kann, aber auf jeden Fall Ihre Ergebnisse veröffentlichen, damit andere Ihre Benchmarking-Methoden Kritik und Validierung liefern.

Persönlich obwohl, würde ich Ihre E / A-Threads von den CPU gebunden Threads mit einer Nachrichten-Warteschlange entkoppeln. Auf diese Weise Ihr vorderes Ende ich jetzt vollständig Netzwerk / O Bindung (einige mit HTTP-Schnittstelle, einige mit Message Queue Interface) und ideal für Ihre Threading Situation. Dann wird die CPU intensive Prozesse entweder Multiprozessing verwenden können, oder auch nur einzelne Prozesse für die Arbeit warten sein auf der Nachrichten-Warteschlange zu gelangen.

Auf längere Sicht wollen Sie vielleicht auch Ihre Gewinde I / O-Front-End mit Twisted-oder etwas wie eventlets da, auch wenn sie die Leistung nicht helfen, sie Skalierbarkeit verbessern sollte. Back-End ist nun bereits skalierbar, weil Sie Ihre Nachrichtenwarteschlange über eine beliebige Anzahl von Maschinen + CPUs je nach Bedarf ausgeführt werden können.

Andere Tipps

Eine andere Lösung ist: http://docs.python.org/library/multiprocessing.html

Anmerkung 1:. Dies ist nicht eine Einschränkung der Sprache Python, aber von CPython Implementierung

Hinweis 2: Im Hinblick auf die Affinität, Ihr Betriebssystem sollte kein Problem, dass selbst zu tun haben

.

Eine interessante Lösung ist das Experiment von Ryan Kelly in seinem Blog berichtet: http://www.rfk.id.au/blog/entry/a-gil-adventure-threading2/

Die Ergebnisse scheinen sehr zufrieden stellend.

Ich habe die folgende Faustregel gilt: ausreichend über die Jahre gefunden: Wenn die Arbeiter auf einigen gemeinsamen Staat abhängig sind, verwende ich ein Multiprozessor-Prozess pro Kern (CPU gebunden ist), und ein Fix Pool von Arbeitsthreads pro Kern (I / O-gebunden). Das Betriebssystem wird die verschiedenen Python-Prozesse von assigining auf die Kerne kümmern.

Der Python GIL ist per Python-Interpreter. Das heißt, die nur Probleme mit ihm zu vermeiden, während Multiprozessing tun einfach ist, mehrere Dolmetscher starten (das heißt unter Verwendung von separaten Prozessen anstelle von Threads für Nebenläufigkeit) und dann einige andere IPC primitive Verwendung für die Kommunikation zwischen den Prozessen (wie Steckdosen). Davon abgesehen, die GIL ist kein Problem, wenn Gewinde mit blockierenden E / A-Anrufen verwendet wird.

Das Hauptproblem der GIL wie früher erwähnt, dass Sie nicht mehr als 2 verschiedenen Python-Code Threads gleichzeitig ausführen können. Ein Gewinde auf einer blockierenden I / O Anrufblockierung blockiert ist und daher nicht Python-Code executin. Das bedeutet, es ist nicht die GIL blockiert. Wenn Sie zwei CPU-intensive Aufgaben in separaten Python-Threads haben, das ist, wo die GIL Multi-Processing in Python tötet (nur die CPython Implementierung, wie bereits erwähnt). Da die GIL stoppt CPU # 1 aus einem Python-Thread ausgeführt wird, während CPU # 0 besetzt ist den anderen Python-Thread ausgeführt wird.

Bis zu diesem Zeitpunkt als GIL aus Python entfernt, Co-Routinen können anstelle von Threads verwendet werden. Ich habe es auf gute Behörde, dass diese Strategie wurde von zwei erfolgreichen Start-ups umgesetzt wurden, greenlets in mindestens einem Fall verwendet wird.

Dies ist eine ziemlich alte Frage, aber da jedes Mal wenn ich über Informationen suche im Zusammenhang mit Python und Performance auf Multi-Core-Systemen dieser Beitrag immer auf der Ergebnisliste ist, würde ich diese Vergangenheit nicht lassen, bevor ich nicht noch meine Gedanken teilen.

Sie können die Multiprocessing-Modul verwenden, anstatt für jede Aufgabe Threads zu erstellen, erstellt es einen weiteren Prozess der CPython Compier Code zu interpretieren. Es wäre Ihre Anwendung, um die Vorteile von Multicore-Systemen übernehmen. Das einzige Problem, das ich auf diesem Ansatz ist, dass Sie einen völlig neuen Prozess-Stack, indem auf Speicher einen erheblichen Aufwand hat. ( http://en.wikipedia.org/wiki/Thread_(computing)#How_threads_differ_from_processes )

Python Multiprocessing-Modul: http://docs.python.org/dev/library/multiprocessing.html

"Der Grund, warum ich nicht das Multiprocessing-Modul bin ist, dass (in diesem Fall) Teil des Programms stark vernetzt ist I / O Bindung (HTTP-Requests) so einen Pool von Arbeitsthreads ist eine großartige Art und Weise zu Squeeze Leistung aus einer Box ... "

Über dieses, ich denke, dass Sie auch einen Pool von Prozess haben: http://docs.python.org/dev/library/multiprocessing.html#using-a-pool-of-workers

Att, Leo

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top