使用PyPy或Cython来加快fsolve的循环速度?

问题描述 投票:1回答:1

我有一个Python脚本,其中包含一个循环,其中有很多对 scipy.optimize.fsolve 每个时间步长99(55+54)次,而现在我需要大约10^5个时间步长)。脚本的其他部分也不是很快,但就我从Spyder Profiler的输出来看,对fsolve的调用是目前最耗时的。在我目前的设置下,运行该脚本需要超过10个小时,所以我可以加快一点速度。

根据我在这里和互联网上其他地方读到的内容,我已经给PyPy做了第一次尝试:在conda下的独立环境中安装了它(MacOS 10.15.5,pypy 7.3.1和pypy3.6 7.3.1),还有自己版本的numpy、scipy和pandas,但到目前为止,它实际上比单纯的Python要慢一些(195 s vs 171 s,100个时间步)。

从我读到的 此处 (PyPy状态博客,17年10月),这可能与使用numpy而不是numpypy,以及或者重复分配临时数组有关。除了调用fsolve千万次以上,我还使用了不少numpy数组,所以在我看来是有道理的。

问题是,我不是开发人员,对PyPy完全是个新手,所以JIT痕迹这样的术语对我来说意义不大,解读其中的内容对我来说很可能是个挑战。此外,过去在2017年10月是正确的,现在可能不再相关。另外,即使我会设法加快numpy数组那部分的速度,我也不确定fsolve部分的速度。

谁能说明一下,我在PyPy上投入时间是否值得?还是Cython更适合这种情况?甚至是mpi4py?

如果能帮上忙的话,我很乐意分享我的代码,但它包含了一个超过800行代码的模块,所以只是把它包含在这个帖子里,对我来说并不是一个好主意。

非常感谢!Sita

EDIT 谢谢大家的快速和善意的回应! 说的很有道理,关于需要看我的代码的问题,我把它 此处 链接有效期至2020年6月19日)。Arterial_1D.py是模块,CoronaryTree.py是调用Arterial_1D.py的脚本。为了一个最小的工作示例,我多放了一行,在这种情况下要不加注释(在代码中明确标记)。另外,我将时间步数设置为100,以使代码在合理的时间内运行(在我的例子中,最小的例子为0.61秒,完整的冠状动脉树为37.3秒)。

EDIT 2: 我真傻,在我的原帖中,我提到用PyPy和Python分别运行100步代码的时间为197秒和171秒,但在那个案例中,我在PyPy环境中调用Python,所以使用的是PyPy版本的Numpy。在我的基础环境中,运行100步需要30多秒。所以在这种情况下,PyPy比Python慢很多,这促使我无论如何都要研究一下这个PyPy状态的博文。

python python-3.x numpy pypy scipy-optimize
1个回答
0
投票

如果不看你的代码,我们真的无法帮你优化。不过既然你上面的描述挺多的,那我就回复一下,我觉得你可以尝试着加速一下。

首先是第一件事。Scipy库。 从scipy.optimization.fsolve的源码来看,它包裹着MINPACK的hybrd和hybrj算法,这是相当快的FORTRAN子程序。所以在你的情况下,改用PyPy对这个瓶颈并没有什么好处。

如何优化你的Scipy fsolve ? 最显而易见的数值优化就是对函数的args进行向量化。但似乎你运行的是一种时间步长算法,而大多数标准的时间步长算法都不能进行时间矢量化。 如果你的 "每步时间XX次 "是一种每步时间的隐式空间循环(即你的网格),你可以考虑将其矢量化,以实现速度上的一些提升。其次是放大你函数的猜测起始根估计。看看你是否可以修改你的算法,以便在整个时间区间内利用好起始解(做一些文献挖掘)。注意,这与 "编程 "的关系不大,而与你的数值方法知识有关。

其次,关于你说的 "脚本的其他部分也不是很快"。 好吧,我会选择用Cython来出汗你代码中剩下的python部分,尤其是循环。它是非常积极开发的,伟大的社区,并且经过实战测试。我个人在很多HPC类型的问题中都用过它。Cython也有一个方便的html注释,它可以突出强调潜在的优化,这些优化可能比你的原生python实现更多。

希望对你有所帮助 欢呼

© www.soinside.com 2019 - 2024. All rights reserved.