Return to site

多进程Multiprocessing

Python学习系列

· Python,技术

先了解GIL

Python设计中, 存在一个 Global Interpreter Lock (GIL), 目的是让Python一次性只处理一个东西。

尽管Python支持多进程, 但在C语言解释器部分的实现在并行时并不是线程安全的。

实际上,解释器被GIL保护,它确保任何时候都只有一个Python进程执行。 GIL最大问题导致了 Python的多线程程序不能利用多核的优势 (比如一个使用多个线程的计算密集型程序只会在一个单CPU上面运行)

 

GIL只会影响那些严重依赖CPU的程序(计算型是典型的例子)。 如果程序大部分只涉及到I/O, 比如网络交互, 那么使用多进程就很合适,因为大部分时间都在等待。

threading

先看一个常用的例子: 两个job(修改全局变量 global A , 一个+1, 一个+10)

相关代码: https://gist.github.com/staticor/3b646a15484adc0fd1f9d1242dd5e97d

使用lock

通过输出可以看到, 全局变量是错次没有固定规律的被修改的。

这时我想到了常用的解决思路 -- 锁。 在每个线程访问共享内存之前, 执行

 

lock.acquire()

将共享内存上锁,确保当前线程执行时,内存是独占的,运算完毕后,使用

lock.release()

 

lock可以在不同线程共享内存时,确保线程间互不影响。

(lock版代码也在上面的Gist)

multiprocessing

下面的简单代码描述了 如何添加线程与进程实例。

进一步地, 可以查看使用Queue(队列), 以实现将每个核或线程的运算结果放在队列中。

等到每个线程或核运行完毕后再从队列中取出结果, 继续加载进入到下一步运算。

原因: 多线程调用的函数不能有返回值, 所以使用Queue存储多个线程运算的结果。

multiprocessing & threading

代码在上面的gist, 运行结果显示

耗时: 多进程 < 普通 < 多线程

进程池

进程池是一种多进程解决方案 -- 可以让我们把要运行任务扔到这个池子里, Python帮我们解决多进程的问题。

All Posts
×

Almost done…

We just sent you an email. Please click the link in the email to confirm your subscription!

OK