最快评估SymPy表达式数组:eval与lambify对比及向量化方案
问题描述
我有一个包含SymPy表达式的数组,示例如下:
np.Array([A + B, C + D - 2.0*E + 10, ...])
表达式会动态变化,且执行效率至关重要。我已掌握A、B、C、D等变量的取值,存储于字典中,变量值为可迭代对象,例如A = [1,2,3,4]。
请问:
- 评估每个表达式的最快方式是什么?
- eval与lambify哪个速度更快?
- 是否存在向量化实现方法?
解决方案
一、最快评估方式
优先使用SymPy的lambify结合NumPy向量化运算,这是此类场景下效率最高的方案之一。lambify能将SymPy表达式直接转换为NumPy兼容的函数,天然支持向量化输入,无需循环遍历数组中的每个表达式。
二、eval vs lambify速度对比
- lambify速度远快于eval:
- eval是通用的字符串解析执行工具,每次调用都要重新解析表达式,且无法利用NumPy的向量化优化,循环处理每个表达式时开销极大。
- lambify会预先将SymPy表达式编译为底层的NumPy(或其他后端如numba)函数,执行时直接调用编译后的代码,完全避开字符串解析的开销,还能充分利用CPU的向量化指令。
实测显示,处理批量可迭代变量时,lambify的执行速度通常是eval的几十到上百倍。
三、向量化实现方法
直接用lambify生成支持NumPy数组的函数,结合变量的数组形式实现全向量化计算,步骤如下:
- 定义SymPy符号和表达式数组:
import sympy as sp import numpy as np A_sym, B_sym, C_sym, D_sym, E_sym = sp.symbols('A B C D E') expr_array = np.array([A_sym + B_sym, C_sym + D_sym - 2.0*E_sym + 10])
- 生成批量计算的向量化函数:
# 直接生成处理整个表达式数组的函数(SymPy 1.9+支持) batch_func = sp.lambify((A_sym, B_sym, C_sym, D_sym, E_sym), expr_array, 'numpy')
- 传入字典中的变量(需转为NumPy数组):
var_dict = { 'A': np.array([1,2,3,4]), 'B': np.array([5,6,7,8]), 'C': np.array([9,10,11,12]), 'D': np.array([13,14,15,16]), 'E': np.array([17,18,19,20]) } # 全向量化计算所有表达式结果 results = batch_func(var_dict['A'], var_dict['B'], var_dict['C'], var_dict['D'], var_dict['E'])
如果追求极致性能,可结合numba后端编译机器码:
batch_func = sp.lambify((A_sym, B_sym, C_sym, D_sym, E_sym), expr_array, 'numba')
这种方式在大规模数据场景下能进一步提升计算速度。
内容的提问来源于stack exchange,提问作者Brayan Muñoz
相关产品推荐
相关产品推荐

