Python(无界)生成器作为子进程.并行化



嗨,我通过创建一个生成器函数解决了我的问题,该函数按递增顺序生成具有特殊属性的连续整数。

为我的程序假设这种模板:

from itertools import islice, count
def special_gen(d):
for n in count(1):
if is_special(d, n):
yield n
if __name__ == '__main__':
first= 10
for d in range(5):
print(f"The first {first} special({d}) numbers are:",
list(islice(special_gen(d), first)))

生成连续项可能需要很长时间,因此我正在研究使用子流程来加快速度。

我认为以下方案是拆分计算的开始 - 它使用四个单独的生成器并合并它们的输出,以便结果按顺序排列,但是,我陷入了如何最好地添加多处理以便每个生成器都在单独的进程中。

PROCESSES = 4
def special_gen_mod(d, mod=1, offset=0):
for n in count(1 + offset, mod):
if is_special(d, n):
yield n
def special_gen(d):
sub_generators = [special_gen_mod(d, PROCESSES, off)
for off in range(PROCESSES)]
yield from heapq.merge(*sub_generators)

请假设时间is_special(d, n} 与 log(n( 和 exp(d( 成正比

您的帮助将不胜感激,谢谢。(首选标准库解决方案(。

额外的实际任务是在罗塞塔代码上生成超级 d 数字,我有一个单任务解决方案,在 d=9 的情况下挣扎。

您可以在生成器中使用multiprocessing,就像在代码的任何其他部分中使用它一样。您还可以将其与yield from结合使用,并获得一个相当优雅的解决方案。

def superd(d, N=5000):
# N is the number of digits to pre-compute in each cycle
with Pool(cpu_count() - 2) as workers:
for offset in count(0, N):
worker_fn_args = zip(range(offset, offset + N), [d] * N)
is_superd_batch = workers.starmap(is_special, worker_fn_args)
yield from [n+offset for n in range(N) if is_superd_batch[n]]

超级 d 示例的完整代码变为:

from multiprocessing import Pool, cpu_count
from itertools import islice, count

def is_special(n, d):
tofind = str(d) * d
return tofind in str(d * n ** d)

def superd(d, N=5000):
if d != int(d) or not 2 <= d <= 9:
raise ValueError("argument must be integer from 2 to 9 inclusive")
with Pool(cpu_count() - 2) as workers:
for offset in count(0, N):
worker_fn_args = zip(range(offset, offset + N), [d] * N)
is_superd_batch = workers.starmap(is_special, worker_fn_args)
yield from [n+offset for n in range(N) if is_superd_batch[n]]

if __name__ == '__main__':
for d in range(2, 10):
print(f"{d}:", ', '.join(str(n) for n in islice(superd(d), 10)))

并生成:

2: 19, 31, 69, 81, 105, 106, 107, 119, 127, 131
3: 261, 462, 471, 481, 558, 753, 1036, 1046, 1471, 1645
4: 1168, 4972, 7423, 7752, 8431, 10267, 11317, 11487, 11549, 11680
5: 4602, 5517, 7539, 12955, 14555, 20137, 20379, 26629, 32767, 35689
6: 27257, 272570, 302693, 323576, 364509, 502785, 513675, 537771, 676657, 678146
7: 140997, 490996, 1184321, 1259609, 1409970, 1783166, 1886654, 1977538, 2457756, 2714763
8: 185423, 641519, 1551728, 1854230, 6415190, 12043464, 12147605, 15517280, 16561735, 18542300
9: 17546133, 32613656, 93568867, 107225764, 109255734, 113315082, 121251742, 175461330, 180917907, 182557181

我的机器(英特尔至强 E3-1230 @3.3GHz(上的运行时(明显(比我输入此答案所花费的时间要短。

相关内容

  • 没有找到相关文章

最新更新