使用进程池规避Python的GIL限制
操作系统 : CentOS7.3.1611_x64
python版本:2.7.5
问题描述
Python的GIL会对CPU密集型的程序产生影响,如果完全使用Python来编程,怎么避开GIL的限制呢?
解决方案
在多线程中使用进程池来规避GIL的限制。具体如下:
1、使用multiprocessing模块来创建进程池;
2、将计算任务分配给不同的线程;
3、在任务线程中把任务提交给之前创建的进程池;
每当有线程要执行cpu密集型任务时,就把该任务提交到进程池中,然后进程池会将任务交给运行在另一个进程中的Python解释器。
当线程等待结果时会释放GIL,而此时的计算任务是在另一个单独的Python解释器中执行的,不再受到GIL的限制了。
在多核系统中采用这个方案能轻易地利用到所有的CPU核心。
假设有这样的worker函数:
def worker(arr):
s = 0
for n in arr :
arrTmp = range(1,n+1)
if len(arrTmp) == 0 : continue
rtmp = 1
for i in arrTmp :
rtmp *= i
s += rtmp
return s
完整代码如下:https://github.com/mike-zhang/pyExamples/blob/master/gilAvoid/gilAvoidTest1/taskCommon.py
普通单进程任务实现:
def main():
s = 0
tStart,tStop = 1,1000
for i in range(1,100):
#t = worker(range(tStart,tStop))
t = worker(range(1,1000))
s += t
tStart = tStop
tStop += 1000
print("len : ",len(str(s)))
print(s%10000)
完整代码如下: https://github.com/mike-zhang/pyExamples/blob/master/gilAvoid/gilAvoidTest1/t1_normal.py
运行效果如下:
(py27env) [mike@localhost test]$ time python t1_normal.py
('len : ', ) real 0m17.919s
user 0m17.915s
sys 0m0.003s
使用进程池的实现:
def wokerThread(start,stop):
#r = gPool.apply(worker,(range(start,stop),))
r = gPool.apply(worker,(range(1,1000),))
q.put(r)
# E-Mail : Mike_Zhang@live.com
def main():
s = 0
thrdArr = []
tStart,tStop = 1,1000
for i in range(1,gCount+1):
thrd = threading.Thread(target=wokerThread,args=(tStart,tStop))
thrdArr.append(thrd)
tStart = tStop
tStop += 1000
for t in thrdArr :
t.daemon = True
t.start()
while not q.full(): time.sleep(0.1)
while not q.empty(): s += q.get()
print("len : ",len(str(s)))
print(s%10000)
完整代码如下:https://github.com/mike-zhang/pyExamples/blob/master/gilAvoid/gilAvoidTest1/t2_mp.py
运行效果如下:
(py27env) [mike@localhost test]$ time python t2_mp.py
queue full
('len : ', ) real 0m4.917s
user 0m18.356s
sys 0m0.146s
可以看出使用上述方法可以规避GIL的限制(测试机器为i5 4核),程序的速度得到明显的提升。
好,就这些了,希望对你有帮助。
本文github地址:
https://github.com/mike-zhang/mikeBlogEssays/blob/master/2017/20170819_使用进程池规避python的GIL限制.rst
欢迎补充
使用进程池规避Python的GIL限制的更多相关文章
- GIL 线程池 进程池 同步 异步
1.GIL(理论 重点)2.线程池 进程池3.同步 异步 GIL 是一个全局解释器锁,是一个互斥锁 为了防止竞争解释器资源而产生的 为何需要gil:因为一个python.exe进程中只有一份解释器,如 ...
- python GIL锁、进程池与线程池、同步异步
一.GIL全局解释器锁 全局解释器锁 在CPython中,全局解释器锁(GIL)是一个互斥锁,它可以防止多个本机线程同时执行Python代码.之所以需要这个锁,主要是因为CPython的内存管理不是线 ...
- python GIL全局解释器锁,多线程多进程效率比较,进程池,协程,TCP服务端实现协程
GIL全局解释器锁 ''' python解释器: - Cpython C语言 - Jpython java ... 1.GIL: 全局解释器锁 - 翻译: 在同一个进程下开启的多线程,同一时刻只能有一 ...
- Python学习之GIL&进程池/线程池
8.6 GIL锁** Global interpreter Lock 全局解释器锁 实际就是一把解释器级的互斥锁 In CPython, the global interpreter lock, or ...
- Python并发编程05 /死锁现象、递归锁、信号量、GIL锁、计算密集型/IO密集型效率验证、进程池/线程池
Python并发编程05 /死锁现象.递归锁.信号量.GIL锁.计算密集型/IO密集型效率验证.进程池/线程池 目录 Python并发编程05 /死锁现象.递归锁.信号量.GIL锁.计算密集型/IO密 ...
- GIL全局解释器锁、死锁现象、python多线程的用处、进程池与线程池理论
昨日内容回顾 僵尸进程与孤儿进程 # 僵尸进程: 所有的进程在运行结束之后并不会立刻销毁(父进程需要获取该进程的资源) # 孤儿进程: 子进程正常运行 但是产生该子进程的父进程意外死亡 # 守护进程: ...
- 4月27日 python学习总结 GIL、进程池、线程池、同步、异步、阻塞、非阻塞
一.GIL:全局解释器锁 1 .GIL:全局解释器锁 GIL本质就是一把互斥锁,是夹在解释器身上的, 同一个进程内的所有线程都需要先抢到GIL锁,才能执行解释器代码 2.GIL的优缺点: 优点: 保 ...
- python进程池剖析(一)
python中两个常用来处理进程的模块分别是subprocess和multiprocessing,其中subprocess通常用于执行外部程序,比如一些第三方应用程序,而不是Python程序.如果需要 ...
- Python 多进程和进程池
一,前言 进程:是程序,资源集合,进程控制块组成,是最小的资源单位 特点:就对Python而言,可以实现真正的并行效果 缺点:进程切换很容易消耗cpu资源,进程之间的通信相对线程来说比较麻烦 线程:是 ...
随机推荐
- Vijos 1006 晴天小猪历险记之Hill 单源单汇最短路
背景 在很久很久以前,有一个动物村庄,那里是猪的乐园(^_^),村民们勤劳.勇敢.善良.团结-- 不过有一天,最小的小小猪生病了,而这种病是极其罕见的,因此大家都没有储存这种药物.所以晴天小猪自告奋勇 ...
- Struts2的知识点小总结
strust2是 struts1和webwork的结合 (本质相当于servlet) 核心:拦截器 interceptor action ognl和valuestack 使用struts的准备工作 ...
- vue2.0引入腾讯地图
百度很多东西,然后我没找到腾讯地图在VUE2.0里面的引用.于是根据找的其他地图引用资料进行尝试.步骤如下. 首先在src里面建立了TMap.js的文件,内容如下: export function T ...
- Unity-Shader-动态阴影(上) 投影的矩阵变换过程
[旧博客转移 - 2017年1月20日 01:20 ] 前面的话 最近很长时间没写博文了,一是太忙 ( lan ) 了,二是这段时间又领悟了一些东西,脑子里很混乱,不知道从何写起.但感觉不能再拖延下去 ...
- Bash : 索引数组
Bash 提供了两种类型的数组,分别是索引数组(indexed array)和关联数组(associative array).本文主要介绍索引数组的基本用法. 索引数组的基本特点 Bash 提供的数组 ...
- Java开发环境的搭建及配置
1.首先下载并安装jdk,jdk和jre最好安装在同一文件夹的不同目录文件中,jdk安装完后就是进行环境变量的配置. JDK的环境变量配置: (1)新建变量JAVA_HOME , 值为 jdk安 ...
- css3变换,过度,动画实现梦幻网页
html和css3一出,整个互联网设计发生了颠覆性的改变,各大IT企业也推出了很多新颖的设计,比如百度浏览器的下载首页,fullpage设计风格加css动画让网页看起来很流畅舒服. css3的变换有3 ...
- ES6正则表达式扩展
前面的话 正则表达式是javascript操作字符串的一个重要组成部分,但在以往的版本中并未有太多改变.然而,在ES6中,随着字符串操作的变更, ES6也对正则表达式进行了一些更新.本文将详细介绍ES ...
- SpringMVC源码情操陶冶-ViewResolver视图解析
简单分析springmvc是如何解析view视图,并返回页面给前端 SpringMVC配置视图解析器 <bean id="viewResolver" class=" ...
- LCS 51Nod 1134 最长递增子序列
给出长度为N的数组,找出这个数组的最长递增子序列.(递增子序列是指,子序列的元素是递增的) 例如:5 1 6 8 2 4 5 10,最长递增子序列是1 2 4 5 10. Input 第1行:1个 ...