C++,python,热爱算法和机器学习
全部博文(1214)
分类: Python/Ruby
2012-04-20 02:09:51
Python 3.2于前天正式。在Python 3.1发布之后,根据Guido的建议 (PEP 3003),Python的开发人员在2011年6月份之前,都不再对Python语言进行大的修改,而是将主要精力集中在修复bug,提高稳定性以及性能上。现在Python 3.2带着这样的目标到来了。
Python 3.2带来的改进有很多,其中一个惹人注目的改动是重新实现的GIL (Global Interpreter Lock)。 众所周知,Python(这里说的Python实际上是Python语言的参考实现CPython)的GIL是阻碍Python性能提升的一个屏障,因为 有GIL的存在,即使Python提供了非常优雅简洁的threading库接口,你实际上还是无法享用多线程所带来的性能提升,因为本质上GIL只允许 一个线程在Python进程下运行。也因此从GIL诞生的那天起,关于去掉GIL的争论就一直没停止过。对此,Guido以及Python的开发人员都有一个很明确的,那就是去掉GIL并不容易,或者说是不值当的。
如果说在Python下使用多线程,因为GIL的存在而不起效用的话也就罢了。更令人不能接受的是,在某些情况下,使用多线程不光不能提高效率,反 而会降低效率,尤其是在多CPU的机器上,效率反而比单CPU(将其余CPU禁止)要低很多。这样的结果无论如何是说不过去的。David Beazley曾经对此做过非常详细的分析,以及。原因大体如下:
Python使用GIL来控制任何时候只能有一个线程运行,并且Python来控制线程何时释放GIL,而底层的OS来控制哪个线程获取GIL。 Python在遇到两种情况下强制某个线程释放GIL,一是该线程要进行IO操作,二是该线程已经执行了某个数量的opcode。这样的机制就带来了两个 问题:
针对这些问题,Antoine Pitrou对GIL的实现进行了重写,他曾在Python的开发列表上详细阐述了重新实现的机制:
Pitrou对GIL的重新实现也就是现在3.2版本的GIL,解决了相当一部分问题。但仍然有部分极端情况未能解决,归根结底在于在GIL的释放由Python来控制,但GIL由哪个线程获取却仍然是底层的OS来决定的,而这仍然有可能带来性能的下降。
为此Beazley专门向Python发了一个, 附上了相关的测试脚本,并介绍了一种可能的解决办法。在这个bug的解决上,相关开发人员对此进行了详细的分析与测试,如果要解决这个问题,显然必须要把 部分kernel的调度机制,挪到Python里,也就是必须对Python的线程区分优先级。Nir Aides为此专门将Kernel的Brainfuck调度算法,在Python里重新实现并做了相应的patch。但该patch并没有集成到3.2 中,对此的解释是针对线程调度的修改最好慢慢来,这个问题需要实际的应用来证实确实需要修复。目前看来,也许在3.3中才能看到该修复。
当然即使该问题得到了修复,Python的多线程也看起来更加完善,但从根本上,仍然还在GIL上转圈圈。仍然会有刚了解Python的开发人员去 质疑为什么不去掉GIL,尤其是在今天,多CPU已经成为标准的配置。但至少在很长的时间内,你听到的答复都将是,很困难,去不掉,你只能选择使用多进 程,或者用C扩展的方式来绕过GIL。
这样的答复即使理由足够充分,也无法令人满意。毕竟在解决问题时,谁都希望能有更多选择。但事实上,Python在经过这么多年的发展后,对于GIL的依赖已经,悲观的说,GIL已不太可能从Python中去掉。除非某个有勇气的人,将Python重新实现。