jrs*_*rsm 7 python numpy sympy
我正在使用sympy为cfd模拟生成不同的表达式.这些表达式大多数是exp = f(x,y,z),例如f(x,y,z)= sin(x)*cos(y)*sin(z).要在网格上获取值,我使用simpy.lambdify.例如:
import numpy as np
import sympy as sp
from sympy.abc import x,y,z
xg, yg, zg = np.mgrid[0:1:50*1j, 0:1:50*1j, 0:1:50*1j]
f = sp.sin(x)*sp.cos(y)*sp.sin(z)
lambda_f = sp.lambdify([x,y,z], f, "numpy")
fn = lambda_f(xg, yg, zg)
print fn
Run Code Online (Sandbox Code Playgroud)
这似乎工作得很好但不幸的是我的表达式越来越复杂,网格计算需要花费很多时间.我的想法是,可能可以使用uFuncify方法(请参阅http://docs.sympy.org/latest/modules/numeric-computation.html)来加快计算速度,我不确定这是否是正确的方法?我也不知道如何让3d功能为3d网格工作?感谢您的任何建议
在之前的版本(0.7.5和之前版本)中,ufuncify仅针对第一个参数(单个维度数组)进行了第一个参数(不是非常令人兴奋).截至0.7.6(尚未发布,但应该在一周内!)ufuncify创建默认的实际实例numpy.ufunc(在numpy api中包装C代码).上面的代码只需要很小的改动就可以了.
In [1]: import numpy as np
In [2]: from sympy import sin, cos, lambdify
In [3]: from sympy.abc import x,y,z
In [4]: from sympy.utilities.autowrap import ufuncify
In [5]: from sympy.printing.theanocode import theano_function
In [6]: xg, yg, zg = np.mgrid[0:1:50*1j, 0:1:50*1j, 0:1:50*1j]
In [7]: f = sym.sin(x)*sym.cos(y)*sym.sin(z)
In [8]: ufunc_f = ufuncify([x,y,z], f)
In [9]: theano_f = theano_function([x, y, z], f, dims={x: 3, y: 3, z: 3})
In [10]: lambda_f = lambdify([x, y, z], f)
In [11]: type(ufunc_f)
Out[11]: numpy.ufunc
In [12]: type(theano_f)
Out[12]: theano.compile.function_module.Function
In [13]: type(lambda_f)
Out[13]: function
In [14]: %timeit ufunc_f(xg, yg, zg)
10 loops, best of 3: 21 ms per loop
In [15]: %timeit theano_f(xg, yg, zg)
10 loops, best of 3: 20.7 ms per loop
In [16]: %timeit lambda_f(xg, yg, zg)
10 loops, best of 3: 22.3 ms per loop
Run Code Online (Sandbox Code Playgroud)
ufuncify并且theano_function具有可比性,并且比lambdify这个简单的表达式略快.使用下面给出的更复杂的表达式,差异更大:
In [17]: f = sin(x)*cos(y)*sin(z) + sin(4*(x - y**2*sin(z)))
In [18]: ufunc_f = ufuncify([x,y,z], f)
In [19]: theano_f = theano_function([x, y, z], f, dims={x: 3, y: 3, z: 3})
In [20]: lambda_f = lambdify([x, y, z], f)
In [21]: %timeit ufunc_f(xg, yg, zg)
10 loops, best of 3: 29.2 ms per loop
In [22]: %timeit theano_f(xg, yg, zg)
10 loops, best of 3: 29.2 ms per loop
In [23]: %timeit lambda_f(xg, yg, zg)
10 loops, best of 3: 42.1 ms per loop
Run Code Online (Sandbox Code Playgroud)
这比使用python版本要快得多,因为没有创建中间数组,遍历循环并且计算在C中运行.Theano产生相同的速度,因为它们也编译为本机代码.对于我在进行多体动力学时看到的大表达式,ufuncify(和相关的autowrap)表现要快得多lambdify.我对theano没有多少经验,所以我不能说他们的方法有多好,但我认为它会是相似的.
正如我上面所说,这仅适用于0.7.6及更高版本.应尽快发布,但在此之前你可以从github获取源代码.有关ufuncify新行为的文档可以在这里找到