NumExpr是NumPy的快速数值表达式求值器。NumExpr对使用表达式(如3*a+4*b)进行计算,并且比在Python中执行相同的计算使用更少的内存。
NumExpr 基础使用
NumExpr拥有更好的性能的主要原因是它避免了为中间结果分配内存,这导致减少一般的内存访问。因此NumExpr最适用于大型数组。
安装方法:
pip install numexpr
使用案例:
import numpy as np import numexpr as ne
a = np.random.rand(10000)
b = np.random.rand(10000)
# 等同于 2*a + b10 ne.evaluate("2*a + b10")
NumExpr 数据格式
NumExpr仅在内部使用以下类型运行:
- 8 位布尔值 (bool)
- 32 位有符号整数(int 或 int32)
- 64 位有符号整数(long 或 int64)
- 32 位单精度浮点数(float 或 float32)
- 64 位双精度浮点数(double 或 float64)
- 2x64 位双精度复数(complex 或 complex128)
- 原始字节串 (str)
如果表达式中的数组不匹配这些类型中的任何一种,它们将被向上转换为上述类型之一.
NumExpr 运算符
NumExpr 支持下面列出的一组运算符:
- Logical operators: &, |, ~
- Comparison operators: <, <=, ==, !=, >=, >
- Unary arithmetic operators: -
- Binary arithmetic operators: +, -, *, /, , %, <<, >>
NumExpr 函数运算
NumExpr 支持下列内置函数:
- where
- sin,cos,tan
- arcsin,arccos,arctan
- arctan2
- sinh,cosh,tanh
- arcsinh,arccosh,arctanh
- log,log10,log1p
- exp,expm1
- conj,real,imag,complex
- contains
NumExpr 使用案例
num = 10000 a = np.random.rand(num)
b = np.random.rand(num)
_ = 2*a + b10 + np.log(a) * np.log(b)
_ = ne.evaluate("2*a + b10 + log(a) * log(b)")
num = 10000 a = np.random.rand(num)
b = np.random.rand(num)
_ = 2*a + b10 + np.abs(a)
_ = ne.evaluate("2*a + b10 + abs(a)")
num = 10000 a = np.random.rand(num)
b = np.random.rand(num)
_ = 2*a + b10 + a*b
_ = ne.evaluate("2*a + b10 + a*b")
num = 10000 a = np.random.rand(num).astype(int16)
b = np.random.rand(num).astype(int16)
_ = 2*a + b10 + a*b
_ = ne.evaluate("2*a + b10 + a*b")
num = 10000 a = np.random.rand(num).astype(int32)
b = np.random.rand(num).astype(int32)
_ = 2*a + b10 + a*b
_ = ne.evaluate("2*a + b10 + a*b")
num = 10000 a = np.random.rand(num).astype(np.bool8)
b = np.random.rand(num).astype(np.bool8)
_ = a | b
_ = ne.evaluate("a | b")
NumExpr 使用总结
-
NumExpr支持基础的运算加速,且对32位浮点数加速比较明显,但对不同的格式有不同的加速比。
-
NumExpr只支持基础的运算函数,复杂的运算(如循环和索引)逻辑并不支持。
-
在数据量比较小的情况下,NumExpr加速并不明显。且在不同机器,需要设置不同的进程数。