2013-09-28 10 views
11

Die Reihenfolge der Ergebnisse aus dem zurückgegebenen Iterator imap_unordered ist willkürlich, und es scheint nicht schneller zu laufen als imap (die ich mit dem folgenden Code überprüfen), also warum sollte man diese Methode verwenden?In welcher Situation müssen wir `multiprocessing.Pool.imap_unordered` verwenden?

from multiprocessing import Pool 
import time 

def square(i): 
    time.sleep(0.01) 
    return i ** 2 

p = Pool(4) 
nums = range(50) 

start = time.time() 
print 'Using imap' 
for i in p.imap(square, nums): 
    pass 
print 'Time elapsed: %s' % (time.time() - start) 

start = time.time() 
print 'Using imap_unordered' 
for i in p.imap_unordered(square, nums): 
    pass 
print 'Time elapsed: %s' % (time.time() - start) 
+0

In diesem Beispiel unterscheidet sich der Unterschied zwischen der für "0 ** 2" erforderlichen Zeit nicht wesentlich von "49 ** 2". Ich frage mich, was passieren würde, wenn einige Berechnungen viel länger dauern als die anderen. Wird 'imap_unordered' in einem solchen Fall schneller sein? –

+0

@CTZhu Ich denke schon. – satoru

Antwort

21

Mit pool.imap_unordered statt pool.imap keinen großen Effekt auf die Gesamtlaufzeit des Codes haben. Es könnte ein wenig schneller sein, aber nicht zu viel.

Sie können jedoch das Intervall zwischen den in Ihrer Iteration verfügbaren Werten gleichmäßiger machen. Das heißt, wenn Sie Operationen haben, die sehr unterschiedliche Zeiträume benötigen (anstatt der konsistenten 0.01 Sekunden, die Sie in Ihrem Beispiel verwendet haben), kann imap_unordered die Dinge glätten, indem Sie schneller berechnete Werte vor langsameren berechneten Werten liefern. Der reguläre imap verzögert die Rückgabe der schnelleren, bis die langsameren vor ihnen berechnet wurden (aber dies verzögert die Worker-Prozesse nicht zu weiteren Berechnungen, sondern nur zu der Zeit, um sie zu sehen).

Versuchen Sie, Ihre Arbeit Funktion Schlaf für i*0.1 Sekunden, mischen Sie Ihre Eingabeliste und Drucken i in Ihren Schleifen. Sie werden den Unterschied zwischen den beiden imap Versionen sehen können. Hier ist meine Version (die main Funktion und die if __name__ == '__main__' vorformulierten wurde erforderlich, korrekt auf Windows laufen):

from multiprocessing import Pool 
import time 
import random 

def work(i): 
    time.sleep(0.1*i) 
    return i 

def main(): 
    p = Pool(4) 
    nums = range(50) 
    random.shuffle(nums) 

    start = time.time() 
    print 'Using imap' 
    for i in p.imap(work, nums): 
     print i 
    print 'Time elapsed: %s' % (time.time() - start) 

    start = time.time() 
    print 'Using imap_unordered' 
    for i in p.imap_unordered(work, nums): 
     print i 
    print 'Time elapsed: %s' % (time.time() - start) 

if __name__ == "__main__": 
    main() 

Die imap Version lange Pausen, während Werte wie 49 gehandhabt werden (unter 4,9 Sekunden) haben wird, dann wird über eine Reihe anderer Werte fliegen (die von den anderen Prozessen berechnet wurden, während wir auf 49 zur Verarbeitung warteten). Im Gegensatz dazu wird die imap_unordered-Schleife in der Regel nicht fast gleichzeitig so lange pausieren. Es wird häufiger, aber kürzere Pausen haben, und seine Ausgabe wird tendenziell glatter sein.

+0

jup, so ist es ideal für z.B. Anzeige einer Fortschrittsleiste für abgeschlossene Aufgaben –

3

imap_unordered scheint auch weniger Speicher im Laufe der Zeit als imap zu verwenden. Zumindest habe ich das mit einem Iterator über Millionen von Dingen erlebt.

+0

Das wäre, weil es nicht so viele Elemente festhalten muss, die vor der Verwendung fertig waren. –

Verwandte Themen