为什么多进程速度慢
我刚开始学习多进程的知识,目的是为了加快我的程序运行速度。于是,我写了两个简单的例子,从一堆随机数字中找出质数。
例子 1:使用多进程
from multiprocessing import Process, Queue
from random import randrange
import time
def randomList(q, size, nmax):
l = []
r = randrange(2, nmax)
for i in range(size):
while r in l: # avoid replicating numbers
r = randrange(2, nmax)
l.append(r)
q.put(r)
def checkPrime(numbers, prime):
if numbers.qsize():
n = numbers.get()
count = 0 # divisors counter
d = 2 # divisor
while not count and d<=n/2:
if n%d:
d+=1
else:
count+=1
if not count:
prime.put(n)
if __name__=="__main__":
numbers = Queue()
prime = Queue()
randomList(numbers, 50, 1000) # 50 number | 100 max value
t1 = time.time()
while numbers.qsize():
for i in range(10): # Running 10 processes
p=Process(target=checkPrime, args=(numbers, prime))
p.start()
p.join()
t2 = time.time()
primes = []
for i in range(prime.qsize()):
primes.append(prime.get())
print("[+] Prime numbers:")
print(primes)
print("[+] Time elapsed:"+str(t2-t1))
输出:
[+] Prime numbers:
[17, 227, 389, 593, 953, 757]
[+] Time elapsed:9.41699981689
例子 2:和例子 1 一样,但不使用多进程
[...]
while numbers.qsize():
checkPrime(numbers, prime)
[...]
输出:
[+] Prime numbers:
[193, 227, 241, 439, 499, 877, 479, 743, 929]
[+] Time elapsed:0.00999999046326
所以,使用多进程让这个程序(可能是特定情况下)变得比不使用它要慢得多。有什么解释吗?我是不是用错了?
3 个回答
在多进程编程中,有一个简单的规则:如果把工作分开(创建子任务)和合并结果(把结果合在一起等)的时间,加起来比顺序执行的时间还要长,那么你的“并行”版本就会比顺序版本效率低。这就是你的情况。试着生成一百万个数字(把进程数量保持在10个),你就会看到差别。
@Sohcahtoa82 提供了一些很好的编码建议,记得参考一下。
你的 for i in range()
在调用 .join()
时,会等这个进程完成后才继续。所以,简单来说,你是启动了一个新进程来处理队列并报告结果,然后又启动了9个其他进程去检查一个空的队列。
.join()
这个方法会让调用它的线程一直等到被调用的进程结束,或者等到你设置的超时时间到。
使用进程池是一种更简单的方法来做同样的事情。你可以查看这个回答,了解如何用 map_async()
和工作进程池一起使用:
我觉得你现在的多进程方法不太好。你不是把工作分成10个进程同时启动,而是一个一个地启动,每个进程只做一小部分工作,然后就结束了。这样的话,你的程序在运行过程中会创建(然后销毁)50个进程,这样会浪费很多资源。
而且,你在启动进程后立刻就把它们合并,这样的话其实就没有真正同时运行多个进程。合并操作会让主程序等着子进程完成后才能继续。
最后,返回结果的方式也可以更简单,不一定要用队列一个一个地取值。如果你能一次性启动每个进程,并给它们一组工作,然后把结果以列表的形式返回给主线程,这样可以减少使用队列带来的额外开销。