什么是全球解释器锁,为什么它是一个问题?
围绕从Python中删除GIL已经产生了很多噪音,我想知道为什么这么重要.我自己从未编写过编译器或解释器,所以不要节俭细节,我可能需要他们理解.
我希望有人可以提供一些见解,了解Java虚拟机的根本不同之处在于它允许它在不需要全局解释器锁(GIL)的情况下很好地实现线程,而Python则需要这样的恶意.
正如维基百科所述:
绿色线程模拟多线程环境而不依赖于任何本机操作系统功能,它们在用户空间而不是内核空间中进行管理,使它们能够在没有本机线程支持的环境中工作.
Python的线程实现为pthreads (kernel threads),并且由于全局解释器锁(GIL),Python进程一次只运行一个线程.
[ 问题 ]但在Green-threads(或所谓的greenlet或tasklets)的情况下,
- 这
GIL会影响他们吗?一次可以运行多个greenlet吗?- 使用greenlets或tasklet的缺陷是什么?
- 如果我使用greenlet,进程可以处理多少个?(我想知道,因为在一个进程中你可以打开你的*ix系统中设置的ulimit(-s,-v)线程 .)
我需要一点见解,如果有人可以分享他们的经验,或者引导我走上正确的道路,那将会有所帮助.
所以我刚刚在Python全局解释器锁(GIL)http://blip.tv/file/2232410上看完了这个演讲.
它的要点是GIL对于单核系统来说是一个非常好的设计(Python实际上将线程处理/调度留给了操作系统).但是,这可能严重地适应多核系统,最终导致IO密集型线程被CPU密集型线程严重阻塞,上下文切换费用,ctrl-C问题[*]等等.
因此,由于GIL限制我们基本上在一个CPU上执行Python程序,我的想法是为什么不接受这个并简单地在Linux上使用taskset来设置程序与系统上某个核心/ cpu的亲和性(特别是在某种情况下)在多核系统上运行的多个Python应用程序)?
所以最终我的问题是:有没有人尝试在Linux上使用带有Python应用程序的任务集(特别是在Linux系统上运行多个应用程序,以便多个核心可以与一个或两个绑定到特定核心的Python应用程序一起使用),如果是这样的话是结果?值得做吗?是否会使某些工作负载更糟糕?我打算这样做并进行测试(基本上看看程序是否需要花费更多或更少的时间来运行),但我很乐意听取其他人的经验.
另外:David Beazley(在链接视频中发表演讲的人)指出,一些C/C++扩展手动释放GIL锁,如果这些扩展针对多核进行优化(即科学或数字数据分析/等),那么而不是为数字运算获得多核的好处,扩展将被有效地削弱,因为它仅限于单个核心(因此可能显着降低程序速度).另一方面,如果您没有使用此类扩展
我没有使用多处理模块的原因是(在这种情况下)程序的一部分是严重的网络I/O绑定(HTTP请求),所以有一个工作线程池是一个很好的方式从一个盒子挤出性能一个线程触发一个HTTP请求,然后因为它在I/O上等待就放弃了GIL而另一个线程可以做到这一点,所以程序的一部分可以轻松地运行100多个线程而不会伤害CPU太多让我实际使用可用的网络带宽.对于无堆栈的Python/etc,我对重写程序或替换我的Python堆栈并不过分感兴趣(可用性也是一个问题).
[*]只有主线程可以接收信号,所以如果你发送一个ctrl-C,Python解释器基本上试图让主线程运行,这样它就可以处理信号,但因为它不能直接控制运行哪个线程(它留给操作系统)它基本上告诉操作系统继续切换线程,直到它最终命中主线程(如果你不幸,可能需要一段时间).
我即将编写一些计算密集型的Python代码,几乎可以肯定它的大部分时间都花在了numpy线性代数函数中.
手头的问题令人尴尬地平行.简而言之,对我来说最简单的方法就是使用多线程.主要障碍几乎肯定是全球翻译锁(GIL).
为了帮助设计这个,有一个心理模型是有用的,numpy可以期望操作在其持续时间内释放GIL.为此,我会欣赏任何经验法则,注意事项,注意事项等.
如果它很重要,我在Linux上使用64位Python 2.7.1,使用numpy1.5.1和scipy0.9.0rc2,使用英特尔MKL 10.3.1构建.
我在一个多线程的C应用程序中嵌入python解释器,我有点困惑的是我应该使用什么API来确保线程安全.
从我收集的内容来看,嵌入python时,在调用任何其他Python C API调用之前,由嵌入器来处理GIL锁.这是通过以下功能完成的:
gstate = PyGILState_Ensure();
// do some python api calls, run python scripts
PyGILState_Release(gstate);
Run Code Online (Sandbox Code Playgroud)
但仅凭这一点似乎还不够.我仍然有随机崩溃,因为它似乎不提供Python API的互斥.
在阅读了更多文档后,我还补充说:
PyEval_InitThreads();
Run Code Online (Sandbox Code Playgroud)
在电话会议结束后,Py_IsInitialized()这就是令人困惑的部分.文档声明这个函数:
初始化并获取全局解释器锁
这表明当这个函数返回时,GIL应该被锁定并且应该以某种方式解锁.但实际上这似乎并不是必需的.有了这条线,我的多线程工作完美,并且PyGILState_Ensure/Release功能保持互斥.
当我尝试PyEval_ReleaseLock()在PyEval_ReleaseLock()应用程序死锁后很快在后续调用中添加PyImport_ExecCodeModule().
那我在这里错过了什么?
有没有人知道Python 3.1中针对C++多线程集成的Global Interpreter Lock的命运
Python 3.2引入了Antoine Pitrou的一个新的GIL实现,它公开了这个函数sys.setswitchinterval.
什么时候改变这个有用,为什么?
我经常看到有人说GIL是根据Python解释器(甚至在stackoverflow上).
但是我在源代码中看到的似乎是GIL是一个全局变量,因此每个python进程中的所有解释器都有一个GIL.我知道他们这样做是因为没有像lua或TCL那样传递的解释器对象,它在开始时设计得不好.线程本地存储似乎不适合python人员使用.
它是否正确?我简要介绍了我在这个项目中使用的2.4版本.
如果在以后的版本中有所改变,特别是在3.0版本中?
我只是在寻找这个新的实现,我使用python 2.7,我必须安装它,所以如果我使用它,我会忘记CPython上的GIL这个词?