文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
11.2 多进程与多线程
正如前面解释的,因为GIL的问题,多线程并非好的可扩展性方案。更好的方案是Python中提供的multiprocessing包。它提供了类似multithreading模块中的接口,区别在于它会启动一个新的进程(通过fork(2))而不是一个新的系统线程。
下面是一个简单的例子,计算100万个随机整数的和8次,同时将其分散到8个线程中。
使用多线程的worker
import random import threading results = [] def compute(): results.append(sum( [random.randint(1, 100) for i in range(1000000)])) workers = [threading.Thread(target=compute) for x in range(8)] for worker in workers: worker.start() for worker in workers: worker.join() print("Results: %s" % results)
程序的运行结果如示例11.1所示。
示例 11.1 time python worker.py的运行结果
$ time python worker.py Results: [50517927, 50496846, 50494093, 50503078, 50512047, 50482863, 50543387, 50511493] python worker.py 13.04s user 2.11s system 129% cpu 11.662 total
这个程序运行在四核的CPU上,这意味着Python最多可以利用400%的CPU能力。但显然它做不到,即使并行运行8个进程,它仍然卡在了129%,这只是硬件能力的32%。
现在,我们使用multiprocessing重写一下如示例11.2所示。对于这种简单的例子来说,实现是相当直接的。
示例 11.2 使用multiprocessing的 worker
import multiprocessing import random def compute(n): return sum( [random.randint(1, 100) for i in range(1000000)]) # Start 8 workers pool = multiprocessing.Pool(8) print("Results: %s" % pool.map(compute, range(8)))
在同样的条件下运行这个程序,结果如示例11.3所示。
示例 11.3 time python worker.py的运行结果
$ time python workermp.py Results: [50495989, 50566997, 50474532, 50531418, 50522470, 50488087, 50498016, 50537899] python workermp.py 16.53s user 0.12s system 363% cpu 4.581 total
执行时间减少到60%,这次程序可以消耗363%的CPU能力,超过CPU能力的90%。
此外,multiprocessing模块不仅可以有效地将负载分散到多个本地处理器上,而且可以通过它的multiprocessing.managers对象在网络中分散负载。它还提供了双向传输,以使进程间可以彼此交换信息。
每次考虑在一定的时间内并行处理一些工作时,最好是依靠多进程创建(fork)多个作业,以便能够在多个CPU核之间分散负载。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论