# -*- encoding: utf-8 -*-
from concurrent.futures import ThreadPoolExecutor
from concurrent.futures import ProcessPoolExecutor
from time import time
'''
第41条: 考虑用concurrent.futures来实现真正的平行计算
关键:
1 GIL
GIL全局解释器锁没有办法用线程实现平行计算
优化性能方法:
1) 用C语言把性能要求高的代码改写为扩展模块
2) 使用concurrent.futures模块,利用另外一个
multiprocessing的模块。
原理: 会以子进程的形式,平行运行多个解释器,从而令
Python程序能够利用多核心的CPU来提升执行速度。
由于子进程与主解释器分离,所以它们的全局解释器锁也是独立的。
每个子进程可以完整利用一个CPU内核。
子进程可以接收主进程发送过来的指令,把计算结果返回给主进程。
2 concurrent.futures.ProcessPoolExecutor
本质: 多进程
处理过程:
1)把数据列表中的每一项数据都传给map
2)用pickle模块对数据进行序列化,将其变成二进制形式
3)通过本地套接字,将序列化的数据从主解释器所在进程发送到
子解释器所在进程
4)在子进程中,用pickle对二进制数据帆序列化,还原为python对象
5) 引入包含目标函数的python模块
6) 各条子进程平行地针对各自输入数据,运行目标函数
7) 对运行结果序列化,转变为字节
8) 将字节通过socket复制到主进程中
9) 主进程对字节反序列化,还原为python对象
10) 每条子进程所求地计算结果合并到一份列表
缺点: 主进程和子进程之间进行序列化和反序列化操作带来开销
适用: 运行函数不需要与程序中其他部分共享状态;主进程与子进程传递数据量小
高级特性: 共享内存,跨进程锁定,队列,代理(复杂,不推荐)
3 总结
通过concurrent.futures.ProcessPoolExecutor提升性能
参考:
Effectiv Python 编写高质量Python代码的59个有效方法
'''
def gcd(pair):
a, b = pair
low = min(a, b)
for i in range(low, 0, -1):
if a % i == 0 and b % i == 0:
return i
def compute():
numbers = [
(1963309, 2265973),
(2030677, 3814172),
(1551645, 2229620),
(2039045, 2020802)
]
start = time()
results = list(map(gcd, numbers))
print results
end = time()
print "cost : {value} seconds".format(
value=end - start
)
start = time()
pool = ThreadPoolExecutor(max_workers=4)
results = list(pool.map(gcd, numbers))
print results
end = time()
print "thread pool executor cost : {value} seconds".format(
value=end - start
)
start = time()
with ProcessPoolExecutor(max_workers=4) as pool:
results = list(pool.map(gcd, numbers))
print results
end = time()
print "process pool executor cost : {value} seconds".format(
value=end - start
)
def process():
compute()
if __name__ == "__main__":
process()
Effective Python 读书笔记: 第41条: 考虑用concurrent.futures来实现真正的平行计算
猜你喜欢
转载自blog.csdn.net/qingyuanluofeng/article/details/88963161
今日推荐
周排行