说到数值计算,可能许多人都能立马想到Matlab。Matlab多年的持续影响力已经让它成为许多人心中科学计算的代名词。但它底层一个重要的库Lapack却很少有人知道。
而Python年龄比Matlab小得多,最近几年随着AI的流行它也开始火了起来。由于做机器学习本质上了也是在做计算,所以许多人也开始在想Python是不是也能做数值计算。当然,Python本身其实只是一个很“简单”的语言,它的数值计算模块实际上是由Numpy和Scipy两个库来实现。而其中最重要的模块之一–线性代数模块–就是直接调用Lapack来实现的。
本文就这两个工具与Lapack之间的关系进行简要介绍,同时也讨论一下在这种关系的情况下,究竟有哪些事情和我们平时想得可能不大一样。
LAPACK是由田纳西大学、加州伯克利分校,科罗拉多丹佛大学以及法国数值算法(集团)有限公司联合开发的开源项目。其官方网站在:http://www.netlib.org/lapack/。
这个工具底层是由Fortran
实现。有报告显示,Fortran实现的矩阵计算要比C/C++还要快,因此这个库的效率也是极高的。
由官网显示,LAPACK曾多年受到Mathworks和Intel的攒助。
Matlab的官方文档中其实清楚地说明了它和LAPACK之间的关系:
LAPACK(线性代数包)是一个例程库,它为数值线性代数和矩阵计算提供快速、稳健的算法。MATLAB® 中的线性代数函数和矩阵运算均基于 LAPACK 构建,并且继续受益于其例程的性能和精度。1
另外,关于他们的历史还有一些简要的介绍:
MATLAB 诞生于 20 世纪 70 年代后期,是一款基于 LINPACK 和 EISPACK 构建的交互式计算器,而 LINPACK 和 EISPACK 在当时是进行矩阵计算的最先进的 Fortran 子例程库。多年来,MATLAB 使用了 LINPACK 和 EISPACK 的十几个 Fortran 子例程的 C 语言版本。
2000 年,MATLAB 改用 LAPACK,这是 LINPACK 和 EISPACK 的现代替代品。它是一个用于数值线性代数的大型、多作者 Fortran 库。LAPACK 最初是为在超级计算机上使用而设计的,因为它能够一次计算矩阵的多个列。LAPACK 例程的速度与基本线性代数子例程 (BLAS) 的速度密切相关。BLAS 版本通常特定于硬件并经过高度优化。
在Numpy官网中明确就写着这么几个大字:
这个的确有点嚣张。
在它的文档中也能明确看到,它底层的矩阵计算全部来自LAPACK。
介绍上述内容根本上就是为我们实操提供指导的,那么他们之间的这种关系能为我们带来哪些启示?
Matlab作为老牌数值计算工具,其功能丰富无比。Numpy虽然如此嚣张地说要替代Matlab但这底气实在还是不足。上述关系表明它们在底层数值矩阵模块都是基于同一个基库,但并不代表在其基础之上的开发是同一个量级和水平的。
当然,从另一个方面来说,正因为它们的基库是一样的,因此在某些具有相同或者相似功能的模块上它们的功能是可以完全等效的。这一点非常重要!因为这就意味着只要是Numpy具有的功能,基本上就可以认为它和Matlab是基本等效的,因此就可以节省大量的测试时间。
这件事情我们之前也做过一些简单的工作,比如:深度对比Python(Numpy,Scipy)与Matlab的数值精度。这篇报告里就十分细致地对比了二者在解线性方程组中的精度,最后发现其结果完全一致(精确到最后一位有效的小数位上)。
那么从这个角度上讲,Numpy在某些计算问题上替代Matlab也是完全可行的!
许多人都抱怨Matlab很慢,当然更多人也在抱怨Python很慢。但这二者的慢都有一个共同的特点:在运行其自身的模块时就非常慢!最典型的就是用它们写循环,比起C完全就不是一个量级。
但注意到前面所说的:Fortran的矩阵计算效率甚至是要快过纯C/C++的!那么这就意味着,如果我们能够尽可能地利用LAPACK模块进行计算,那么运算效率就一定能上去!
比如机器学习库sklearn,其底层就是直接依赖Numpy。但我们在实践中也不难发现sklearn的效率极高。这就是因为它在做复杂的计算的时候主要都是在调用LAPACK的模块。
那么从技巧上讲,最简单的方法其实就是向量化。因为向量化可以极大减少循环的使用,从而就能够使尽可能多的计算都由LAPACK来实现,而不是用Matlab或者Python自带的循环来实现。
另外,笔者也做过一些测试,比如一个简单的矩阵乘法。如果用Matlab的循环来实现,大概比直接用Matlab的矩阵乘法多1000倍以上的时间。
我曾经也试过修改过一个算法,向量化过后在1W量级的数据集上可以将运算时间从30分钟降低到30秒左右。
目前关于这2种语言的速度的对比也有不少了,这里就不太多说。总体感觉二者在不同的问题上还是各有不同的表现。但这里需要强调的一些问题是:
(1)Matlab是一个统一框架的软件,而Python的各种对比本质上是各种库的对比,因此单说谁快谁慢其实都是不太严谨的。
(2)Matlab作为一款成熟的商业软件,其相关的配套功能也是比较健全的。在运行效率上有个很明显的特点就是:它优化了硬件层面的保护,因此在进行大规模计算时不会尽最大努力去压榨硬件的能力,因此在一些大量问题的时候可能会显得慢一些。但这种保护同时也带来了更高的稳定性。相反,Python的各种库(包括Numpy和Scipy),本质上都是以功能导向的。并不会对硬件层面进行太多优化,因此它会放任程序对硬件进行最大程度的压榨。所以在具体使用时也需要注意这个问题。
笔者曾多次使用Python的
joblib
模块来进行并行计算。让我体会最深刻的是一旦运算量较大,CPU的温度就会飚升,甚至触发操作系统自带的硬件保护机制(有时是鲁大师的高温报警)。这一点可能也不是什么好事,因为这样会明显折损硬件的寿命。因此在使用时要特别注意。
简单说完了Matlab和Python(Numpy, Scipy)与LAPACK之间的关系并分析了一些用处。从上述分析不难看到,了解这些“周边”知识对我们的工作和学习实际上也是有不小的帮助的。由于Python和LAPACK的这种关系,使得它其实也可以做一些科学计算的工作。Matlab由于底层调用LAPACK,因此也能提高效率。
本文的介绍和分析还很窄,今后如果有机会还可以更加深入地讨论这些问题。
https://ww2.mathworks.cn/help/matlab/math/lapack-in-matlab.html ↩︎