numpy 加速渐近化和向量化函数

1szpjjfi  于 2023-05-17  发布在  其他
关注(0)|答案(2)|浏览(146)

我正在使用sympy生成一些用于数值计算的函数。因此,我对一个表达式进行lambdify化和向量化,以便在numpy数组中使用它。下面是一个例子:

import numpy as np
import sympy as sp

def numpy_function():
    x, y, z = np.mgrid[0:1:40*1j, 0:1:40*1j, 0:1:40*1j]
    T   = (1 - np.cos(2*np.pi*x))*(1 - np.cos(2*np.pi*y))*np.sin(np.pi*z)*0.1
    return T

def sympy_function():
    x, y, z = sp.Symbol("x"), sp.Symbol("y"), sp.Symbol("z")
    T   = (1 - sp.cos(2*sp.pi*x))*(1 - sp.cos(2*sp.pi*y))*sp.sin(sp.pi*z)*0.1
    lambda_function = np.vectorize(sp.lambdify((x, y, z), T, "numpy"))
    x, y, z = np.mgrid[0:1:40*1j, 0:1:40*1j, 0:1:40*1j]
    T = lambda_function(x,y,z)
    return T

sympy版本和纯numpy版本之间的问题是速度,即。

In [3]: timeit test.numpy_function()  
100 loops, best of 3: 11.9 ms per loop

对比

In [4]: timeit test.sympy_function()
1 loops, best of 3: 634 ms per loop

那么有没有什么方法可以更接近numpy版本的速度呢?我认为np.vectorize非常慢,但不知何故,我的代码的某些部分没有它就无法工作。谢谢你的任何建议。

EDIT:所以我找到了vectorize函数是必要的原因,即:

In [35]: y = np.arange(10)

In [36]: f = sp.lambdify(x,sin(x),"numpy")

In [37]: f(y)
Out[37]: 
array([ 0.        ,  0.84147098,  0.90929743,  0.14112001, -0.7568025 ,
       -0.95892427, -0.2794155 ,  0.6569866 ,  0.98935825,  0.41211849])

但这似乎工作得很好:

In [38]: y = np.arange(10)

In [39]: f = sp.lambdify(x,1,"numpy")

In [40]: f(y)
Out[40]: 1

所以对于像1这样的简单表达式,这个函数不返回数组。有没有办法解决这个问题,这是不是某种bug,或者至少是不一致的设计?

thigvfpy

thigvfpy1#

lambdify为常量返回单个值,因为不涉及numpy函数。这是因为lambdify的工作方式(参见https://stackoverflow.com/a/25514007/161801)。
但这通常不是问题,因为常量将自动广播到与数组一起使用的任何操作中的正确形状。另一方面,如果你显式地使用一个具有相同常量的数组,那么效率会低得多,因为你会多次计算相同的操作。

cu6pst1q

cu6pst1q2#

在这种情况下使用np.vectorize()就像在xyz的第一维上循环,这就是为什么它会变慢。你不需要np.vectorize()如果你告诉lambdify()使用NumPy的函数,这正是你正在做的。然后,使用:

def sympy_function():
    x, y, z = sp.Symbol("x"), sp.Symbol("y"), sp.Symbol("z")
    T   = (1 - sp.cos(2*sp.pi*x))*(1 - sp.cos(2*sp.pi*y))*sp.sin(sp.pi*z)*0.1
    lambda_function = sp.lambdify((x, y, z), T, "numpy")
    x, y, z = np.mgrid[0:1:40*1j, 0:1:40*1j, 0:1:40*1j]
    T = lambda_function(x,y,z)
    return T

使性能具有可比性:

In [26]: np.allclose(numpy_function(), sympy_function())
Out[26]: True

In [27]: timeit numpy_function()
100 loops, best of 3: 4.08 ms per loop

In [28]: timeit sympy_function()
100 loops, best of 3: 5.52 ms per loop

相关问题