NLP | Przetwarzanie list równolegle z execnet

| | | | | | | | | | | | | | | | | | | |

W poniższym kodzie liczby całkowite są po prostu podwojone, można wykonać dowolne czyste obliczenia. To jest moduł do wykonania przez execnet. Otrzymuje 2 krotki (i, arg), zakłada, że arg jest liczbą i odsyła (i, arg * 2).

Kod:

if __ name__ = = `__channelexec__` :

dla (i, arg) w kanał:

channel.send ((i, arg * 2 ))

Aby użyć ten moduł, aby podwoić każdy element na liście, zaimportuj moduł plisty i wywołaj plisty .map () wi th moduł remote_double i lista liczb całkowitych do podwojenia.

Kod: Używanie plist


importuj plisty, remote_double

plisty. map (remote_double, zakres ( 10 ))

Wyjście:

[0, 2, 4, 6, 8, 10, 12, 14, 16, 18] 

Mapa ( ) funkcja jest zdefiniowana w plists.py. Pobiera czysty moduł, listę argumentów i opcjonalną listę dwóch krotek (spec, count). Domyślnie używane są specyfikacje [(' popen ', 2)], co oznacza, że użytkownik otworzy dwie lokalne bramy i kanały. Gdy te potoki są otwarte, użytkownik może umieścić je w pętli itertools, która tworzy nieskończony iterator, który wraca do początku, gdy tylko osiągnie koniec.

Teraz każdy argument może zostać wysłany jako argumenty do potoku do przetworzenia, a ponieważ kanały są cykliczne, każdy kanał otrzymuje prawie równy rozkład argumentów. Właśnie tam wszedłem Ja — kolejność, w jakiej wyniki są zwracane, jest nieznana, więc i , jako indeks każdego argumentu na liście, jest przekazywany do i z kanału, aby użytkownik mógł połączyć wyniki w oryginalnej kolejności . Następnie poczekaj na wyniki z wielokanałową kolejką odbioru i wstaw je do wstępnie wypełnionej listy o tej samej długości co oryginalne argumenty. Po uzyskaniu wszystkich oczekiwanych wyników wyjdź z bram i zwróć wyniki, jak pokazano w poniższym kodzie —

Kod:


import itertools, execnet

def map (mod, args, specs = [( `popen` , 2 )]):

bramy = []

kanały = []

dla specyfikacja, liczba w specyfikacje:

for i w zakres (liczba):

gw = execnet.makegateway (spec)

gateways.append (gw )

channels.append (gw.remote_exec (mod))


cyc = itertools.cycle (kanały)


for i, arg w enumerate (argumenty):

kanał = next (cyc )

channel.send ((i, arg))

mch = execnet.MultiChannel (kanały)

kolejka = mch.make_receive_queue ()

l = len (args)

# tworzy listę o długości l,

# gdzie każdy element jest Brak

wyniki = [ Brak ] * l

for i w zakresie (l):

kanał, (i, wynik) = queue.get ()

wyniki [i] = wynik

for gw in bramy:

gw.exit ()

return wyniki

Kod: zwiększ równoległość, zmieniając specyfikację


plisty. map (remote_double, zakres ( 10 ), [( `popen` , 4 )])

Wyjście:

[0, 2, 4, 6, 8, 10, 12, 14, 16, 18] 

Jednakże więcej równoległości niekoniecznie oznacza szybsze przetwarzanie. Zależy to od dostępnych zasobów, a im więcej otwartych bramek i kanałów, tym większe obciążenie. W idealnym przypadku powinna istnieć jedna brama i kanał na rdzeń procesora, aby zmaksymalizować wykorzystanie zasobów. Użyj plists.map () z dowolnym czystym modułem, o ile odbiera i odsyła 2 krotki, gdzie i jest pierwszym elementem. Ten wzorzec jest najbardziej przydatny, gdy istnieje wiele liczb, które należy przetworzyć, aby przetworzyć je tak szybko, jak to możliwe.