我听说在 Python 中使用线程不如其他编程语言高效。
这是真的吗?如果是,那么 Python 程序员该如何克服这个问题呢?
我听说在 Python 中使用线程不如其他编程语言高效。
这是真的吗?如果是,那么 Python 程序员该如何克服这个问题呢?
人们认为Python中的多线程不太有效率是因为全局解释器锁(Global Interpreter Lock)。由于解释器的编写方式,同时只能有一个线程安全地执行解释器中的代码。
这意味着,如果您有一些相当耗费计算资源的线程,也就是说,在解释器中做了很多事情,那么您实际上仍然只有单线程程序的性能。在这种情况下,您最好使用multiprocessing模块,它与multithreading模块具有相同的接口,但会启动多个解释器副本(缺点是您必须明确共享内存)。
在Python中,如果您正在进行大量IO操作,仍然可以从多线程中获得速度提升。当一个线程等待磁盘或网络I/O时,其他线程仍然可以执行,因为当线程阻塞时,它们会释放解释器锁。
CPython使用引用计数和循环垃圾回收机制进行内存管理。为了使其实用化,它有一个称为“全局解释器锁”的机制来保护引用计数系统以及所有其他解释器内部。
在单核机器上,这并不重要——所有线程都是通过时间片轮转实现的。但在多核机器上,情况就不同了:在CPython上运行的CPU绑定型Python程序将无法利用所有可用的核心。
对此,有很多可能的解决办法:
如果正在使用线程将阻塞IO转换为非阻塞操作,则在标准CPython中可以正常工作,无需任何特殊修改——IO操作已经释放了GIL。
multiprocessing是一个支持使用类似于线程模块的API来生成进程的包。multiprocessing包提供了本地和远程并发,通过使用子进程而不是线程有效地绕过全局解释器锁定。因此,multiprocessing模块允许程序员充分利用给定机器上的多个处理器。它可运行于Unix和Windows。
有一个选择是使用不同的Python实现,比如Jython或IronPython。这样,您仍然可以享受使用Python语言的好处,而不必处理GIL。但是,您将无法使用仅限于CPython的库。
另一个选择是使用不同的构造而不是线程。例如,如果您使用Stackless Python,Tasklets是一种替代方案。
在CPython中,线程是高效的,但线程不能在不同的处理器/核心上并发运行。这可能就是所说的。只有在需要进行共享内存并发时才会受到影响。
其他Python实现没有这个问题。
from multiprocessing import Pool
def some_function(x):
return x*x
Xs = [i for i in xrange(1, 1000)] # make 1, 2, ..., 999, 1000
pool = Pool(processes=16) # start 16 worker processes on 16 CPU
print pool.map(some_function, Xs) # print out
Thread
类和Pool
类是用于两个不同的事情。 - Austin Henley