Lesen Sie mehrere Dateien mit multiprocessing
Muss ich Lesen, einige sehr große Textdateien (100+ Mb), verarbeiten alle Zeilen mit regex und speichern die Daten in einer Struktur. Meine Struktur erbt von defaultdict, hat es eine lese - (selbst) - Methode, das Lesen selbst.Dateiname-Datei.
Blick auf diese sehr einfache (aber nicht realen) Beispiel, ich bin nicht mit regex, aber ich bin splitting-Zeilen:
import multiprocessing
from collections import defaultdict
def SingleContainer():
return list()
class Container(defaultdict):
"""
this class store odd line in self["odd"] and even line in self["even"].
It is stupid, but it's only an example. In the real case the class
has additional methods that do computation on readen data.
"""
def __init__(self,file_name):
if type(file_name) != str:
raise AttributeError, "%s is not a string" % file_name
defaultdict.__init__(self,SingleContainer)
self.file_name = file_name
self.readen_lines = 0
def read(self):
f = open(self.file_name)
print "start reading file %s" % self.file_name
for line in f:
self.readen_lines += 1
values = line.split()
key = {0: "even", 1: "odd"}[self.readen_lines %2]
self[key].append(values)
print "readen %d lines from file %s" % (self.readen_lines, self.file_name)
def do(file_name):
container = Container(file_name)
container.read()
return container.items()
if __name__ == "__main__":
file_names = ["r1_200909.log", "r1_200910.log"]
pool = multiprocessing.Pool(len(file_names))
result = pool.map(do,file_names)
pool.close()
pool.join()
print "Finish"
Ich am Ende müssen sich alle Ergebnisse in einem einzigen Container. Es ist wichtig, dass die Reihenfolge der Zeilen beibehalten. Mein Ansatz ist es zu langsam, wenn die Rückgabe-Werte. Bessere Lösung?
Ich bin mit python 2.6 unter Linux
Du musst angemeldet sein, um einen Kommentar abzugeben.
Du bist wahrscheinlich schlagen zwei Probleme.
Einer von Ihnen erwähnt wurde: Sie Lesen mehrere Dateien auf einmal. Diejenigen, die liest am Ende wird, interleaved, verursacht festplattenverschleiß. Sie Lesen möchte ganze Dateien auf einmal, und dann nur den Multi-Thread-Berechnung auf die Daten.
Zweite, Sie schlagen die overhead-Python-multiprocessing-Modul. Es ist nicht wirklich mit threads, sondern starten mehrerer Prozesse und serialisieren der Ergebnisse durch ein Rohr. Das ist sehr langsam für bulk-Daten-in der Tat, es scheint langsamer zu sein als die Arbeit, die Sie tun in den thread (zumindest im Beispiel). Dies ist die real-world-problem, verursacht durch die GIL.
Wenn ich ändern tun (), um die Rückkehr kein statt-container.Elemente() zu deaktivieren, die zusätzliche Daten zu kopieren, in diesem Beispiel ist schneller als ein einzelner thread, solange die Dateien sich bereits im Cache:
Zwei threads: 0.36 verstrichene 168%CPU
Einen thread (pool ersetzen.Landkarte mit Karte): 0:00.52 verstrichene 98%CPU
Leider, das GIL-problem ist fundamental und kann nicht umgangen werden, von innen Python.
Multiprocessing ist mehr geeignet, um die CPU - oder Speicher-orientierte Prozesse, da die seek-Zeit von Rotations-Laufwerke tötet performance beim Wechsel zwischen den Dateien. Legen Sie entweder Ihre log-Dateien in eine schnelle flash-Laufwerk oder eine andere Art von Speicher-Festplatte (physikalisch oder virtuell) oder auf multiprocessing.
Erstellen Sie einen pool mit möglichst vielen Arbeiter-Dateien. Dass vielleicht zu viele. In der Regel, mein Ziel ist es, die Anzahl der Arbeiter um die gleiche wie die Anzahl der Kerne.
Die einfache Tatsache ist, dass der Letzte Schritt wird zu einem einzigen Prozess verschmelzen alle gemeinsam die Ergebnisse. Es ist nicht zu vermeiden, angesichts deiner Beschreibung des Problems. Dies ist bekannt als barrier-Synchronisation: alle Aufgaben müssen auf denselben Punkt erreichen, bevor alle gehen können.
Sollten Sie wahrscheinlich führen Sie das Programm mehrmals, oder in einer Schleife, vorbei an einem unterschiedlichen Wert zu
multiprocessing.Pool()
jedes mal, beginnend bei 1 und die Anzahl der Kerne. Zeit jeder laufen, und sehen, welche Arbeitnehmer zählen, macht am besten.Das Ergebnis wird davon abhängen, wie CPU-intensiv sind (im Gegensatz zu intensiv auf die Festplatte) Ihre Aufgabe ist. Ich wäre nicht überrascht, wenn 2 waren am besten, wenn Ihre Aufgabe ist etwa die Hälfte der CPU und die Hälfte der Festplatte, die selbst auf einer 8-core Maschine.