Ich habe ein Programm in Python geschrieben, die 4 Eingabe Textdateien liest und schreibt sie alle in eine Liste mit dem Namen ListOutput
, die einen gemeinsamen Speicher zwischen 4 Prozesse in meinem Programm verwendet (ich verwendete 4 Prozesse so meine Programm läuft schneller!)MultiProcessing langsamer mit mehr Prozessen
Ich habe auch eine gemeinsam genutzte Speichervariable namens processedFiles
, die die Namen der bereits gelesenen Eingabedateien von einem der Prozesse speichert, so dass der aktuelle Prozess sie nicht wieder liest (Ich verwendete Sperre so Prozesse nicht Überprüfen Sie das Vorhandensein einer Datei innerhalb processedFiles
zur gleichen Zeit).
Wenn ich nur einen Prozess verwende, läuft mein Programm schneller (7 Millisekunden) — mein Computer hat 8 Kerne. Warum ist das?
import glob
from multiprocessing import Process, Manager,Lock
import timeit
import os
os.chdir("files")
# Define a function for the Processes
def print_content(ProcessName,processedFiles,ListOutput,lock):
for file in glob.glob("*.txt"):
newfile=0
lock.acquire()
print "\n Current Process:",ProcessName
if file not in processedFiles:
print "\n", file, " not in ", processedFiles," for ",ProcessName
processedFiles.append(file)
newfile=1 #it is a new file
lock.release()
#if it is a new file
if newfile==1:
f = open(file,"r")
lines = f.readlines()
ListOutput.append(lines)
f.close()
#print "%s: %s" % (ProcessName, time.ctime(time.time()))
# Create processes as follows
try:
manager = Manager()
processedFiles = manager.list()
ListOutput = manager.list()
start = timeit.default_timer()
lock=Lock()
p1 = Process(target=print_content, args=("Procees-1",processedFiles,ListOutput,lock))
p2 = Process(target=print_content, args=("Process-2",processedFiles,ListOutput,lock))
p3 = Process(target=print_content, args=("Process-3",processedFiles,ListOutput,lock))
p4 = Process(target=print_content, args=("Process-4",processedFiles,ListOutput,lock))
p1.start()
p2.start()
p3.start()
p4.start()
p1.join()
p2.join()
p3.join()
p4.join()
print "ListOutput",ListOutput
stop = timeit.default_timer()
print stop - start
except:
print "Error: unable to start process"
Bei einer Laufzeit von '7ms' investieren Sie einen beträchtlichen Teil der Zeit, um Prozesse zu starten und zu koordinieren. Sie haben auch viele "versteckte" sequentielle Teile. Denken Sie darüber nach: Sie können Dateien nur sequentiell öffnen, weil sie gesperrt sind, und jede gelesene Zeile muss auch synchronisiert werden, wenn in den gemeinsamen Speicher geschrieben wird - es gibt praktisch keine Verstärkung durch Mehrfachverarbeitung. Darüber hinaus starten Sie Prozesse und leiten Daten zwischen ihnen weiter. All das braucht Zeit. – MisterMiyagi
Zu @ MisterMiyagis ausgezeichneten Kommentaren füge ich hinzu, dass die Datei selten compute-gebunden ist. Der Prozessor verbringt die meiste Zeit damit, auf das io-Subsystem zu warten. Im Allgemeinen gibt es nur einen Vorteil beim Hinzufügen von Prozessoren für Jobs, die sie tatsächlich benötigen. Hier fügt das Hinzufügen von mehr Prozessoren reinen Overhead des Typs hinzu, den MM beschreibt. – Gene
Ein wenig off-topic: Es ist einfacher und besser, 'Lock's als Kontextmanager zu verwenden. Aus der [Dokumentation] (https://docs.python.org/2/library/multiprocessing.html#multiprocessing.Lock): "' Lock' unterstützt das Kontext-Manager-Protokoll und kann daher in 'with'-Anweisungen verwendet werden. " Fügen Sie dazu einfach eine Anweisung 'with lock:' vor jeder Gruppe von Anweisungen hinzu, die exklusiven Zugriff auf etwas erfordern. – martineau