NumPy 的快速数值表达式求值器
项目描述
- 维护者:
罗伯特·A·麦克劳德
- 联系方式:
- robbmcleod @ gmail 。com
- 网址:
- 文档:
- 特拉维斯 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。
执照
NumExpr 在MIT许可下分发。