我遇到multiprocessing.Pool.apply
的问题。
我的目标是要有5个过程,每个过程用100个元素填充一个数组(此测试为100个),然后将数组合并为长度为500的单个数组。问题是,由于任何原因,最终只能包含400个元素了解。
我尝试过更改池创建的进程数量,但是除了执行时间外,它什么都没有改变。
import torch.multiprocessing as mp
import itertools
pool = mp.Pool(processes=5)
split = int(500/5)
lst = pool.apply(RampedGraph, (split,[])) #each foo returns a list of 100 elements
lst = list(itertools.chain.from_iterable(lst)) #merging the lists into one
len(lst)
>>>400
len(lst)
的预期输出应为500
。
谁能启发我我做错了什么?
EDIT Foo方法说明:
def RampedGraph(popsize, graph_lst):
cyclic_size = int(math.ceil(popsize/2))
acyclic_size = popsize - full_size
append = graph_lst.append
for _ in range(cyclic_size):
t = c.Node().cyclic()
nn = c.number_of_nodes()
c = c.calculate(0, False)
append((t,nn,c))
for _ in range(acyclic_size):
t = c.Node().acyclic()
nn = c.number_of_nodes()
c = c.calculate(0, False)
append((t,nn,c))
return graph_lst
答案 0 :(得分:2)
import torch.multiprocessing as mp
# import multiprocessing as mp
import itertools
def RampedGraph(popsize, graph_lst):
print(mp.current_process().name)
return list(range(100))
num_workers = 5
pool = mp.Pool(processes=num_workers)
split = int(500/num_workers)
lst = pool.starmap(RampedGraph, [(split,[])]*num_workers)
lst = list(itertools.chain.from_iterable(lst))
print(len(lst))
# 500
pool.starmap(RampedGraph, [(split,[])]*5)
发送5个任务到任务池。
它导致RampedGraph(split, [])
同时被调用5次。
RampedGraph
返回的5个结果被收集到列表lst
中。
请注意,同时调用RampedGraph
5次并不能保证使用所有5个处理器。例如,如果RampedGraph
都很快完成,有可能是一个处理器处理多个任务,也许另一个处理器永远也不会被使用的。
然而,如果RampedGraph
需要在一般时间的非平凡的量,则可以期望使用所有5个工作进程。
注意:我使用import multiprocessing as mp
而不是import torch.multiprocessing as mp
运行以上代码。但是,由于torch.multiprocessing
被认为是一个简易替换为multiprocessing
,这不应该有所作为。
使用multiprocessing
附带成本和效益。
当然,好处是可以同时使用多个处理器。
成本包括启动其他流程所需的时间以及进程间通信的成本。 multiprocessing
使用Queues
将参数输送到由工人处理的功能运行,并运送返回值返回到主处理。为了通过队列传输返回的值,对象将通过腌制被序列化为字节。如果通过队列发送的腌制对象很大,则在使用多处理时这会增加可观的开销成本。请注意,所有这些费用并不是由相同代码的等效顺序版本引起的。
尤其是当工作进程运行的功能快速完成时,开销成本可能会占据程序的总运行时间,这使得使用多处理的代码比相同代码的顺序版本慢。
因此,使用多处理时加快速度的关键是尝试最小化进程间的通信并确保工作进程完成大量工作,从而使间接费用在总运行时间中所占的比例很小。