6 Stimmen

Python Multiprocessing - Ich verstehe es einfach nicht

Ich habe einige Zeit damit verbracht, Multiprocessing zu verstehen, obwohl die Feinheiten sich meinem ungeübten Verstand entziehen. Ich habe es geschafft, einen Pool dazu zu bringen, eine einfache Ganzzahl zurückzugeben, aber wenn die Funktion nicht einfach ein Ergebnis zurückgibt, wie alle Beispiele, die ich finden kann (sogar in der Dokumentation Es handelt sich um ein obskures Beispiel, das ich nicht ganz verstehe.

Hier ist ein Beispiel, das ich gerade versuche, zum Laufen zu bringen. ABER, ich kann es nicht wie vorgesehen zum Laufen bringen, und ich bin sicher, es gibt einen einfachen Grund dafür. Möglicherweise muss ich eine Warteschlange oder einen gemeinsamen Speicher oder einen Manager verwenden, aber so oft ich auch die Dokumentation lese, kann ich mir keinen Reim darauf machen, was das eigentlich bedeutet und was es tut. Alles, was ich bis jetzt verstanden habe, ist die Pool-Funktion.

Außerdem verwende ich eine Klasse, da ich die Verwendung globaler Variablen wie in die Antwort auf diese Frage .

import random

class thisClass:
    def __init__(self):
        self.i = 0

def countSixes(myClassObject):
    newNum = random.randrange(0,10)
    #print(newNum) #this proves the function is being run if enabled
    if newNum == 6:
        myClassObject.i += 1

if __name__ == '__main__':
    import multiprocessing
    pool = multiprocessing.Pool(1) #use one core for now

    counter = thisClass()

    myList = []
    [myList.append(x) for x in range(1000)]

    #it must be (args,) instead of just i, apparently
    async_results = [pool.apply_async(countSixes, (counter,)) for i in myList]

    for x in async_results:
        x.get(timeout=1)

    print(counter.i)

Kann mir jemand erklären, was zu tun ist, damit ich endlich verstehe, was ich übersehe und was es bewirkt?

2 Stimmen

Wenn ich Ihre Frage noch einmal lese, verstehe ich jetzt, dass Sie dachten, die Verwendung einer Klasse würde die dieses Problem . Das wird es nicht. Wenn Sie wirklich Speicher zwischen Prozessen teilen wollen (wovon die Dokumentation selbst abrät!), dann müssen Sie multiprocessing die eingebauten Datentypen wie beschrieben aquí .

12voto

senderle Punkte 135243

Ich habe eine Weile gebraucht, um zu verstehen, was Sie wollen. Das Problem hat mit der Art und Weise zu tun, wie Multiprocessing funktioniert. Im Grunde müssen Sie Ihr Programm in einem funktionalen Stil schreiben, anstatt sich auf Seiteneffekte zu verlassen, wie Sie es jetzt tun.

Im Moment senden Sie Objekte an Ihren Pool, die geändert werden sollen, und erhalten nichts von countSixes . Das funktioniert nicht mit Multiprocessing, denn um das Problem der GIL schafft Multiprocessing ein kopieren.counter und sendet es an eine brandneue Dolmetscherin . Wenn Sie also inkrementieren i inkrementieren Sie tatsächlich eine kopieren.i und dann, weil man nichts zurückgibt, wirft man es weg!

Um etwas Sinnvolles zu tun, müssen Sie etwas von countSixes . Hier ist eine vereinfachte Version Ihres Codes, die etwas Ähnliches tut, wie Sie wollen. Ich habe ein Argument drin gelassen, nur um zu zeigen, was Sie tun sollten, aber eigentlich könnte man das auch mit einer Null-Arg-Funktion machen.

import random

def countSixes(start):
    newNum = random.randrange(0,10)
    if newNum == 6:
        return start + 1
    else:
        return start

if __name__ == '__main__':
    import multiprocessing
    pool = multiprocessing.Pool(1) #use one core for now

    start = 0
    async_results = [pool.apply_async(countSixes, (start,)) for i in range(1000)]

    print(sum(r.get() for r in async_results))

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