在Python(Windows)中使用池进行多处理
我必须以一种并行的方式进行研究,以使它运行得更快。我不熟悉python中的多处理库,但还不能使它成功运行。 在这里,我正在调查每一对(来源,目标)是否在我研究的不同框架之间的特定位置。有几点:在Python(Windows)中使用池进行多处理,python,numpy,multiprocessing,pool,Python,Numpy,Multiprocessing,Pool,我必须以一种并行的方式进行研究,以使它运行得更快。我不熟悉python中的多处理库,但还不能使它成功运行。 在这里,我正在调查每一对(来源,目标)是否在我研究的不同框架之间的特定位置。有几点: 这是一个功能,我希望运行得更快(不是几个进程) 随后执行该过程;这意味着将每个帧与前一帧进行比较 此代码是原始代码的一种非常简单的形式。代码输出一个剩余值列表 我正在使用Windows操作系统 有人可以检查代码(多处理部分)并帮助我改进它以使其正常工作吗。谢谢 import numpy as np fro
import numpy as np
from multiprocessing import Pool, freeze_support
def Main_Residence(total_frames, origin_list, target_list):
Previous_List = {}
residence_list = []
for frame in range(total_frames): #Each frame
Current_List = {} #Dict of pair and their residence for frames
for origin in range(origin_list):
for target in range(target_list):
Pair = (origin, target) #Eahc pair
if Pair in Current_List.keys(): #If already considered, continue
continue
else:
if origin == target:
if (Pair in Previous_List.keys()): #If remained from the previous frame, add residence
print "Origin_Target remained: ", Pair
Current_List[Pair] = (Previous_List[Pair] + 1)
else: #If new, add it to the current
Current_List[Pair] = 1
for pair in Previous_List.keys(): #Add those that exited from residence to the list
if pair not in Current_List.keys():
residence_list.append(Previous_List[pair])
Previous_List = Current_List
return residence_list
if __name__ == '__main__':
pool = Pool(processes=5)
Residence_List = pool.apply_async(Main_Residence, args=(20, 50, 50))
print Residence_List.get(timeout=1)
pool.close()
pool.join()
freeze_support()
Residence_List = np.array(Residence_List) * 5
在这里介绍的上下文中,多处理没有意义。 您将创建五个子流程(以及属于池的三个线程,用于管理工作人员、任务和结果),以便一次执行一个函数。所有这些都是以系统资源和执行时间为代价的,而您的四个工作进程根本不做任何事情。多处理不会加快函数的执行速度。特定示例中的代码总是比在主进程中直接执行
Main\u Residence(20,50,50)
慢。要使多处理在这样的上下文中有意义,您手头的工作需要分解为一组同质任务,这些任务可以并行处理,其结果可能稍后合并 例如(不一定是一个好的例子),如果您想要计算一系列数字的最大素数因子,您可以将为任何特定数字计算该因子的任务委托给池中的工作人员。然后,几个工人将并行进行这些单独的计算:
def largest_prime_factor(n):
p = n
i = 2
while i * i <= n:
if n % i:
i += 1
else:
n //= i
return p, n
if __name__ == '__main__':
pool = Pool(processes=3)
start = datetime.now()
# this delegates half a million individual tasks to the pool, i.e.
# largest_prime_factor(0), largest_prime_factor(1), ..., largest_prime_factor(499999)
pool.map(largest_prime_factor, range(500000))
pool.close()
pool.join()
print "pool elapsed", datetime.now() - start
start = datetime.now()
# same work just in the main process
[largest_prime_factor(i) for i in range(500000)]
print "single elapsed", datetime.now() - start
(最大素数因子函数取自in)
正如您所看到的,池的执行速度大约是相同工作量的单个进程执行速度的两倍,同时在三个进程中并行运行。这是由于多处理/池引入的开销造成的
因此,您声明示例中的代码已经简化。您必须分析原始代码,看看是否可以将其分解为同质任务,这些任务可以传递到您的池中进行处理。如果这是可能的,使用多处理可能会帮助您加快程序的速度。否则,多处理可能会花费您的时间,而不是节省时间
编辑:
因为你要求对代码提出建议。关于你的职能我几乎不能说什么。您自己说过,这只是一个提供MCVE的简化示例(顺便说一句,非常感谢!大多数人不会花时间将代码缩减到最低限度)。无论如何,代码审查的请求更适合于
利用可用的任务委派方法进行一些研究。在我的主要因素示例中,使用apply\u async
带来了巨大的损失。与使用map
相比,执行时间增加了九倍。但我的示例只使用了一个简单的iterable,您的每个任务需要三个参数。这可能是星图的一种情况,但它仅在Python 3.3中可用。
无论如何,任务数据的结构/性质基本上决定了要使用的正确方法。
我对您的示例函数的多处理进行了一些q&d测试。
输入定义如下:
inp = [(20, 50, 50)] * 5000 # that makes 5000 tasks against your Main_Residence
在Python3.6中,我在三个子进程中运行了这个函数,除了删除了print
station(I/O是昂贵的)之外,没有改变函数。我每次都使用、和对结果进行迭代,以解释异步结果上的阻塞get()
。
以下是输出:
starmap elapsed 0:01:14.506600
apply elapsed 0:02:11.290600
starmap async elapsed 0:01:27.718800
apply async elapsed 0:01:12.571200
# btw: 5k calls to Main_Residence in the main process looks as bad
# as using apply for delegation
single elapsed 0:02:12.476800
如您所见,虽然所有四种方法都做相同的工作量,但执行时间不同;您选择的apply\u async
似乎是最快的方法
编码风格。你的代码看起来很。。。非常规:)您使用大写的带下划线的单词作为名称(函数名和变量名),这在Python中几乎是不允许的。此外,将名称Previous_List
分配给字典也是。。。有问题。请看一看,特别是本节,了解Python的常用编码风格
从print
的外观判断,您仍然在使用Python 2。我知道,在公司或机构环境中,这有时是你所能得到的。不过,请记住,感谢您的解释。非常有用的指导。最初的代码当然不同,也更长,但主要部分是相似的,有三个for循环。我将按照你在第二段中的建议进行研究。欢迎对守则提出任何建议或修改。谢谢。我非常感谢你为回答我的问题所花费的时间、精力和提出的建议。非常感谢。嗨@shmee,我有一个关于在Windows笔记本电脑上运行多处理.Pool
的问题。我希望你能花点时间来检查一下这个问题。非常感谢你的帮助!
starmap elapsed 0:01:14.506600
apply elapsed 0:02:11.290600
starmap async elapsed 0:01:27.718800
apply async elapsed 0:01:12.571200
# btw: 5k calls to Main_Residence in the main process looks as bad
# as using apply for delegation
single elapsed 0:02:12.476800