Effective Python 读书笔记: 第41条: 考虑用concurrent.futures来实现真正的平行计算

# -*- 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() 

猜你喜欢

转载自blog.csdn.net/qingyuanluofeng/article/details/88963161