python多进程并行的简单实现

本文探讨了Python中多线程与多进程的性能差异,指出多线程受GIL限制无法充分利用多核CPU,而多进程通过multiprocessing模块能有效实现并行处理。对比了threading.Thread与multiprocessing.Process及Pool的使用方法,展示了如何通过进程池提高CPU利用率。

  这两天在跑一个文件处理程序的时候想着利用多核并行处理实现节省时间,然后例程里用了threading.Thread来实现,结果依旧很慢,查看了一下cpu使用情况根本就是在单核上跑啊。查了一下才发现python中多线程存在PIL锁,什么意思呢,就是说这个锁使得同时只能有一个线程执行。。。。。这样的结果就是即使利用了多线程,多个线程仍旧是在单核上执行的,执行某一个线程的时候,余下的所有线程都吃瓜。
  那怎么利用多核并行执行呢?python中提供了multiprocess模块可以实现这个需求。两种方式,第一种利用multiprocess.Process,第二种利用进程池multiprocess.Pool

1.首先来看看多线程实现,代码如下:

from multiprocessing import cpu_count
import threading
 
def loop():
    while True:
        pass
        
if __name__ == '__main__':
    threads = []
    for i in range(cpu_count()):
        t = threading.Thread(target=loop, args=[])  # 新建一个线程,target表示线程将要执行的函数,args表示函数的参数
        threads.append(t)
        t.start()   # 启动线程
    for t in threads:
        t.join()    # 线程等待,等子线程(t)执行结束完以后再结束主线程
 
    while True:
        pass

cpu_count()是获取cpu核的个数的函数,这里让线程执行目标为死循环是为了简单粗暴地观察cpu使用情况。在我的四核cpu上执行结果如下:

可以看到基本上只消耗了一个cpu的资源,也就是说多线程的方式实际上并不能实现多核并行执行。下面来看看多进程的方式实现。

2. 多进程之multiprocess.Process
  Process是python中用来创建进程的基础模块,后面的Pool也是基于Process来实现的。代码如下:

from multiprocessing import cpu_count
from multiprocessing import Process
 
def loop():
    while True:
        pass
        
if __name__ == '__main__':
    threads = []
    for i in range(cpu_count()):
        t = Process(target=loop, args=[])
        threads.append(t)
        t.start()
    for t in threads:
        t.join()
 
    while True:
        pass

基本的代码步骤和前面多线程实现一样,运行上面代码再观察任务管理器结果如下:

可以看到此时cpu利用率达到了100%,我的破电脑四核cpu,执行上面的代码四个进程分别在四个核上并行执行。

3. 多进程之multiprocess.Pool
  Pool:池子的意思,也就是进程池。multiprocess.Pool首先建立一个固定大小的进程池,有需求来的话就让池中一个进程去执行任务(应该就是Process吧)。现在将上面的代码改写成进程池的实现:

from multiprocessing import cpu_count
from multiprocessing import Pool
 
def loop():
    while True:
        pass
        
if __name__ == '__main__':
    p = Pool(cpu_count())  # 创建一个大小等于cpu核数的进程池
    for i in range(cpu_count()): # 分配cpu核数个任务给每个进程并加入进程池
        p.apply_async(loop, args=[])  # 这里用了异步非阻塞式
        
    p.close()  # 关闭进程池,不能再加入进程
    p.join()   # 主进程等进程池中所有子进程全结束再结束
 
    while True:
        pass

上面的代码执行结果如下:

和前面Process的实现结果一样,四个进程在不同的cpu核上执行,cpu利用率达到100%。此外有一个需要注意的问题,Pool在实现多进程执行的时候有两种方式:
  • 同步阻塞式apply
  • 异步非阻塞式apply_async

简单来说apply方法是阻塞的,因此在一个子进程执行的时候,其他进程等待,等当前子进程执行结束之后再执行下一个。apply_async方法是非阻塞的,根据系统调度来切换进程,不用等待进程结束。
如果把上面的程序中apply_async改为apply,结果会发现四个进程中只有一个会执行,占用cpu25%,其他都是0,并且由于死循环这个进程不会结束,其他进程根本不会执行。

总结

  用到并行了大概了解了一下怎么实现,没有深入的学习,更详细地分析可以看以下文章。Pool的这个同步阻塞式方法也没有理解。。。。感觉只利用了单核cpu。。。

https://www.cnblogs.com/xiao987334176/p/9019884.html
python进程池apply与apply_async的区别

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值