【发布时间】:2014-12-10 21:07:17
【问题描述】:
我有一个输入向量列表,我需要将其用作使用 SymPy 生成的函数列表的输入。在实际应用中,输入向量的数量约为 100k,符号函数集约为 5M。这是目前我的代码中的瓶颈,所以我正在努力加快速度。
我已经通过使用 Sympy 的 lambdify 创建基于 numpy 的 lambda 函数进行了重大改进,但我不禁想到有一种方法可以对其进行矢量化并将 for 循环放入 numpy/C 而不是 python。
我最初认为 numpy.apply_along_axis() 会有所帮助,但它仍然会在 python 中循环。
这是我现在正在做的简化版本:
import time
import sympy as sp
import numpy as np
#Input for performance testing
# sampleSize = 200000
# inputVector = [1.2, -0.33]
# inputArray = np.array(inputVector*np.ones((sampleSize,1)))
#This array would have ~100k rows in actual data set
inputArray = [[-.333, -.558],
[-.454, -.367],
[-.568, -.678]]
start = time.time()
#These are the equations of motion of a mechanical system. Each row represents
#a unique arrangement of components. There may be a better way to handle this,
#but I haven't understood the system well enough to do so yet.
#This array would have ~5M rows in actual data set
symEqns = [['(R_1 - 1)/(R_0 - 1)', '0', '-R_1 + 1', '(R_1 - 1)/(R_0*R_1 - 1)','1'],
['R_1/R_0', '0', '-1/(R_0 - 1)', '(R_1 - 1)/(R_0 - 1)', '1']]
for eqnSet in symEqns:
#Create lambda functions
lambdaFuncs = []
for eqn in eqnSet:
func = sp.lambdify(['R_0', 'R_1'], eqn, 'numpy')
#This is ~5x slower, due to use of pure python vs. numpy ??
# func = lambda R_0, R_1: eval(eqn)
lambdaFuncs.append(func)
#Evaluate each lambda func for each input set
# in my actual code, this is a parameter of an object. forgot to store it in my example code
outputList = []
for row in inputArray:
results = []
for func in lambdaFuncs:
results.append(func(*row))
outputList.append(results)
end = time.time()
print "\nTotal Time Elapsed: {:d}:{:0>5.2f}".format(int((end-start)/60), (end-start)%60)
如果有帮助,我还可以构建评估以独立计算每个函数,为每个函数创建一列结果。这是这种情况下评估块的示例(使用 for 循环进行说明,我想使用 numpy 进行矢量化评估):
#Evaluate each lambda func for each input set
outputList = []
for func in lambdaFuncs:
results = []
for row in inputArray:
results.append(func(*row))
outputList.append(results)
[编辑] 供将来参考,这是我针对此问题改进的工作示例代码。我从 Oliver 的回复中调整了一些东西,主要是允许可变长度的输入向量:
import time
import sympy as sp
import numpy as np
# This array would have ~100k rows in actual data set
input_array = np.array([[-.333, -.558],
[-.454, -.367],
[-.568, -.678]])
#This array would have ~5M rows in actual data set (generated via Sympy linear algebraic solns)
sym_eqns = [['(R_1 - 1)/(R_0 - 1)', '0', '-R_1 + 1', '(R_1 - 1)/(R_0*R_1 - 1)','1'],
['R_1/R_0', '0', '-1/(R_0 - 1)', '(R_1 - 1)/(R_0 - 1)', '1']]
for eqn_set in sym_eqns:
output_list = []
for eqn in eqn_set:
func = sp.lambdify(['R_0', 'R_1'], eqn, 'numpy')
results = func(*[input_array[:,n] for n in range(input_array.shape[1])])
output_list.append(results)
【问题讨论】:
-
最好添加您的改进版本作为答案。
标签: python performance numpy lambda sympy