16 Stimmen

Gleichzeitiges Ausführen mehrerer Prozesse

Ich versuche, ein Programm in Python zu erstellen, das gleichzeitig mehrere Instanzen (15) einer Funktion über verschiedene Prozessoren ausführt. Ich habe dazu recherchiert und habe das untenstehende Programm mit dem Process-Tool aus der multiprocessing-Bibliothek erstellt.

Leider führt das Programm jede Instanz der Funktion sequenziell aus (es scheint darauf zu warten, dass eine fertig ist, bevor es zum nächsten Teil der Schleife übergeht).

from __future__ import print_function
from multiprocessing import Process
import sys
import os
import re

for i in range(1,16):
    exec("path%d = 0" % (i))
    exec("file%d = open('%d-path','a', 1)" % (i, i))

def stat(first, last):
    for j in range(1,40000):
        input_string = "water" + str(j) + ".xyz.geocard"
        if os.path.exists('./%s' % input_string) == True:
            exec("out%d = open('output%d', 'a', 1)" % (first, first))
            exec('print("Datei %s wird verarbeitet...", file=out%d)' % (input_string, first))
            with open('./%s' % input_string,'r') as file:
                for line in file:
                    for i in range(first,last):
                        search_string = " " + str(i) + " path:"
                        for result in re.finditer(r'%s' % search_string, line):
                            exec("path%d += 1" % i)

            for i in range(first,last):
                exec("print(path%d, file=file%d)" % (i, i))  

processes = []

for m in range(1,16):
    n = m + 1
    p = Process(target=stat, args=(m, n))
    p.start()
    processes.append(p)

for p in processes:
    p.join()

Ich bin relativ neu im Programmieren und habe keine Erfahrung mit Parallelisierung - jede Hilfe würde sehr geschätzt werden.

Ich habe das gesamte Programm oben eingefügt, wobei "Some Function" durch die tatsächliche Funktion ersetzt wurde, um zu zeigen, dass es sich nicht um ein Timing-Problem handelt. Das Programm kann Tage dauern, um alle 40.000 Dateien (von denen jede ziemlich groß ist) durchzugehen.

28voto

mdadm Punkte 1343

Ich denke, was passiert, ist, dass du in some_function nicht genug machst, um zu beobachten, wie die Arbeit parallel abläuft. Es startet einen Prozess und dieser wird abgeschlossen, bevor der nächste gestartet wird. Wenn du eine zufällige Wartezeit in some_function einbaust, wirst du sehen, dass sie tatsächlich parallel laufen.

from multiprocessing import Process
import random
import time

def some_function(first, last):
    time.sleep(random.randint(1, 3))
    print first, last

processes = []

for m in range(1,16):
   n = m + 1
   p = Process(target=some_function, args=(m, n))
   p.start()
   processes.append(p)

for p in processes:
   p.join()

Ausgabe

2 3
3 4
5 6
12 13
13 14
14 15
15 16
1 2
4 5
6 7
9 10
8 9
7 8
11 12
10 11

3voto

ruscur Punkte 195

Bist du sicher? Ich habe es gerade versucht und es hat bei mir funktioniert; die Ergebnisse werden bei jeder Ausführung durcheinander gebracht, sie werden also parallel ausgeführt.

Schau dir deine Funktion an. Sie nimmt "first" und "last" entgegen, also ist die Ausführungszeit kleiner für kleinere Werte? In diesem Fall könntest du erwarten, dass die kleineren nummerierten Argumente die Laufzeit verkürzen, sodass es so aussieht, als würde es parallel ausgeführt.

ps ux | grep python | grep -v grep | wc -l
> 16

Wenn du den Code wiederholt ausführst (z.B. mit einem Bash-Skript), wirst du sehen, dass jeder Prozess gestartet wird. Wenn du das bestätigen möchtest, importiere os und lass die Funktion os.getpid() ausgeben, damit du sehen kannst, dass sie eine unterschiedliche Prozess-ID haben.

Also ja, überprüfe deine Ergebnisse noch einmal, denn es scheint mir, dass du es richtig parallel geschrieben hast!

1voto

Dieser Code unten kann 10 Prozesse parallel ausgeführt werden, die die Zahlen von 0 bis 99 drucken.

*if __name__ == "__main__": ist erforderlich, um Prozesse unter Windows auszuführen:

from multiprocessing import Process

def test():
    for i in range(0, 100):
        print(i)

if __name__ == "__main__": # Hier
    process_list = []

    for _ in range(0, 10):
        process = Process(target=test)
        process_list.append(process)

    for process in process_list:
        process.start()

    for process in process_list:
        process.join()

Und dieser Code unten ist die Kurzform der for Schleife Version des obigen Codes, der 10 Prozesse parallel ausführt, die die Zahlen von 0 bis 99 drucken:

from multiprocessing import Process

def test():
    [print(i) for i in range(0, 100)]

if __name__ == "__main__":
    process_list = [Process(target=test) for _ in range(0, 10)]

    [process.start() for process in process_list]

    [process.join() for process in process_list]

Das ist das Ergebnis:

...
99
79
67
71
67
89
81
99
80
68
...

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