我一直在使用sympy
来处理微分方程组。我象征性地编写方程,使用autowrap
通过cython编译它们,然后将结果函数传递给scipy ODE求解器。这样做的一个主要好处是我可以使用sympy jacobian
函数象征性地解析jacobian,编译它,并将它也解释为ODE求解器。
这对于大约30个变量的系统来说非常有用。最近我尝试用150个变量来做,发生的事情是我在编译jacobian函数时耗尽了内存。这是在Windows上使用anaconda和用于python的Microsoft Visual C ++ 14工具。基本上在编译jacobian时,它现在是一个22000个元素的向量,在链接步骤中的内存使用量上升到大约7GB(在我的8GB笔记本电脑上),然后最终崩溃。
在我去尝试拥有更多内存的机器之前,有人有一些建议吗?其他操作系统或其他C编译器是否可能改善这种情况?
我知道很多人都会做这类工作,所以如果有答案的话,这对社区的一大块人来说都是有益的。
编辑:回应Jonathan的一些评论:
是的,我完全清楚这是一个N ^ 2问题。雅可比是所有偏导数的矩阵,因此它的大小为N ^ 2。这种扩展没有真正的方法。但是,一个22000个元素的数组几乎没有在运行时产生内存问题的水平 - 我只在编译期间遇到问题。
基本上我们有三个层次可以解决这个问题。
1)在没有jacobian的情况下解决ODE问题,或者以某种方式将jacobian拆分为不具有150x150矩阵。这将解决根本问题,但它肯定限制了我能做的事情,而且我还不相信编译雅可比函数是不可能的
2)改变sympy
自动生成C代码的方式,将其拆分为多个块,为中间表达式使用更多函数,以某种方式使.c文件更小。有更多同情经验的人可能对此有一些想法。
3)改变编译C的方式,这样就需要更少的内存。
我认为通过发布一个更加面向#3(literal referencing of large array -- compiler out of memory)的单独问题,我会得到不同的受众回答。事实上,这正是发生的事情。也许#3的答案是"你不能"#34;但这也是有用的信息。
答案 0 :(得分:0)
根据http://www.sympy.org/scipy-2017-codegen-tutorial/发布的大量示例,我能够将其编译好。
关键是
1)而不是使用autowrap
,直接编写C代码并对其进行更多控制。除此之外,这允许将参数列表作为向量传递而不是扩展它。这需要一些努力才能工作(通过distutils等设置编译器标志等),但最终它运行良好。将上面链接的课程回购作为一个例子有很大帮助。
2)使用公共子表达式消除(sympy.cse
)来显着减小jacobian元素的表达式的大小。
(1)在这种情况下,它本身并没有那么多帮助(虽然我能够用它来大大提高小型号的性能)。代码仍然是200 MB而不是原来的300 MB。但是将它与(2)(cse
)结合起来,我能够将其降低到1.7 MB(尽管有14000个临时变量)。
我的笔记本电脑上cse
大约需要20-30分钟。之后,它会很快编译。