为什么numpy计算不受全局解释器锁的影响?

时间:2016-04-07 14:24:39

标签: python multithreading numpy multiprocessing gil

我正在尝试决定是否应该使用多处理或线程,并且我已经学习了一些有关Global Interpreter Lock的有趣内容。在这个不错的blog post中,似乎多线程不适合繁忙的任务。但是,我还了解到一些功能,如I / O或numpy,不受GIL的影响。

任何人都可以解释为什么,以及我如何能够找出我的(可能非常重的)代码是否适合多线程?

1 个答案:

答案 0 :(得分:16)

许多 numpy计算不受GIL影响,但不是全部。

虽然在不需要Python解释器的代码(例如C库)中,可以专门发布GIL - 允许依赖于解释器的其他代码继续运行。在Numpy C代码库中,宏NPY_BEGIN_THREADSNPY_END_THREADS用于分隔允许GIL发布的代码块。您可以在this search of the numpy source中看到这些内容。

NumPy C API documentation提供了有关线程支持的更多信息。请注意处理条件GIL版本的其他宏NPY_BEGIN_THREADS_DESCRNPY_END_THREADS_DESCRNPY_BEGIN_THREADS_THRESHOLDED,这取决于数组dtypes和循环的大小。

大多数核心功能会释放GIL - 例如Universal Functions (ufunc)这样做as described

  

只要不涉及任何对象数组,就会在调用循环之前释放Python全局解释器锁(GIL)。如有必要,可以重新获取它以处理错误情况。

关于您自己的代码,source code for NumPy is available。检查上述宏使用的功能(以及它们调用的功能)。另请注意,性能优势在很大程度上取决于 GIL发布的时间< - >如果您的代码不断地进出Python,您将获得很多改进。

另一个选择就是测试它。但是,请记住,使用条件GIL宏的函数可能会对小型和大型数组表现出不同的行为。因此,使用小数据集的测试可能无法准确表示较大任务的性能。

有关numpy可用on the official wiki的并行处理的一些其他信息,以及关于Python GIL的有用帖子over on Programmers.SE