2016-08-01 9 views
0

Ich habe eine Liste von Zeichenfolgen und auf jeden String mache ich einige Änderungen, die Sie in wordify() sehen können. Um dies zu beschleunigen, zerlege ich die Liste in Unterlisten mit chunked() (die Anzahl der Unterlisten ist die Anzahl der CPU-Kerne - 1). Auf diese Weise bekomme ich Listen, die wie [[,,],[,,],[,,],[,,]] aussehen.Multiprocessing mit Karte

Was ich versuche zu erreichen:

ich wordify() auf jedem dieser Teil-Listen gleichzeitig tun will, die Teil-Listen als separate Listen zurück. Ich möchte warten, bis alle Prozesse abgeschlossen sind, und dann diese Unterlisten in einer Liste zusammenführen. Der folgende Ansatz funktioniert nicht.

import multiprocessing 
from multiprocessing import Pool 
from contextlib import closing 

def readFiles(): 
    words = [] 
    with open("somefile.txt") as f: 
     w = f.readlines() 
    words = words + w 
    return words 


def chunked(words, num_cpu): 
    avg = len(words)/float(num_cpu) 
    out = [] 
    last = 0.0  
    while last < len(words): 
     out.append(words[int(last):int(last + avg)]) 
     last += avg  
    return out  


def wordify(chunk,wl): 
    wl.append([chunk[word].split(",", 1)[0] for word in range(len(chunk))]) 
    return wl 


if __name__ == '__main__': 
    num_cpu = multiprocessing.cpu_count() - 1 
    words = readFiles() 
    chunked = chunked(words, num_cpu) 
    wordlist = [] 
    wordify(words, wordlist) # works 
    with closing(Pool(processes = num_cpu)) as p: 
     p.map(wordify, chunked, wordlist) # fails 

Antwort

1

Sie haben Ihren Code schreiben, so dass Sie nur eine einzige Funktion zu map vorbei; es ist nicht schlau genug zu wissen, dass deine Hoffnung wordlist in das zweite Argument deiner Funktion übergeht.

TBH Teilfunktion Anwendung ist ein klobig Bit in Python, aber Sie können verwenden functools.partial:

from functools import partial 
p.map(partial(wordify, wordlist), chunked) 
+0

Erste Lösung gibt mir: 'cPickle.PicklingError: Kann nicht beizen : attribute . Lookup __builtin __ Funktion failed' Zweite Lösung funktioniert, aber es ist langsamer als es zu tun singlethreaded: 'singlethreaded: 0.423000097275',' multithreaded: 0.605999946594' – doc

+0

Sie sollten nicht einen Geschwindigkeitsschub erwarten, wenn die Arbeit getan ist beträchtlich. Eine Zeile durch das erste Komma zu trennen, ist wenig Arbeit, und es ist mit ziemlicher Sicherheit zeitaufwändiger, nur die Strings über Interprozess-Pipes hin und her zu schicken. Es ist nicht wirklich, dass Letzteres besonders teuer ist, es ist eher das, was Sie mit den Saiten tun, ist sehr billig. –

+0

Die Datenmenge, um die es geht, wird erheblich zunehmen. Gibt es eine effizientere Möglichkeit, dies zu tun, da ich absolut keine Notwendigkeit sehe, zwischen den Prozessen Zeichenketten zu senden, während die Unterlisten geändert werden. Nur Material sollte hin- und hergeschickt werden, wenn die Unterlisten erneut hinzugefügt werden. – doc