NumExpr是一个用于numpy类型快速数值表达式计算的第三方Python加速库。有了它, 在数组上操作的表达式(如3xa+4xb)相比在python中执行速度更快,所需内存空间占用更少。
值得一提的是,NumExpr集成了intel的vml(向量数学计算库 vectore math library)技术, 这使得数值型表达式的计算速度得到了进一步提升。
NumExpr获得比numpy更好的性能的主要原因是避免为中间结果分配内存,这样可以提高缓存利用率,减少内存访问。因此,NumExpr在处理大型数组时相比numpy效果最好。
我们可以通过conda或者pip来进行安装,命令如下:
$ conda install -c anaconda numexpr
或者
pip install numexpr
我们计算由两个向量a,b 组成的表达式 f 为例,来评估输入不同大小的两个向量下使用NumExpr和Numpy二者的性能差异。其中f表达式如下:
import numexpr as ne
from time import time
def timeIt_numpy(a, b, runs, loops):
output = np.zeros(runs)
for r in range(runs):
to = time()
for _ in range(loops):
current = 2*a**3 + 3*b**2
ti = time()
output[r] = ti - to
return output
上述代码实现了利用Numpy来计算表达式f的功能,其中:
a,b 代表输入的两个向量
runs 代表我们做几次对比实验
loops 代表每次实验表达式重复执行多少次,以方便我们统计时间
output 代表每次实验(即上述表达式执行loops次)所耗费的时间
def timeIt_numexpr(a, b, runs, loops):
output = np.zeros(runs)
for r in range(runs):
to = time()
for _ in range(loops):
current = ne.evaluate('2*a**3 + 3*b**2')
ti = time()
output[r] = ti - to
return output
上述代码实现了利用NumExpr来计算表达式f的功能,相关参数含义同上。这里需要注意的是,使用NumExpr来计算表达式的值,只需要将表达式写成:
current = ne.evaluate('2*a**3 + 3*b**2')
形式即可,对程序的修改及其简单。
这里为了直观对比输入不同size下的vector,统计两者的时间差异,使用matplotlib来画图显示,代码如下:
import matplotlib.pyplot as plt fig, ax = plt.subplots(1, 1, figsize=(16, 8)) N = 16 runs = 10 loops = 1000 time_numpy = np.zeros((runs, N)) time_numexpr = np.zeros((runs, N)) # Time for i in range(N): a = np.random.rand(2**(i + 1)) b = np.random.rand(2**(i + 1)) time_numpy[:,i] = timeIt_numpy(a, b, runs, loops) time_numexpr[:,i] = timeIt_numexpr(a, b, runs, loops) # Plot x = np.arange(N) mu = np.mean(time_numpy, axis=0) ax.plot(mu, label="NumPy") x = np.arange(N) mu = np.mean(time_numexpr, axis=0) ax.plot(mu, label="NumExpr") ax.set_xlabel('N') ax.set_xticks(x) ax.set_xticklabels([f'$2^{{{e + 1}}}$'for e in range(N)]) ax.set_ylabel('time in seconds for each run') ax.set_title(f'runs = {runs} | loops = {loops}') ax.legend() plt.show()
代码含义如下:
N 代表一共输入16组不同大小size的向量,每次实验输入向量的size为[2^1, 2^2 … 2^16]
runs 代表每组向量,进行10次实验
loops 代表表达式执行1000次,方便我们统计表达式执行耗时
在代码中使用NumExpr的好处:
联系客服