Python 为什么池比相同数量的进程慢

Python 为什么池比相同数量的进程慢,python,multiprocessing,python-multiprocessing,Python,Multiprocessing,Python Multiprocessing,我最近尝试将一些并行进程重构到一个池中,并惊讶地发现该池所用的时间几乎是纯进程的两倍。请假设它们运行在同一台机器上,具有相同数量的内核。我希望有人能解释为什么我使用Pool的实现需要更长的时间,并提供一些建议: 共享依赖项: 下面是使用过程的更快实现。[UPDATE]经过重构以控制与池实现相同的活动进程数,速度更快: processes = [] pipes = [] def _get_partition(send_end): send_end.send(best_partition

我最近尝试将一些并行进程重构到一个池中,并惊讶地发现该池所用的时间几乎是纯进程的两倍。请假设它们运行在同一台机器上,具有相同数量的内核。我希望有人能解释为什么我使用Pool的实现需要更长的时间,并提供一些建议:

共享依赖项:

下面是使用
过程
的更快实现。[UPDATE]经过重构以控制与池实现相同的活动进程数,速度更快:

processes = []
pipes = []

def _get_partition(send_end):
    send_end.send(best_partition(a_graph, resolution=res, randomize=rand))

for idx in range(iterations):
    recv_end, send_end = Pipe(False)
    p = Process(target=_get_partition, args=(send_end,))
    processes.append(p)
    pipes.append(recv_end)

running_procs = []
finished_procs = []
while len(finished_procs) < iterations:
    while len(running_procs) < n_cores and len(processes):
        proc = processes.pop()
        proc.start()
        running_procs.append(proc)

    for idx, proc in enumerate(running_procs):
        if not proc.is_alive():
            finished_procs.append(running_procs.pop(idx))

for p in finished_procs:
    p.join()

partitions = [pipe.recv() for pipe in pipes]

通常,当一个池和一堆进程之间存在差异时(这两个进程都有好处),定义结果的是您的数据集和执行的任务

在不知道你的
a_图是什么的情况下,我胡乱猜测它是个大东西。在您的流程模型中,您依赖于子流程中该文件的内存中副本。在池模型中,每次调用一个worker时,您都会将一个
图的副本作为参数传输给每个worker。这实际上是作为队列实现的。在您的流程模型中,当Python解释器调用
fork()
时,您的子流程将在C级获得该文件的副本。这比通过队列传输大型Python对象、字典、数组或其他任何东西要快得多

如果任务只需要很短的时间就可以完成,则情况正好相反。在这种情况下,池是性能更好的解决方案,因为池将任务传递给已经运行的进程。流程不需要在每个任务完成后重新创建。在这种情况下,创建大量只运行几分之一秒的新流程所需的开销会降低流程的实现速度


正如我所说的,这纯粹是推测,但在您的示例中,您实际将什么作为参数传递给您的工作人员,这可能就是解释

在第一个示例中,您正在创建更多的进程。感谢您回复Shadow,我在同一台计算机上运行这些进程,并且池使用了该计算机必须提供的最大内核数。您的时间度量中具体包括哪些内容?这两种情况下的整个代码片段或其中的一部分都无关紧要。试着增加你在池中创建的进程的数量-你会明白我的意思。另外,我们讨论的是多重处理,对吗?您已经将其标记为多线程,在Python中处理方式不同。感谢您的解释,这很有意义。
processes = []
pipes = []

def _get_partition(send_end):
    send_end.send(best_partition(a_graph, resolution=res, randomize=rand))

for idx in range(iterations):
    recv_end, send_end = Pipe(False)
    p = Process(target=_get_partition, args=(send_end,))
    processes.append(p)
    pipes.append(recv_end)

running_procs = []
finished_procs = []
while len(finished_procs) < iterations:
    while len(running_procs) < n_cores and len(processes):
        proc = processes.pop()
        proc.start()
        running_procs.append(proc)

    for idx, proc in enumerate(running_procs):
        if not proc.is_alive():
            finished_procs.append(running_procs.pop(idx))

for p in finished_procs:
    p.join()

partitions = [pipe.recv() for pipe in pipes]
pool = Pool(processes=n_cores)
results = [
    pool.apply_async(
        best_partition,
        (a_graph,),
        dict(resolution=res, randomize=rand)
    ) for i in range(iterations)
]
partitions = [res.get() for res in results]
pool.close()
pool.join()