Skip to main content

NumPy 的快速数值表达式求值器

项目描述

作者:

David M. Cooke、Francesc Alted 等。

维护者:

罗伯特·A·麦克劳德

联系方式:
robbmcleod @ gmail 。com
网址:

https://github.com/pydata/numexpr

文档:

http://numexpr.readthedocs.io/en/latest/

特拉维斯 CI :

特拉维斯

GitHub 操作:

行动

皮皮:

版本

DOI :

土井

阅读文档:

文档

什么是 NumExpr?

NumExpr 是 NumPy 的快速数值表达式求值器。有了它,与在 Python 中执行相同计算相比,对数组(如'3*a+4*b')进行操作的表达式得到加速并使用更少的内存。

此外,它的多线程功能可以利用您的所有内核——与 NumPy 相比,这通常会导致显着的性能扩展。

最后但同样重要的是,numexpr 可以利用英特尔的 VML(向量数学库,通常集成在其数学内核库或 MKL)中。这允许进一步加速超越表达。

NumExpr 如何实现高性能

NumExpr 获得比 NumPy 更好的性能的主要原因是它避免为中间结果分配内存。这会导致更好的高速缓存利用率并总体上减少内存访问。因此,NumExpr 最适用于大型数组。

NumExpr 将表达式解析为自己的操作码,然后由集成计算虚拟机使用。数组操作数被分成小块,这些小块很容易放入 CPU 的缓存中并传递给虚拟机。然后虚拟机对每个块应用这些操作。值得注意的是,表达式中的所有临时变量和常量也是分块的。块分布在 CPU 的可用内核中,从而实现高度并行的代码执行。

结果是 NumExpr 可以充分利用您的机器计算能力进行数组计算。NumPy 的常见加速通常在 0.95 倍(对于非常简单的表达式,如 'a + 1')和 4 倍(对于相对复杂的表达式'a*b-4.1*a > 2.5*b',如在某些情况下)。

NumExpr 在太大而无法放入 L1 CPU 缓存的矩阵上表现最佳。为了更好地了解可以在您的平台上实现的不同加速,请运行提供的基准测试。

安装

从轮子

NumExpr 可通过pip安装,适用于各种平台和 Python 版本(可在以下位置浏览:https ://pypi.org/project/numexpr/#files )。安装可以如下执行:

pip install numexpr

如果您使用 Python 的 Anaconda 或 Miniconda 发行版,您可能更喜欢在这种情况下使用conda包管理器:

conda install numexpr

从源头

在大多数Nix 系统上,您的编译器已经存在。但是,如果您使用的虚拟环境的 Python 版本比系统 Python 版本要新得多,系统可能会提示您安装新版本的 `gcc或clang。

对于 Windows,您需要先安装 Microsoft Visual C++ Build Tools(免费)。版本取决于您安装的 Python 版本:

https://wiki.python.org/moin/WindowsCompilers

对于 Python 3.6+,只需安装最新版本的 MSVC 构建工具就足够了。请注意,通过 pip 找到的轮子不包括 MKL 支持。如果 MKL 后端用于 NumPy,则通过conda可用的轮子将具有 MKL。

有关所需版本的 NumPy,请参阅requirements.txt。

NumExpr 以标准 Python 方式构建:

python setup.py build install

您可以使用以下方法测试numexpr:

python -c "import numexpr; numexpr.test()"

不要在源目录中测试 NumExpr,否则会产生导入错误。

启用英特尔® MKL 支持

NumExpr 包括对 Intel 的 MKL 库的支持。这可能会在英特尔架构上提供更好的性能,主要是在评估超越函数(三角函数、指数函数……)时。

如果您有 Intel 的 MKL,请将分发包随附的 site.cfg.example 复制到site.cfg并编辑后一个文件以提供系统中 MKL 库的正确路径。完成此操作后,您可以继续执行上面列出的常规构建说明。

注意构建过程中的消息,以了解是否检测到 MKL。最后,您可以通过运行bench/vml_timing.py脚本来检查您机器上的加速(您可以在脚本中对set_vml_accuracy_mode()和set_vml_num_threads()函数使用不同的参数, 以了解它如何影响性能)。

用法

>>> import numpy as np
>>> import numexpr as ne

>>> a = np.arange(1e6)   # Choose large arrays for better speedups
>>> b = np.arange(1e6)

>>> ne.evaluate("a + 1")   # a simple expression
array([  1.00000000e+00,   2.00000000e+00,   3.00000000e+00, ...,
         9.99998000e+05,   9.99999000e+05,   1.00000000e+06])

>>> ne.evaluate('a*b-4.1*a > 2.5*b')   # a more complex one
array([False, False, False, ...,  True,  True,  True], dtype=bool)

>>> ne.evaluate("sin(a) + arcsinh(a/b)")   # you can also use functions
array([        NaN,  1.72284457,  1.79067101, ...,  1.09567006,
        0.17523598, -0.09597844])

>>> s = np.array([b'abba', b'abbb', b'abbcdef'])
>>> ne.evaluate("b'abba' == s")   # string arrays are supported too
array([ True, False, False], dtype=bool)

文档

请参阅numexpr.readthedocs.io上的官方文档。包括用户指南、基准测试结果和参考 API。

作者

请参阅AUTHORS.txt。

执照

NumExpr 在MIT许可下分发。

项目详情