python - 在 RK4 算法中使用 lambda 函数

标签 python performance optimization runge-kutta

在 Python 中有两种实现经典 Runge-Kutta 方案的方法显示 here .第一个使用 lambda 函数,第二个不使用它们。

哪个会更快,为什么?

最佳答案

我修改了给定链接中的代码,并使用了 cProfile比较这两种技术:

import numpy as np
import cProfile as cP

def theory(t):
    return (t**2 + 4.)**2 / 16.

def f(x, y):
    return x * np.sqrt(y)

def RK4(f):
    return lambda t, y, dt: (
            lambda dy1: (
            lambda dy2: (
            lambda dy3: (
            lambda dy4: (dy1 + 2*dy2 + 2*dy3 + dy4)/6
                      )( dt * f( t + dt  , y + dy3   ) )
                      )( dt * f( t + dt/2, y + dy2/2 ) )
                      )( dt * f( t + dt/2, y + dy1/2 ) )
                      )( dt * f( t       , y         ) )


def test_RK4(dy=f, x0=0., y0=1., x1=10, n=10):
    vx = np.empty(n+1)
    vy = np.empty(n+1)
    dy = RK4(f=dy)
    dx = (x1 - x0) / float(n)
    vx[0] = x = x0
    vy[0] = y = y0
    i = 1
    while i <= n:
        vx[i], vy[i] = x + dx, y + dy(x, y, dx)
        x, y = vx[i], vy[i]
        i += 1
    return vx, vy


def rk4_step(dy, x, y, dx):
    k1 = dx * dy(x, y)
    k2 = dx * dy(x + 0.5 * dx, y + 0.5 * k1)
    k3 = dx * dy(x + 0.5 * dx, y + 0.5 * k2)
    k4 = dx * dy(x + dx, y + k3)
    return x + dx, y + (k1 + k2 + k2 + k3 + k3 + k4) / 6.


def test_rk4(dy=f, x0=0., y0=1., x1=10, n=10):
    vx = np.empty(n+1)
    vy = np.empty(n+1)
    dx = (x1 - x0) / float(n)
    vx[0] = x = x0
    vy[0] = y = y0
    i = 1
    while i <= n:
        vx[i], vy[i] = rk4_step(dy=dy, x=x, y=y, dx=dx)
        x, y = vx[i], vy[i]
        i += 1
    return vx, vy

cP.run("test_RK4(n=10000)")
cP.run("test_rk4(n=10000)")

得到:

         90006 function calls in 0.095 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.095    0.095 <string>:1(<module>)
    40000    0.036    0.000    0.036    0.000 untitled1.py:13(f)
        1    0.000    0.000    0.000    0.000 untitled1.py:16(RK4)
    10000    0.008    0.000    0.086    0.000 untitled1.py:17(<lambda>)
    10000    0.012    0.000    0.069    0.000 untitled1.py:18(<lambda>)
    10000    0.012    0.000    0.048    0.000 untitled1.py:19(<lambda>)
    10000    0.009    0.000    0.027    0.000 untitled1.py:20(<lambda>)
    10000    0.009    0.000    0.009    0.000 untitled1.py:21(<lambda>)
        1    0.009    0.009    0.095    0.095 untitled1.py:28(test_RK4)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
        2    0.000    0.000    0.000    0.000 {numpy.core.multiarray.empty}


         50005 function calls in 0.064 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.064    0.064 <string>:1(<module>)
    40000    0.032    0.000    0.032    0.000 untitled1.py:13(f)
    10000    0.026    0.000    0.058    0.000 untitled1.py:43(rk4_step)
        1    0.006    0.006    0.064    0.064 untitled1.py:51(test_rk4)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
        2    0.000    0.000    0.000    0.000 {numpy.core.multiarray.empty}

所以我会说 function call overhead在“lambda”实现中使其变慢。

尽管如此,请注意我似乎以某种方式失去了一些精确度,因为尽管彼此一致,但结果比示例中的结果更不准确:

>>> vx, vy = test_rk4()
>>> vy
array([   1.        ,    1.56110667,    3.99324757, ...,  288.78174798,
        451.27952013,  675.64427775])
>>> vx, vy = test_RK4()
>>> vy
array([   1.        ,    1.56110667,    3.99324757, ...,  288.78174798,
        451.27952013,  675.64427775])

关于python - 在 RK4 算法中使用 lambda 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41470860/

相关文章:

java - 加速大量 Random.nextint 调用

c++ - 如何提高与 std::vector 共享内存的数据映射(Eigen::Map)矩阵的 GEMM 性能?

c - 我需要减少项目中使用的所有目标文件的文本段

python - 通过优化选择最佳行

c++ - 使用 -O0 时 g++ 在 undefined reference 处停止

python - 将 PySpark 数据框列从列表转换为字符串

python - 在 beautifulsoup 中编写干净的代码

performance - HTTP 请求与文件大小?

Python 的 readline() 函数似乎不起作用?

Python 为随机选择的单词定义一个 Action