如何从3维的sympy表达式中获得快速的lambda函数? [英] How to get a fast lambda function from an sympy expression in 3 dimensions?

查看:93
本文介绍了如何从3维的sympy表达式中获得快速的lambda函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用sympy为cfd模拟生成不同的表达式. 通常,这些表达式的类型为exp = f(x,y,z) f(x,y,z)= sin(x)* cos(y)* sin(z).为了在网格上获取值,我使用simpy.lambdify. 例如:

I am using sympy to generate different expressions for cfd-simulations. Mostly these expressions are of the kind exp = f(x,y,z) for example f(x,y,z) = sin(x)*cos(y)*sin(z). To get values on a grid I use simpy.lambdify. For example:

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

这似乎工作得很好,但不幸的是我的表达式越来越复杂,网格计算要花很多时间. 我的想法是,可能可以使用uFuncify方法 (请参见 http://docs.sympy.org/latest/modules/numeric-computation.html) 加快计算速度,我不确定这是否是正确的方法? 而且我还不确定如何为3d网格工作. 感谢您的任何建议

This seems to work pretty good but unfortunately my expressions are getting more and more complex and the grid computation takes a lot of time. My Idea was that it is maybe possible to use the uFuncify method (see http://docs.sympy.org/latest/modules/numeric-computation.html ) to speed the computations up, im not sure if this is the right way ? And im also not sure how to get ufunctify to work for 3d grids ? Thanks for any Suggestions

推荐答案

在以前的版本(0.7.5和更早版本)中,ufuncify仅对第一个参数的单维数组起作用(不是很令人兴奋).从0.7.6开始(尚未发布,但应该在一周内!)默认情况下,ufuncify创建 actual 实例(在numpy api中包装C代码).您上面的代码仅需进行很小的更改即可使其工作.

In previous releases (0.7.5 and prior), ufuncify only worked on single dimension arrays for the first argument (not very exciting). As of 0.7.6 (not released yet, but should be in a week!) ufuncify creates actual instances of numpy.ufunc by default (wraps C code in numpy api). Your code above only needs a small change to make it work.

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

ufuncifytheano_function是可比的,并且对于此简单表达式而言,其速度比lambdify稍快.使用下面给出的更复杂的表达式,差异会更大:

ufuncify and theano_function are comparable, and slightly faster than lambdify for this simple expression. The difference is greater using the more complicated expression given below:

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

与使用python版本相比,这快了 ,因为没有创建任何中间数组,遍历了循环,并且在C中运行了计算.Theano产生了相等的速度,因为它们也可以编译为本机代码.对于执行多体动力学ufuncify(和相关的autowrap)的执行速度显着快于lambdify.我没有theano的丰富经验,所以我也不能说他们的方法的扩展性如何,但是我认为它会很相似.

This is much faster than using the python version, as no intermediate arrays are created, the loop is traversed and the calculation ran in C. Theano produces equivalent speeds, as they also compile to native code. For the large expressions that I see when doing multibody dynamics, ufuncify (and the related autowrap) perform significantly faster than lambdify. I don't have much experience with theano, so I can't say how well their approach scales either, but I'd assume it would be similar.

正如我上面所说,这仅在sympy 0.7.6及更高版本中可用.应该会很快发布,但是在那之前,您可以从 github 中获取源代码.可以在此处找到有关ufuncify新行为的文档

As I said above, this is only available in sympy 0.7.6 and up. Should be released soon, but until then you can grab the source from github. Docs on ufuncify new behavior can be found here

这篇关于如何从3维的sympy表达式中获得快速的lambda函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