1.14。线程层

原文: http://numba.pydata.org/numba-doc/latest/user/threading-layer.html

本节是关于 Numba 线程层,这是在内部用于执行通过使用 CPU 的parallel目标而发生的并行执行的库,即:

  • @jit@njit中使用parallel=True kwarg。
  • @vectorize@guvectorize中使用target='parallel' kwarg。

注意

如果代码库不使用threadingmultiprocessing模块(或任何其他类型的并行),Numba 附带的线程层的默认值将运行良好,无需进一步操作!

1.14.1。哪些线程层可用?

有三个可用的线程层,它们的名称如下:

  • tbb - 由英特尔 TBB 支持的线程层。
  • omp - 由 OpenMP 支持的线程层。
  • workqueue - 一个简单的内置工作共享任务调度程序。

实际上,保证存在的唯一螺纹层是workqueueomp层需要存在合适的 OpenMP 运行时库。 tbb层需要存在 Intel 的 TBB 库,这些库可以通过 conda 命令获得:

  1. $ conda install tbb

如果您使用pip安装 Numba,可以通过运行以下命令启用 TBB:

  1. $ pip install tbb

由于 manylinux1 的兼容性问题和其他可移植性问题,在 PyPI 上的 Numba 二进制轮中禁用了 OpenMP 线程层。

注意

Numba 搜索并加载线程层的默认方式是容忍缺少库,不兼容的运行时等。

1.14.2。设置穿线层

通过环境变量NUMBA_THREADING_LAYER或通过赋值给numba.config.THREADING_LAYER设置线程层。如果使用设置线程层的编程方法,则必须在逻辑上在发生并行目标的任何基于 Numba 的编译之前进行。选择线程层有两种方法,第一种是选择在各种形式的并行执行下安全的线程层,第二种是通过线程层名称进行显式选择(例如tbb)。

1.14.2.1。选择安全并行执行的线程层

并行执行从根本上以四种形式从核心 Python 库派生(前三个也适用于通过其他方式使用并行执行的代码!):

  • 来自threading模块的threads
  • 来自multiprocessing模块spawnspawn进程(Windows 上的默认值,仅适用于 Unix 上的 Python 3.4+)
  • fork来自multiprocessing模块的进程通过fork(在 Unix 上是默认的,也是 Unix 上 Python 2 的唯一选项)。
  • fork来自multiprocessing模块的进程通过使用forkserver(仅在 Unix 上的 Python 3 中可用)。基本上产生了一个新的过程,然后根据要求从这个新过程中生成叉子。

任何与这些形式的并行性一起使用的库必须在给定范例下表现出安全行为。因此,线程层选择方法旨在提供一种方法,以简单,跨平台和环境容忍的方式选择对给定范例安全的线程层库。可以提供给设置机制的选项如下:

  • default没有提供特定的安全保证,是默认设置。
  • safe是分叉和线程安全的,这需要安装tbb软件包(Intel TBB 库)。
  • forksafe提供了一个 fork 安全库。
  • threadsafe提供了一个线程安全的库。

要发现所选的线程层,可以在并行执行后调用函数numba.threading_layer()。例如,在没有安装 TBB 的 Linux 机器上:

  1. from numba import config, njit, threading_layer
  2. import numpy as np
  3. # set the threading layer before any parallel target compilation
  4. config.THREADING_LAYER = 'threadsafe'
  5. @njit(parallel=True)
  6. def foo(a, b):
  7. return a + b
  8. x = np.arange(10.)
  9. y = x.copy()
  10. # this will force the compilation of the function, select a threading layer
  11. # and then execute in parallel
  12. foo(x, y)
  13. # demonstrate the threading layer chosen
  14. print("Threading layer chosen: %s" % threading_layer())

产生:

  1. Threading layer chosen: omp

这是有道理的,因为在 Linux 上存在的 GNU OpenMP 是线程安全的。

1.14.2.2。选择命名的线程层

高级用户可能希望为其用例选择特定的线程层,这可以通过直接向设置机制提供线程层名称来完成。选项和要求如下:

线程层名称 平台 要求
tbb 所有 tbb包($ conda install tbb
omp Linux 的视窗 OSX GNU OpenMP 库(很可能已经存在)MS OpenMP 库(很可能已经存在)intel-openmp包($ conda install intel-openmp
workqueue 所有 没有

如果线程层未正确加载,Numba 将检测到这一点,并提供有关如何解决问题的提示。还应注意,Numba 诊断命令numba -s有一个__Threading Layer Information__部分,用于报告当前环境中线程层的可用性。

1.14.3。额外说明

线程层与 CPython 内部和系统级库的交互相当复杂,还需要注意一些其他事项:

  • 英特尔 TBB 库的安装极大地拓宽了线程层选择过程中可用的选项。
  • 在 Linux 上,omp线程层不是 fork 安全的,因为 GNU OpenMP 运行时库(libgomp)不是 fork 安全的。如果在使用omp线程层的程序中发生 fork,则会出现一种检测机制,它将尝试并正常终止分叉子项并将错误消息打印到STDERR
  • 在 OSX 上,需要intel-openmp包来启用基于 OpenMP 的线程层。
  • 对于运行 Python 2.7 的 Windows 用户,tbb线程层不可用。