在 python 中并行迭代单个列表
iterating over a single list in parallel in python
objective是在并行中使用builtin
[=51=对单个iter
进行计算] sum & map
函数 同时 。也许使用(类似于)itertools
而不是经典的 for loops
来分析通过 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)
一样)
n.b。使用 sum & map
且不使用 for loops
,也许使用 itertools
and/or 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
”程序的源代码。
您可以使用 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))
将 工作,但是内置函数 sum
(和 Python 2 中的 map
)没有以这样的方式实现支持并行迭代。您调用的第一个函数将完全使用它的迭代器,然后第二个函数将使用第二个迭代器,然后第三个函数将使用第三个迭代器。由于 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
函数。
objective是在并行中使用builtin
[=51=对单个iter
进行计算] sum & map
函数 同时 。也许使用(类似于)itertools
而不是经典的 for loops
来分析通过 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)
一样)
n.b。使用 sum & map
且不使用 for loops
,也许使用 itertools
and/or 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
”程序的源代码。
您可以使用 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))
将 工作,但是内置函数 sum
(和 Python 2 中的 map
)没有以这样的方式实现支持并行迭代。您调用的第一个函数将完全使用它的迭代器,然后第二个函数将使用第二个迭代器,然后第三个函数将使用第三个迭代器。由于 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
函数。