我听说Python中的线程效率不高(与其他语言相比)。
这是真的吗?如果是这样,Python程序员怎么能克服这个呢?
答案 0 :(得分:19)
人们之所以说多线程在python中效率不高是因为Global Interpreter Lock。由于编写解释器的方式,只有一个线程可以同时安全地在解释器中执行代码。
这意味着如果你的线程有很大的计算限制,也就是说,在解释器中做了很多东西,那么你实际上仍然只具有单线程程序的性能。在这种情况下,您可能最好使用多处理模块,该模块与多线程模块具有相同的接口,但会启动解释器的多个副本(这样做的缺点是您必须明确共享内存)。
如果你正在做一些严重IO绑定的事情,你仍然可以在python中从多线程中获得速度提升。当一个线程正在等待磁盘或网络i / o时,其他线程仍然可以执行,因为当线程阻塞时它们会释放解释器锁。
答案 1 :(得分:9)
CPython将引用计数与循环垃圾收集器一起用于内存管理。为了实现这一点,它有一个称为“全局解释器锁”的机制,它保护引用计数系统以及所有其他解释器内部。
在单核机器上,这没关系 - 无论如何,所有线程都是通过时间切片伪造的。在多核机器上,它有所不同:在CPython上运行的CPU绑定Python程序将不会使用所有可用内核。
对此有很多可能的回应:
如果使用线程将阻塞IO转换为非阻塞操作,那么在标准CPython中可以正常工作而无需任何特殊修改 - IO操作已经释放了GIL。
答案 2 :(得分:5)
您可以使用multiprocessing来克服此问题!它就像python中的多线程一样简单,但却为你提供了所有cpu内核的全部功能。
multiprocessing是一个使用类似于线程模块的API支持产生进程的包。多处理包提供本地和远程并发,通过使用子进程而不是线程有效地侧向执行全局解释器锁。因此,多处理模块允许程序员充分利用给定机器上的多个处理器。它可以在Unix和Windows上运行。
答案 3 :(得分:1)
一种选择是使用不同的Python实现,如Jython或IronPython。这样,您仍然可以获得使用Python语言而不必处理GIL的好处。但是,您将无法使用仅限CPython的库。
另一种选择是使用与线程不同的构造。例如,如果您使用Stackless Python,Tasklets是另一种选择。
答案 4 :(得分:1)
线程在CPython中很有效,但线程无法在不同的处理器/内核上并发运行。这可能就是这个意思。如果您需要执行共享内存并发,它只会影响您。
其他Python实现没有这个问题。
答案 5 :(得分:0)
找到解决方案后(下面)我想知道为什么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