2012-12-30 12 views
6

Ich habe Permutationen mit der Funktion itertools.permutations in Python generiert. Das Problem ist, dass das Ergebnis ist sehr groß und ich würde durch sie mit mehreren Threads gehen mögen, aber nicht wirklich wissen, wie das hier zu tun ist, was habe ich bisher:Python Permutationen Threads

perms = itertools.permutations('1234', r=4) 

#I would like to iterate through 'perms' with multiple threads 
for perm in perms: 
    print perm 
+0

Wie möchten Sie die Daten zwischen Threads teilen? Warum willst du mehrere Threads verwenden? –

+0

Ich möchte es gleichmäßig aufteilen: wenn 'perms' 1'000'000 Einträge enthält und ich 4 Threads habe, sollte jeder Thread 250'000 Einträge verarbeiten; Wenn ich nur einen Thread verwende, dauert es etwa 10 Minuten, um die gesamten Einträge zu durchlaufen. Deshalb würde ich gerne mehr als einen Thread verwenden. – wasp256

+0

was genau ist Ihr Prozess, IO gebunden oder CPU gebunden? –

Antwort

4

Wenn die Arbeit, die Sie mit den Elementen aus dem Permutationsgenerator ausführen möchten, CPU-intensiv ist, möchten Sie wahrscheinlich Prozesse statt Threads verwenden. CPythons Global Interpreter Lock (GIL) macht Multithreading von begrenztem Wert, wenn CPU-gebundene Arbeit ausgeführt wird.

Verwenden Sie stattdessen die Pool Klasse multiprocessing Modul, etwa so:

import multiprocessing 
import itertools 

def do_stuff(perm): 
    # whatever 
    return list(reversed(perm)) 

if __name__ == "__main__": 
    with multiprocessing.Pool() as pool: # default is optimal number of processes 
     results = pool.map(do_stuff, itertools.permutations('1234', r=4)) 

     # do stuff with results 

Beachten Sie, dass, wenn Sie über results iteriert wird (anstatt mit ihm als Liste, etwas zu tun), können Sie imap anstelle von map, um einen Iterator zu erhalten, mit dem Sie die Ergebnisse bearbeiten können, da sie von den Arbeitsprozessen erzeugt werden. Wenn es egal ist, in welcher Reihenfolge die Elemente zurückgegeben werden, können Sie imap_unordered verwenden, um (ich denke) ein wenig Speicher zu sparen.

Die Voreinstellung if __name__ is "__main__" ist für Windows erforderlich, wobei das Modul multiprocessing die Einschränkungen des Betriebssystems umgehen muss (keine fork).

0

Pythons futures Modul macht es einfach zu teilen Arbeit zwischen Threads. In diesem Beispiel werden 4 Threads verwendet, Sie können sie jedoch an Ihre Bedürfnisse anpassen.

from concurrent import futures 

def thread_process(perm): 
    #do something 

with futures.ThreadPoolExecutor(max_workers=4) as executor: 
    for perm in perms: 
     executor.submit(thread_process, perm) 
+0

Das Problem bei der Verwendung von Threading ist, dass es nicht das tut, was das OP will, da die GIL es nicht parallel ausführt –

+0

Ich sehe nicht wo Er sagt, was er meint, indem er "mehrere Threads durchläuft" - er könnte alles tun, von der Ausführung eines anderen Prozesses bis hin zu Socket/File-Aufrufen, die Threads blockieren. In diesen Szenarien wird die GIL kein Problem verursachen. Ich stimme zu, dass es sicherlich davon abhängt, was er tun möchte. –

1

Ihre Verarbeitungsfunktion Unter der Annahme, ist f (x) wollen Sie

from multiprocessing import Pool 

def f(x): 
    return x*x 

if __name__ == '__main__': 
    pool = Pool(processes=4) # start 4 worker processes 
    perms = itertools.permutations('1234', r=4) 
    for r in pool.map(f, perms): 
     print (r) 

In der Tat tun, Threads würden die Prozesse parallel nicht ausgeführt werden, es sei denn, es ist IO gebunden. Wenn es CPU-gebunden ist und Sie einen Quad-Core haben, dann ist es der richtige Weg. Wenn Sie kein Multicore haben und es CPU-gebunden ist, dann befürchte ich, dass es Ihre derzeitige Situation nicht verbessert, wenn Sie es parallel machen.

1

Split das Index der Anzahl von Dauerwellen zwischen Threads this function dann verwenden, um die perm aus dem Index nicht in jedem Thread zu erzeugen, als alle perms zu erzeugen und sie zwischen Threads aufzuteilen.