考虑以下脚本,我测试了使用
itertools.tee
得到的生成器进行计算的两种方法:#!/usr/bin/env python3
from sys import argv
from itertools import tee
from multiprocessing import Process
def my_generator():
for i in range(5):
print(i)
yield i
def double(x):
return 2 * x
def compute_double_sum(iterable):
s = sum(map(double, iterable))
print(s)
def square(x):
return x * x
def compute_square_sum(iterable):
s = sum(map(square, iterable))
print(s)
g1, g2 = tee(my_generator(), 2)
try:
processing_type = argv[1]
except IndexError:
processing_type = "no_multi"
if processing_type == "multi":
p1 = Process(target=compute_double_sum, args=(g1,))
p2 = Process(target=compute_square_sum, args=(g2,))
print("p1 starts")
p1.start()
print("p2 starts")
p2.start()
p1.join()
print("p1 finished")
p2.join()
print("p2 finished")
else:
compute_double_sum(g1)
compute_square_sum(g2)
当我以“正常”模式运行脚本时,这是我得到的结果:
$ ./test_tee.py
0
1
2
3
4
20
30
这里是并行模式:
$ ./test_tee.py multi
p1 starts
p2 starts
0
1
2
3
4
20
0
1
2
3
4
30
p1 finished
p2 finished
初始生成器似乎被“复制”并执行了两次。
我希望避免这种情况,因为在我的实际应用中,这似乎会导致我使用的一个外部库在初始生成器上出现错误 (https://github.com/pysam-developers/pysam/issues/397),同时仍能够在相同生成的值上进行并行计算。
有没有办法实现我想要的效果?
multiprocessing
时会复制整个进程,所以每个进程都有自己的迭代器副本。至少在Linux / Unix上是这样。在Windows上,会崩溃,因为multiprocessing
不使用forking。相反,您的代码将崩溃,并显示“TypeError:can't pickle generator objects”。 - PM 2RingPool.imap
吗? - Antti Haapala -- Слава Україні