文章目录
- 一、简介
- 二、安装
- 三、函数详解
- 四、性能评估
Python 性能优化:NumExpr + Numba + CuPy
一、简介
numexpr(全称:numpy expression)
:用于在 NumPy 表达式上快速执行元素级运算的 Python 加速库。
- 优势:将表达式转换为高效的机器码,然后在内部优化执行并行计算。
- 利用多核处理器并行计算:在计算表达式时并行执行操作,从而加快计算速度。
- 基于缓存的内存管理策略:在计算过程中,避免创建临时数组来减少内存占用。
- 局限性:只有在处理大型数据集时,才会比标准的 NumPy 表达式速度更快;
- 适用范围:只适用于 NumPy 表达式;
表达式:是由变量、运算符和函数组成的符号序列,用于表示计算过程或计算结果。如:
"(a**2 + b**2) / (a + b + 1e-10)"
变量
:表示数据或值的符号,可以是数值、字符串、布尔值等。运算符
:如:算术运算符、逻辑运算符、比较运算符等。Python运算符函数
:如:数学函数、三角函数等。Python函数
二、安装
- pip安装:
pip install numexpr
- conda安装:
conda install numexpr
三、函数详解
"""#####################################################################################################################
# 函数功能:用于在 NumPy 表达式上快速执行元素级运算的 Python 加速库。
# 函数说明:numexpr.evaluate(expression, local_dict=None, global_dict=None, out=None, order='K', casting='safe', **kwargs)
# 参数说明:
# expression (str): 要评估的数学表达式。
# local_dict (dict, optional): 本地命名空间中的变量字典。
# global_dict (dict, optional): 全局命名空间中的变量字典。
# out (ndarray, optional): 结果存储的数组。若提供,则结果存储在该数组中。
# order (str, optional): 数组存储顺序。如:'C'(行优先)、'F'(列优先)、'K'(与数组的存储顺序相同)。
# casting (str, optional): 指定如何处理数据类型转换,如:'no'(不允许转换)、'equiv'(仅当转换安全)、'safe'(只允许安全转换)。
# **kwargs:其他参数传递给底层的 numexpr 引擎。
# 返回参数:
# out (ndarray): 若提供,则返回结果数组;否则返回一个新的数组。
#####################################################################################################################"""
四、性能评估
NumExpr简介
import time
import numpy as np
import numexpr
import matplotlib.pyplot as plt
def compare_performance():
numexpr_times = []
numpy_times = []
ns = range(10, 500, 10)
for n in ns:
# 生成表达式
np.random.seed(0)
a = np.random.rand(n, n, n)
b = np.random.rand(n, n, n)
expression = "(a**2 + b**2) / (a + b + 1e-10)"
# 使用numexpr计算
start_time = time.time()
x_numexpr = numexpr.evaluate(expression)
numexpr_time = time.time() - start_time
numexpr_times.append(numexpr_time)
# 使用numpy计算
start_time = time.time()
x_numpy = (a ** 2 + b ** 2) / (a + b + 1e-10)
numpy_time = time.time() - start_time
numpy_times.append(numpy_time)
print(f"n={n}: numexpr_time={numexpr_time:.5f} seconds, numpy_time={numpy_time:.5f} seconds")
plt.figure(figsize=(10, 6))
plt.plot(ns, numexpr_times, marker='o', label='numexpr')
plt.plot(ns, numpy_times, marker='o', label='numpy')
plt.title('Performance Comparison of numexpr vs numpy')
plt.xlabel('Three-dimensional array [n, n, n]')
plt.ylabel('Time (seconds)')
plt.legend()
plt.grid(True)
plt.show()
if __name__ == "__main__":
compare_performance()
不循环调用:三维数组 = [1000, 1000, 1000]
import time
import numpy as np
# 创建大型数据集
np.random.seed(0)
n = 1000
a = np.random.rand(n, n, n) # 三维数组:100x100x100
b = np.random.rand(n, n, n) # 三维数组:100x100x100
expression = "(a**2 + b**2) / (a + b + 1e-10)"
# (1)使用 numexpr 评估表达式
import numexpr
start_time = time.time()
x_numexpr = numexpr.evaluate(expression)
print(f"numexpr时耗: {time.time() - start_time:.5f} 秒")
# (2)直接使用 Python 原生操作计算
start_time = time.time()
x_python = (a ** 2 + b ** 2) / (a + b + 1e-10)
print(f"Python 时耗: {time.time() - start_time:.5f} 秒")
print(f"结果是否一致: {np.allclose(x_numexpr, x_python)}")
"""
numexpr时耗: 0.97169 秒
Python 时耗: 9.74043 秒
两种方法计算结果是否一致: True
"""