1029 Stimmen

Mehrfachverarbeitung gegen Gewindeschneiden Python

Ich versuche, die Vorteile von [multiprocessing](http://docs. python.org/library/multiprocessing) gegenüber threading zu verstehen. Ich weiß, dass multiprocessing das Global Interpreter Lock umgeht, aber welche anderen Vorteile gibt es noch und kann threading nicht dasselbe tun?

9 Stimmen

Ich denke, das könnte im Allgemeinen nützlich sein: blogs.datalogics.com/2013/09/25/… Obwohl je nach Sprache interessante Dinge passieren können. Zum Beispiel sind laut Andrew Sledges Link die Python-Threads langsamer. Bei Java ist es genau umgekehrt, Java-Prozesse sind viel langsamer als Threads, weil für einen neuen Prozess eine neue JVM benötigt wird.

7 Stimmen

Keine der beiden Top-Antworten (aktuelle Top, zweite Antwort) behandelt das GIL in irgendeiner signifikanten Weise. Hier ist eine Antwort, die das GIL-Aspekt behandelt: stackoverflow.com/a/18114882/52074

0 Stimmen

@AndrasDeak können wir das umgekehrt schließen gemäß: meta.stackoverflow.com/questions/251938/…, da diese viel mehr Upvotes/Antworten hat?

41voto

buydadip Punkte 8050

Wie in der Frage erwähnt, ist Multiprocessing in Python der einzige echte Weg, um echte Parallelität zu erreichen. Multithreading kann dies nicht erreichen, weil das GIL verhindert, dass Threads parallel ausgeführt werden.

Als Konsequenz kann das Threading in Python nicht immer nützlich sein und tatsächlich je nachdem, was Sie erreichen möchten, sogar zu einer schlechteren Leistung führen. Wenn Sie beispielsweise eine CPU-gebundene Aufgabe wie das Dekomprimieren von Gzip-Dateien oder 3D-Rendering (alles, was die CPU intensiv belastet) ausführen, kann das Threaden Ihre Leistung tatsächlich behindern, anstatt sie zu verbessern. In einem solchen Fall möchten Sie Multiprocessing verwenden, da nur diese Methode tatsächlich parallel ausgeführt wird und dabei hilft, das Gewicht der anstehenden Aufgabe zu verteilen. Es kann dabei einige Overheads geben, da Multiprocessing das Kopieren des Speichers eines Skripts in jeden Unterprozess beinhaltet, was bei größeren Anwendungen Probleme verursachen kann.

Dennoch wird Multithreading nützlich, wenn Ihre Aufgabe IO-gebunden ist. Wenn zum Beispiel der Großteil Ihrer Aufgabe darauf wartet, auf API-Aufrufe zu warten, würden Sie Multithreading verwenden, denn warum nicht einen weiteren Anforderung in einem anderen Thread starten, während Sie warten, anstatt dass Ihre CPU einfach untätig herumsitzt.

TL;DR

  • Multithreading ist nebenläufig und wird für IO-gebundene Aufgaben verwendet
  • Multiprocessing erreicht echte Parallelität und wird für CPU-gebundene Aufgaben verwendet

2 Stimmen

Könnten Sie ein Beispiel für eine Aufgabe nennen, die IO-gebunden ist?

8 Stimmen

@YellowPillow Angenommen, Sie machen mehrere API-Aufrufe, um Daten anzufordern. In diesem Fall wird die meiste Zeit damit verbracht, auf das Netzwerk zu warten. Während es auf dieses Netzwerk I/O wartet, kann der GIL freigegeben werden, um vom nächsten Task verwendet zu werden. Allerdings muss der Task den GIL wieder erwerben, um den Rest des mit jedem API-Aufruf verbundenen Python-Codes auszuführen. Da der Task jedoch auf das Netzwerk wartet, muss er nicht am GIL festhalten.

29voto

chrisg Punkte 38343

Ein weiterer nicht erwähnter Punkt ist, dass es davon abhängt, welches Betriebssystem Sie verwenden, wenn es um Geschwindigkeit geht. In Windows sind Prozesse teuer, daher wären Threads in Windows besser. Doch in Unix sind Prozesse schneller als ihre Windows-Varianten, daher ist die Verwendung von Prozessen in Unix sicherer und schneller zu starten.

8 Stimmen

Hast du konkrete Zahlen, die das belegen? Z.B. Vergleiche zwischen der Durchführung einer Aufgabe seriell, dann auf mehreren Threads, dann auf mehreren Prozessen, sowohl unter Windows als auch unter Unix?

3 Stimmen

Stimmen Sie der Frage von @ArtOfWarfare zu. Zahlen? Empfehlen Sie die Verwendung von Threads für Windows?

0 Stimmen

Das Betriebssystem spielt keine große Rolle, da der Python GIL es nicht erlaubt, mehrere Threads in einem einzelnen Prozess auszuführen. Multiprocessing wird in Windows und Linux schneller sein.

23voto

Chitransh Gaurav Punkte 456

Andere Antworten haben sich mehr auf den Aspekt Multithreading vs. Multiprocessing konzentriert, aber in Python muss der Global Interpreter Lock (GIL) berücksichtigt werden. Wenn eine größere Anzahl (sagen wir k) von Threads erstellt werden, wird die Leistung im Allgemeinen nicht um das k-fache steigen, da die Anwendung immer noch als Single-Thread-Anwendung läuft. Das GIL ist ein globaler Lock, der alles sperrt und nur die Ausführung eines einzigen Threads zulässt und dabei nur einen einzigen Kern verwendet. Die Leistung steigt an Stellen, an denen C-Erweiterungen wie numpy, Network, I/O verwendet werden, wo viele Hintergrundarbeiten erledigt werden und das GIL freigegeben wird.

Bei der Verwendung von Threading gibt es nur einen einzigen Betriebssystem-Level-Thread, während Python Pseudo-Threads erstellt, die vollständig von Threading selbst verwaltet werden, aber im Wesentlichen als einzelner Prozess ausgeführt werden. Präemption findet zwischen diesen Pseudo-Threads statt. Wenn die CPU mit maximaler Kapazität läuft, möchten Sie möglicherweise auf Multiprocessing umsteigen.

Im Falle von eigenständigen Ausführungsinstanzen können Sie stattdessen Pool verwenden. Aber im Falle von sich überschneidenden Daten, bei denen Prozesse kommunizieren sollen, sollten Sie multiprocessing.Process verwenden.

0 Stimmen

"So wenn Threading verwendet wird, gibt es nur einen einzigen Betriebssystem-Level-Thread, während Python Pseudo-Threads erstellt, die vollständig von Threading selbst verwaltet werden, aber im Wesentlichen als ein einzelner Prozess laufen." Das stimmt nicht. Python-Threads sind echte OS-Threads. Was du beschreibst, sind Green Threads. Python verwendet das nicht. Es ist nur so, dass ein Thread den GIL halten muss, um Python-Bytecode auszuführen, was die Thread-Ausführung sequenziell macht.

0 Stimmen

Jetzt im Falle von eigenständigen Ausführungsfällen können Sie stattdessen Pool wählen. Aber im Falle von sich überschneidenden Daten, bei denen Sie Prozesse kommunizieren möchten, sollten Sie multiprocessing.Process verwenden. Welcher Pool? Die multiprocessing-Bibliothek hat einen Pool, also macht dies nicht viel Sinn.

16voto

Jeril Punkte 6583

MultiProcessing

  • Multiprocessing fügt CPUs hinzu, um die Rechenleistung zu erhöhen.
  • Mehrere Prozesse werden gleichzeitig ausgeführt.
  • Die Erstellung eines Prozesses ist zeitaufwendig und ressourcenintensiv.
  • Multiprocessing kann symmetrisch oder asymmetrisch sein.
  • Die Multiprocessing-Bibliothek in Python verwendet separaten Speicherplatz, mehrere CPU-Kerne, umgeht die GIL-Beschränkungen in CPython, child Prozesse sind killbar (z. B. Funktionsaufrufe im Programm) und ist viel einfacher zu verwenden.
  • Einige Fallstricke des Moduls sind ein größeres Speicher-Footprint und IPCs ein wenig komplizierter mit mehr Overhead.

Multithreading

  • Multithreading erstellt mehrere Threads eines einzigen Prozesses, um die Rechenleistung zu erhöhen.
  • Mehrere Threads eines einzigen Prozesses werden gleichzeitig ausgeführt.
  • Die Erstellung eines Threads ist sowohl zeit- als auch ressourcenschonend.
  • Die Multithreading-Bibliothek ist schlank, teilt den Speicher, ist verantwortlich für reaktives UI und wird gut für an I/O gebundene Anwendungen genutzt.
  • Das Modul ist nicht killbar und unterliegt der GIL.
  • Mehrere Threads leben im selben Prozess im selben Bereich, jeder Thread wird eine spezifische Aufgabe erledigen, hat seinen eigenen Code, eigenen Stack-Speicher, Befehlszeiger und teilt den Heap-Speicher.
  • Wenn ein Thread ein Speicherleck hat, kann er die anderen Threads und den übergeordneten Prozess beschädigen.

Beispiel für Multi-Thread und Multi-Processing mit Python

Python 3 hat die Möglichkeit, parallele Aufgaben zu starten. Das erleichtert unsere Arbeit.

Es hat für Thread-Pooling und Process-Pooling.

Das Folgende gibt einen Einblick:

ThreadPoolExecutor Beispiel

import concurrent.futures
import urllib.request

URLS = ['http://www.foxnews.com/',
        'http://www.cnn.com/',
        'http://europe.wsj.com/',
        'http://www.bbc.co.uk/',
        'http://some-made-up-domain.com/']

# Eine einzelne Seite abrufen und die URL sowie den Inhalt melden
def load_url(url, timeout):
    with urllib.request.urlopen(url, timeout=timeout) as conn:
        return conn.read()

# Wir können ein with-Statement verwenden, um sicherzustellen, dass Threads schnell aufgeräumt werden
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
    # Starten Sie die Ladevorgänge und markieren Sie jeden Future mit seiner URL
    future_to_url = {executor.submit(load_url, url, 60): url for url in URLS}
    for future in concurrent.futures.as_completed(future_to_url):
        url = future_to_url[future]
        try:
            data = future.result()
        except Exception as exc:
            print('%r hat eine Ausnahme erzeugt: %s' % (url, exc))
        else:
            print('%r Seite hat %d Bytes' % (url, len(data)))

ProcessPoolExecutor Beispiel

import concurrent.futures
import math

PRIMES = [
    112272535095293,
    112582705942171,
    112272535095293,
    115280095190773,
    115797848077099,
    1099726899285419]

def is_prime(n):
    if n % 2 == 0:
        return False

    sqrt_n = int(math.floor(math.sqrt(n)))
    for i in range(3, sqrt_n + 1, 2):
        if n % i == 0:
            return False
    return True

def main():
    with concurrent.futures.ProcessPoolExecutor() as executor:
        for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)):
            print('%d ist eine Primzahl: %s' % (number, prime))

