Python为何在科学计算领域打败Fortran? - cerfacs


为什么越来越多以前在 Fortran 中执行的时间要求严格的科学计算现在用 Python 这种速度较慢的语言编写?
Python 以速度慢着称,即比 Fortran、C 或 Rust 等编译语言慢得多。普通的 Python 比 Fortran 慢得多。

然而,这种比较毫无意义,因为 Python 的科学用途并不依赖于普通的 Python。相反,Python 被用作粘合层,依赖于编译的优化包,将它们串在一起以执行目标计算。

科学计算中最广泛的软件包可能是NumPy,即Numerical Python。
 顾名思义,数字数据是通过这个包来操作的,而不是在普通的Python中,在幕后所有繁重的工作都是由C/C++或Fortran编译的例程完成的。
从本质上讲,Python被用来将一个快速例程指向正确的方向(即指向正确的内存地址),仅此而已。

比较brute-force(Fortran)和基于KDtree的(Python / NumPy / SciPy)性能时间:

  • 10亿个细胞
  • 1000万个多孔的边界节点
  • 1.8万个穿孔

brute-force的版本运行了6小时30分钟;而基于Kdtree的版本呢?只用了4分钟,几乎快了100倍,结果的差异只在机器精度的层面上出现。
 
详细点击标题
 
Reddit网友评论:
1. 这与我的经历产生了共鸣。在我之前的研究小组中,有一个模拟量很大的项目在不到两个月的时间内从构思到手稿,因为它能够利用 Numpy、Numba 和 Scipy。如果它是用另一种语言完成的,我很难相信它会这么快发布(即使最终的模拟可能会稍微快一点)。
 
2. Numpy是~120万行的C语言,不是因为它是一个薄薄的BLAS封装,而是因为它本身就是一个大型的数值库。

numpy的一部分,np.linalg使用BLAS后端,以及dot、matmul和tensordot。你的普通函数 "ufuncs "如加、减、乘、除根本不使用BLAS,只是一个C语言的for循环。在最近的numpy中,exp也使用AVX-512(它是在1.18或1.19中添加的,我忘了是哪个)。

如果你在纯numpy中做arr1 * arr2,你可以在低级语言中通过不分配来打败它,尽管np.mul(arr1, arr2, out=out)让你在numpy中获得不分配的风格,而且numpy内存池可能使分配基本免费。

然而,在低级语言中,你将有能力分割出arr1, arr2并进行多线程操作,而numpy不能做到这一点。

另一方面,numpy不遗余力地以最佳顺序执行内存访问,许多操作(视图等)基本上是免费的,它记录了步长和迭代顺序而不是移动数据。C++库(BOOST、Eigen)没有这些优化。

编译器也可能在低级语言中融合循环,这在numpy中非常明确地不会发生。

还有一些操作在numpy中是不存在的,在低级语言中可以很容易地实现,例如用一个矩阵乘以一个对角线矩阵,你把它作为一个向量存储。
 
3.Python中的计算任务通常利用高度优化的库。Python的成功一直取决于两件事...

  • 开发速度是编程中存在的一个问题。
  • 对非时间限制的代码进行运行时间优化总是在浪费开发时间。

Python在科学领域胜出,因为它提供了一个完整的软件包,由于其直观的成语风格,开发速度快,由于其有效利用低级开发库的模块化,运行速度快。