Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4586803
  • 博文数量: 1214
  • 博客积分: 13195
  • 博客等级: 上将
  • 技术积分: 9105
  • 用 户 组: 普通用户
  • 注册时间: 2007-01-19 14:41
个人简介

C++,python,热爱算法和机器学习

文章分类

全部博文(1214)

文章存档

2021年(13)

2020年(49)

2019年(14)

2018年(27)

2017年(69)

2016年(100)

2015年(106)

2014年(240)

2013年(5)

2012年(193)

2011年(155)

2010年(93)

2009年(62)

2008年(51)

2007年(37)

分类: 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。这样的机制就带来了两个 问题:

  1. 使用固定数量的opcode做为单位来强制切换线程,必然是粗糙的,不准确的,因为有的代码可能执行的很快,而有的则更耗时。
  2. 让OS来选择哪个线程执行,有时候是无法预测的(尤其在多CPU下)。比如有可能造成某个线程刚刚释放GIL,却马上又获取了GIL。

针对这些问题,Antoine Pitrou对GIL的实现进行了重写,他曾在Python的开发列表上详细阐述了重新实现的机制:

  • 使用固定的时间而不是固定数量的opcode来进行线程的强制切换。这样就解决了上述问题1,但使用固定的时间仍然是相当机械的,有可能在这个时间内,某个优先级更高的线程(比如一个IO等待操作正巧数据来了)需要运行,却只能等待。
  • 在线程释放GIL后,开始等待,直到某个其它线程获取GIL后,再开始去尝试获取GIL。这样可以避免此前获得GIL的线程,不会立即再次获取GIL,但仍然无法保证优先级高的线程获取GIL。

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重新实现。


阅读(2649) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~