if __name__ == '__main__':
    main()

0 Stimmen

Es wäre besser gewesen, wenn Sie sowohl ThreadPoolExecutor als auch ProcessPoolExecutor am selben Beispiel gezeigt hätten.

0 Stimmen

Wie die Multiplikation von riesigen Matrizen

1 Stimmen

@Chandan, du kannst das gleiche Beispiel von ProcessPoolExecutor verwenden und with concurrent.futures.ProcessPoolExecutor() as executor: zu with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: ändern.

11voto

Threads teilen den gleichen Speicherbereich, um sicherzustellen, dass zwei Threads nicht denselben Speicherplatz teilen. Daher müssen besondere Vorsichtsmaßnahmen getroffen werden. Der CPython-Interpreter behandelt dies mithilfe eines Mechanismus namens GIL oder des Global Interpreter Lock.

Was ist GIL (Ich möchte nur klarstellen, dass GIL oben wiederholt wird)?

Im CPython-Interpreter ist der globale Interpreter-Lock, oder GIL, ein Mutex, der den Zugriff auf Python-Objekte schützt und verhindert, dass mehrere Threads gleichzeitig Python-Bytecodes ausführen. Dieser Lock ist hauptsächlich erforderlich, weil das Speichermanagement von CPython nicht threadsicher ist.

Für die Hauptfrage können wir Anwendungsfälle vergleichen, wie?

1-Anwendungsfälle für Threadverarbeitung: Bei GUI-Programmen kann die Threadverarbeitung verwendet werden, um die Anwendung ansprechend zu machen. Zum Beispiel kann in einem Textbearbeitungsprogramm ein Thread für die Aufzeichnung der Benutzereingaben zuständig sein, ein anderer für die Anzeige des Textes und ein Dritter für die Rechtschreibprüfung. Hier muss das Programm auf die Benutzerinteraktion warten, was der größte Engpass ist. Ein weiterer Anwendungsfall für die Threadverarbeitung sind Programme, die IO- oder netzwerkbasiert sind, wie Web-Scraper.

2-Anwendungsfälle für die Multiprozessverarbeitung: Die Multiprozessverarbeitung übertrifft die Threadverarbeitung in Fällen, in denen das Programm rechenintensiv ist und keine IO- oder Benutzerinteraktion durchführen muss.

Für weitere Details besuchen Sie diesen Link und Link oder benötigen Sie eingehende Kenntnisse zur Threadverarbeitung besuchen Sie hier für die Multiprozessverarbeitung besuchen Sie hier

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X