Wie kann die Leistung in Python maximiert werden, wenn viele I / O-Operationen ausgeführt werden?

8

Ich habe eine Situation, in der ich viele Dateien herunterlade. Im Moment läuft alles auf einem Haupt-Python-Thread und lädt alle paar Minuten bis zu 3000 Dateien herunter. Das Problem ist, dass die dafür benötigte Zeit zu lang ist. Ich weiß, dass Python kein echtes Multithreading hat, aber gibt es dafür einen besseren Weg? Ich dachte daran, mehrere Threads zu starten, da die I / O-gebundenen Operationen keinen Zugriff auf die globale Interpreter-Sperre erfordern sollten, aber vielleicht verstehe ich dieses Konzept falsch.

    
Rhubarb 04.06.2010, 03:46
quelle

4 Antworten

5

Könnte immer einen Blick auf multiprocessing werfen.

    
Amber 04.06.2010, 03:51
quelle
15

Multithreading ist für den speziellen Zweck, E / A im Netz zu beschleunigen, einfach in Ordnung (obwohl asynchrone Programmierung eine noch größere Leistung bringen würde). CPythons Multithreading ist ziemlich "wahr" (native OS-Threads) - woran Sie wahrscheinlich denken, ist die GIL, die globale Interpreter-Sperre, die verschiedene Threads daran hindert, Python-Code gleichzeitig auszuführen. Aber alle I / O-Primitive geben die GIL auf, während sie darauf warten, dass Systemaufrufe abgeschlossen werden, sodass die GIL für die I / O-Leistung nicht relevant ist !

Bei der asynchronen Programmierung ist das mächtigste Framework verdreht , aber es kann eine Weile dauern, bis Sie den Dreh raus haben Diese Programmierung wurde nie gemacht. Es wäre wahrscheinlich einfacher für Sie, zusätzliche E / A-Leistung durch die Verwendung eines Threads-Pools zu erhalten.

    
Alex Martelli 04.06.2010 04:08
quelle
3
  

Gibt es einen besseren Weg, dies zu tun?

Ja

  

Ich dachte daran, mehrere Threads seit den E / A-gebundenen Operationen zu starten

Nicht.

Auf Betriebssystemebene teilen alle Threads in einem Prozess eine begrenzte Anzahl von E / A-Ressourcen.

Wenn du echte Geschwindigkeit willst, spawne so viele schwere OS-Prozesse, wie es deine Plattform toleriert. Das Betriebssystem ist wirklich sehr gut darin, E / A-Workloads zwischen Prozessen auszubalancieren. Lass das Betriebssystem das aussortieren.

Die Leute werden sagen, dass das Hervorbringen von 3000 Prozessen schlecht ist, und sie haben Recht. Sie wollen wahrscheinlich nur ein paar hundert auf einmal spawnen.

Was Sie wirklich wollen, ist Folgendes.

  1. Eine gemeinsame Nachrichtenwarteschlange, in der die 3000 URIs in der Warteschlange stehen.

  2. Ein paar hundert Arbeiter, die alle aus der Warteschlange lesen.

    Jeder Worker ruft einen URI aus der Warteschlange ab und ruft die Datei ab.

Die Arbeiter können weiterlaufen. Wenn die Warteschlange leer ist, sitzen sie einfach nur da und warten auf Arbeit.

"alle paar Minuten" deponieren Sie die 3000 URIs in die Warteschlange, damit die Arbeiter anfangen zu arbeiten.

Dies wird jede Ressource auf Ihrem Prozessor binden, und es ist ziemlich trivial. Jeder Arbeiter ist nur ein paar Zeilen Code. Das Laden der Warteschlange ist ein spezieller "Manager", der nur ein paar Zeilen Code enthält.

    
S.Lott 04.06.2010 15:02
quelle
0

Gevent ist dafür perfekt.

Gevents Verwendung von Greenlets (Lightweight-Coroutinen im selben Python-Prozess) bietet Ihnen asynchrone Vorgänge , ohne die Lesbarkeit des Codes zu beeinträchtigen oder die Einführung abstrakter "Reaktor" -Konzepte in Ihren Mix.

    
Archie1986 05.08.2011 16:10
quelle

Tags und Links