如何提高Python中odeint的速度?

时间:2011-06-10 09:04:21

标签: python performance scipy

我使用scipy包中的Python和odeint来解决大量(~10e6)耦合的ODE。方程组可以表示为一些矩阵乘法的总和,我使用numpy和blas支持。我的问题是这需要很长时间。当我分析代码时,我发现大部分时间都是在进行odeint做其他事情而不是评估rhs。这是来自探查器的五个最耗时的调用:

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
5       1547.915  309.583 1588.170  317.634 {scipy.integrate._odepack.odeint}
60597   11.535    0.000   23.751    0.000   terms3D.py:5(two_body_evolution)
121194  11.242    0.000   11.242    0.000   {numpy.core._dotblas.dot}
60597   10.145    0.000   15.460    0.000   generator.py:13(Gs2)
121203   3.615    0.000   3.615     0.000   {method 'repeat' of 'numpy.ndarray' objects}

rhs基本上由two_body_evolution和Gs2组成。这个配置文件适用于~7000耦合的ODE,这与~4000相同:

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
5        259.427  51.885   273.316  54.663 {scipy.integrate._odepack.odeint}
30832    3.809    0.000    7.864    0.000  terms3D.py:5(two_body_evolution)
61664    3.650    0.000    3.650    0.000  {numpy.core._dotblas.dot}
30832    3.464    0.000    5.637    0.000  generator.py:13(Gs2)
61673    1.280    0.000    1.280    0.000  {method 'repeat' of 'numpy.ndarray' objects}

所以我的主要问题是odeint中的“隐藏”时间与方程的数量可怕地成比例。您对此有什么想法以及如何提高性能吗?

感谢您的时间

OscarÅkerlund

2 个答案:

答案 0 :(得分:6)

这至少是一个可能的时间来源:

如果你不向odeint(即LSODA)提供雅可比行列式,它将尝试通过有限差分来计算它。此外,如果它认为问题是僵硬的,它可能会试图将雅可比变换为O(m ^ 3)。当变量数量很大时,这两个步骤都很昂贵。

您可以尝试通过将odeintml参数的适当值传递给例程来强制mu使用带状雅可比行列式来减少这些操作所花费的时间。您不需要提供Dfun,这些参数也适用于通过区分计算的雅可比。

答案 1 :(得分:2)

一千万个方程式是一个非平凡的数字。

为什么你说它“可怕地扩展”?对于m x m个matricies,矩阵加法为O(m^2),乘法为O(m^3)。你引用两个时间点与方程式/自由度相对应,但这只能描述一条直线。我会在4K和10M之间选择几个中间点,看看Big-Oh符号是否显示它是如何缩放的。将结果拟合为壁面时间与DOF的三阶多项式;这会告诉你事情是如何扩展的。

你的方程是线性的还是非线性的?静态还是瞬态?根据问题的类型,您可以使用其他一些参数,如时间步长,收敛标准,集成方案选择等。