我使用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
答案 0 :(得分:6)
这至少是一个可能的时间来源:
如果你不向odeint
(即LSODA)提供雅可比行列式,它将尝试通过有限差分来计算它。此外,如果它认为问题是僵硬的,它可能会试图将雅可比变换为O(m ^ 3)。当变量数量很大时,这两个步骤都很昂贵。
您可以尝试通过将odeint
和ml
参数的适当值传递给例程来强制mu
使用带状雅可比行列式来减少这些操作所花费的时间。您不需要提供Dfun,这些参数也适用于通过区分计算的雅可比。
答案 1 :(得分:2)
一千万个方程式是一个非平凡的数字。
为什么你说它“可怕地扩展”?对于m x m个matricies,矩阵加法为O(m^2)
,乘法为O(m^3)
。你引用两个时间点与方程式/自由度相对应,但这只能描述一条直线。我会在4K和10M之间选择几个中间点,看看Big-Oh符号是否显示它是如何缩放的。将结果拟合为壁面时间与DOF的三阶多项式;这会告诉你事情是如何扩展的。
你的方程是线性的还是非线性的?静态还是瞬态?根据问题的类型,您可以使用其他一些参数,如时间步长,收敛标准,集成方案选择等。