2015-04-08 2 views
1

Цель состоит в том, чтобы сделать расчеты на одном iter в параллельно использование builtinsum & map функции одновременно. Может быть, с помощью (что-то вроде) itertools вместо классического for loops для анализа (LARGE) данные, прибывающие через iterator ...итерация по одному списку параллельно в питоне

В одном простом примере случае, если я хочу, чтобы вычислить ilen, sum_x & sum_x_sq:

ilen,sum_x,sum_x_sq=iterlen(iter),sum(iter),sum(map(lambda x:x*x, iter)) 

Но без преобразования (большой)iter к list (как с iter=list(iter))

NB Сделайте это с помощью sum & map и без for loops, возможно, используя модули itertools и/или threading?

def example_large_data(n=100000000, mean=0, std_dev=1): 
    for i in range(n): yield random.gauss(mean,std_dev) 

- редактировать -

Будучи очень конкретны: я хороший взгляд на itertools надеясь, что там была двойная функция как map, которые могли бы это сделать. Например: len_x,sum_x,sum_x_sq=itertools.iterfork(iter_x,iterlen,sum,sum_sq)

Если бы я был очень конкретным: я ищу только один ответ, исходный код python для процедуры «iterfork».

+1

Близко связано: http://stackoverflow.com/questions/21945732/consuming-two-iterators-in-parallel – user2357112

+0

В чем важность использования встроенной 'sum' и' map'? Любое решение будет включать в себя либо достаточно накладных расходов во время выполнения, что использование этих встроенных функций оказывает незначительное влияние на производительность, либо достаточно кода расширения C, который переписывает 'sum' и' map' будет тривиальным в сравнении. – user2357112

+0

Согласен: возможно, это может быть сделано только в потоках, но я надеюсь, что нет, и есть какая-то питоническая функция, которую я упустил. Я хорошо смотрел на «itertools», надеясь, что есть двойная функция, такая как «карта», которая может это сделать. Например: 'len_x, sum_x, sum_x_sq = itertools.iterfork (iter_x, count, sum, sum_sq)' ... эта проблема возникла достаточно часто, и мне кажется, что мне нужен шаблон. – NevilleDNZ

ответ

2

Вы можете использовать itertools.tee, чтобы превратить ваш единственный итератор в три итератора, которые вы можете передать вашим трем функциям.

iter0, iter1, iter2 = itertools.tee(input_iter, 3) 
ilen, sum_x, sum_x_sq = count(iter0),sum(iter1),sum(map(lambda x:x*x, iter2)) 

Это будет работы, но встроенная функция summap в Python 2) не реализована таким образом, что поддерживает параллельные итерации. Первая вызванная вами функция полностью поглотит итератор, затем вторая будет потреблять второй итератор, тогда третья функция будет потреблять третий итератор. Поскольку tee должен хранить значения, которые видят один из его выходных итераторов, но не все остальные, это по существу то же самое, что создавать список из итератора и передавать его каждой функции.

Теперь, если вы используете функции генератора, которые потребляют только одно значение от их ввода для каждого выводимого значения, вы можете провести параллельную итерацию, используя zip. В Python 3, map и zip - оба генератора. Вопрос в том, как сделать sum в генератор.

Я думаю, вы можете получить то, что хотите, используя itertools.accumulate (который был добавлен в Python 3.2). Это генератор, который дает текущую сумму своего ввода.Вот как вы могли бы сделать его работу для вашей проблемы (я предполагаю, что ваш count функции должен был быть итератором дружественного вариантом len):

iter0, iter1, iter2 = itertools.tee(input_iter, 3) 

len_gen = itertools.accumulate(map(lambda x: 1, iter0)) 
sum_gen = itertools.accumulate(iter1) 
sum_sq_gen = itertools.accumulate(map(lambda x: x*x, iter2)) 

parallel_gen = zip(len_gen, sum_gen, sum_sq_gen) # zip is a generator in Python 3 

for ilen, sum_x, sum_x_sq in parallel_gen: 
    pass # the generators do all the work, so there's nothing for us to do here 

# ilen_x, sum_x, sum_x_sq have the right values here! 

Если вы используете Python 2, а не 3, вам придется написать свою собственную функцию генератора accumulate (в документах, которые я связал выше) есть чистая реализация Python, и используйте itertools.imap и itertools.izip, а не встроенные функции map и zip.

+0

Это очень хороший намек ... Я дам ему вращение. Thanx – NevilleDNZ