python能够在多个内核上运行吗?


70

问题:由于python使用“ GIL”,python是否能够同时运行其单独的线程?


信息:

看完这篇文章后,我对python是否能够利用多核处理器的不确定性产生了怀疑。尽管python做得很好,但认为它缺乏如此强大的功能实在是很奇怪。因此,我感到不确定,因此决定在这里提问。如果我编写的程序是多线程的,那么它是否可以在多个内核上同时执行?



1
请注意,问题“ python是否能够在多个内核上运行?” 与“ python是否能够(在一个进程中)同时运行其单独的线程?”是一个不同的问题吗?
扎卡里·瑞安·史密斯

Answers:


60

答案是“是,但是...”

但是当您使用常规线程进行并发时,cPython不能。

您可以使用或之类的东西multiprocessingcelerympi4py可以将并行工作拆分为另一个进程。

或者,您可以使用JythonIronPython之类的东西来使用没有GIL的替代解释器。

较软的解决方案是使用不会在GIL上运行的库来执行繁重的CPU任务,例如numpy可以在不保留GIL的情况下进行繁重的工作,因此可以继续使用其他python线程。您也可以通过ctypes这种方式使用库。

如果您不进行CPU限制工作,则可以完全忽略GIL问题(因为),因为python在等待IO时不会获取GIL。


我相信还是Stackless Python。
2011年

我相信pypy目前仍具有GIL,他们正在尝试软件过渡内存,但尚未完成。
雅各布·鲍耶

看来你是对的;尽管已经开始了支持无GIL的PyPy所需的一些工作(特别是混合垃圾收集器),但GIL仍然存在;我已经编辑了答案以反映这一点。
SingleNegationElimination 2011年

2
考虑一下几乎每个人都对我的问题有什么反应,好像我不知道GIL是什么一样,我感到您是唯一阅读整个问题的人……总之,谢谢,所有指向各种库的链接都相当有帮助的。
Narcolapser 2011年

40

Python线程无法利用许多内核。这是由于在python(cPython)的C实现中称为GIL(全局解释器锁)的内部实现细节,几乎可以肯定是您所使用的。

解决方法是为此目的开发的multiprocessing模块http://www.python.org/dev/peps/pep-0371/

文档:http : //docs.python.org/library/multiprocessing.html

(或使用并行语言。)


3
+1表示线程受到某种程度的限制,这是我到目前为止所经历的..通过多处理可以正常工作!
数学

多重处理对我不起作用,我已经用尽了所有带有args的替代文档:jobutil。非常令人沮丧
Jamie Nicholl-Shelley

11

CPython(Python的经典且流行的实现)不能有多个线程同时执行Python字节码。这意味着计算绑定程序将仅使用一个内核。C扩展(例如numpy)内部发生的I / O操作和计算可以同时进行。

Python的其他实现(例如Jython或PyPy)的行为可能有所不同,我不清楚它们的详细信息。

通常的建议是使用许多进程而不是许多线程。


2

线程共享一个进程,并且一个进程在内核上运行,但是您可以使用python的多处理模块在单独的进程中调用函数并使用其他内核,也可以使用子进程模块,后者也可以运行您的代码和非python代码。


2

示例代码在我的ubuntu 14.04,python 2.7 64位上采用了所有4个内核。

import time
import threading


def t():
    with open('/dev/urandom') as f:
        for x in xrange(100):
            f.read(4 * 65535)

if __name__ == '__main__':
    start_time = time.time()
    t()
    t()
    t()
    t()
    print "Sequential run time: %.2f seconds" % (time.time() - start_time)

    start_time = time.time()
    t1 = threading.Thread(target=t)
    t2 = threading.Thread(target=t)
    t3 = threading.Thread(target=t)
    t4 = threading.Thread(target=t)
    t1.start()
    t2.start()
    t3.start()
    t4.start()
    t1.join()
    t2.join()
    t3.join()
    t4.join()
    print "Parallel run time: %.2f seconds" % (time.time() - start_time)

结果:

$ python 1.py
Sequential run time: 3.69 seconds
Parallel run time: 4.82 seconds

2
因此,Parralel运行时间比顺序运行更糟糕:o
–sliders_alpha

1
在这里,您会失去上下文切换的机会。对您来说,真正的收益是,例如,您正在与Web服务交互,其中大部分时间都花在等待响应上。
chjortlund

我认为这只是异步的。不是pthread类型的线程。我的意思是,来自C pthread库的线程类型。
Fahim Ferdous

您将需要使用多处理库来完成您愿意做的事情
Fahim Ferdous

1

我将脚本转换为Python3并在Raspberry Pi 3B +上运行:

import time
import threading

def t():
        with open('/dev/urandom', 'rb') as f:
                for x in range(100):
                        f.read(4 * 65535)

if __name__ == '__main__':
    start_time = time.time()
    t()
    t()
    t()
    t()
    print("Sequential run time: %.2f seconds" % (time.time() - start_time))

    start_time = time.time()
    t1 = threading.Thread(target=t)
    t2 = threading.Thread(target=t)
    t3 = threading.Thread(target=t)
    t4 = threading.Thread(target=t)
    t1.start()
    t2.start()
    t3.start()
    t4.start()
    t1.join()
    t2.join()
    t3.join()
    t4.join()
    print("Parallel run time: %.2f seconds" % (time.time() - start_time))

python3 t.py

Sequential run time: 2.10 seconds
Parallel run time: 1.41 seconds

对我来说,并行运行更快。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.