NLP | Параллельная обработка списков с помощью execnet

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

В приведенном ниже коде целые числа просто удваиваются, поэтому можно выполнить любое чистое вычисление. Это модуль, который должен выполняться execnet. Он получает 2 кортежа (i, arg), предполагает, что arg — это число, и отправляет обратно (i, arg * 2).

Код:

if __ name__ = = `__channelexec__` :

для (i, arg) в канале :

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

Для использования этот модуль для дублирования каждого элемента в списке, импортируйте модуль plists и вызовите plists .map() wi th модуль remote_double и список целых чисел для удвоения.

Код: использование plist


import plists, remote_double

plists. map (remote_double, range ( 10 ))

Вывод:

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

Карта ( ) определена в plists.py. Он принимает чистый модуль, список аргументов и необязательный список из двух кортежей (spec, count). По умолчанию используются спецификации [(' popen ', 2)], что означает, что пользователь откроет два локальных шлюза и канала. Как только эти каналы открыты, пользователь может поместить их в цикл itertools, который создает бесконечный итератор, который возвращается к началу, как только достигает конца.

Теперь каждый аргумент может быть отправлен в качестве аргументов. в трубу для обработки, а так как каналы цикличны, то каждый канал получает почти равное распределение аргументов. Вот где я появился — порядок, в котором возвращаются результаты, неизвестен, поэтому i в качестве индекса каждого аргумента в списке передается в канал и из него, чтобы пользователь мог комбинировать результаты в исходном порядке. . Затем дождитесь результатов с очередью приема MultiChannel и вставьте их в предварительно заполненный список той же длины, что и исходные аргументы. После получения всех ожидаемых результатов выйдите из шлюзов и верните результаты, как показано в приведенном ниже коде —

Код:


import itertools, execnet

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

шлюзы = []

каналы = []

для спецификация, количество в спецификации:

для i для диапазон (количество):

gw = execnet.makegateway (spec)

gateways.append (gw )

channels.append (gw.remote_exec (mod))


cyc = itertools.cycle (каналы)


for i, arg in enumerate (аргументы):

канал = следующий (cyc )

channel.send ((i, arg))

mch = execnet.MultiChannel (каналы)

очередь = mch.make_receive_queue ()

l = len (args)

# создает список длиной l,

# где каждый элемент равен None

результаты = [ None ] * l

for i in range (l):

канал, (i, результат) = queue.get ()

results [i] = result

для gw в шлюзы:

gw.exit ()

return результаты

Код: улучшите распараллеливание, изменив спецификацию


списки. map (remote_double, range ( 10 ), [( `popen` , 4 )])

Вывод:

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

Однако отсутствие распараллеливания обязательно означает более быструю обработку. Это зависит от доступных ресурсов, и чем больше шлюзов и каналов открыто, тем больше накладных расходов. В идеале должен быть один шлюз и канал на ядро ЦП, чтобы максимизировать использование ресурсов. Используйте plists.map() с любым чистым модулем, если он получает и отправляет обратно 2 кортежа, где i — первый элемент. Этот шаблон наиболее полезен, когда необходимо обработать много чисел, чтобы обработать их как можно быстрее.