Python与C++在稀疏线性代数应用中的对比
我正在写一个应用程序,里面有很多计算时间会用来对稀疏矩阵和向量进行基本的线性代数操作(比如加法、乘法、与向量相乘、与标量相乘等等)。到目前为止,我们已经用C++和Boost矩阵库搭建了一个原型。
我在考虑换成Python,这样编写应用程序会更简单,因为Boost库(这个简单的C++线性代数库)似乎速度也不是特别快。这个项目是研究性质的,主要是为了验证概念,所以在运行速度上可以接受一些降低(因为我认为C++的性能几乎总是优于Python),只要编写代码的时间能大幅减少就行。
基本上,我希望能从之前使用过这些库的人那里得到一些建议。但具体来说:
1) 我发现了scipy.sparse和pySparse。这些库(或者其他库)推荐吗?
2) 除了Boost,还有哪些库推荐给C++使用?我见过一些有C接口的库,但我还是希望能做一些复杂度低的事情,如果能获得相对不错的性能就更好了。
3) 最终,Python在执行线性代数操作时的运行速度会和C++相当吗?我需要进行很多线性代数操作,如果速度下降得很明显,那我可能就不应该尝试这个切换了。
谢谢你们提前提供的帮助和分享的经验。
5 个回答
2) 看起来你是在寻找 Eigen 这个库。
3) 我猜如果你在做稀疏线性代数的工作,早晚你都会希望能尽可能提高速度,所以我建议你还是用C++。我觉得用Python没什么必要,除非你只是想快速测试一个原型,但你已经在C++中做过这个了。
正如llasram所说,很多Python的库都是用C/C++写的,所以Python的运行速度应该是可以接受的。
在C++中,你也可以试试gsl(GNU科学库),不过我觉得它的线性代数功能和Boost库是差不多的,因为这两个库都使用BLAS来处理这些功能。对于稀疏线性代数,你可以看看SBLAS,不过我自己没用过。以下是我看到的一些简单的“优缺点”:
- C++ :
- 会强迫你保持一个结构良好的程序
- 可以很容易地为高级语言(比如Python)封装,以确保快速测试(可以看看Python的C API或者SWIG)。
- Python :
- 调试起来很简单,但容易导致结构不好的程序
- 可以非常方便地导入数据进行测试
- 有一些非常可靠的库,比如scipy和numpy(顺便说一下,scipy也使用BLAS进行线性代数运算)
- 管理代码
我个人使用gsl来处理矩阵操作,并把我的C++库封装成Python库,这样可以方便地用数据进行测试。在我看来,这是一种结合两种语言优点的方法。
我的建议是,在把算法翻译成其他语言之前,先在Python中彻底测试这个算法(否则你可能会在一个糟糕的算法上过早地进行优化)。一旦你清楚地定义了适合你问题的最佳接口,就可以把它提取到外部代码中。
让我来解释一下。
假设你的最终算法是处理一堆数字,格式是(行,列,值),然后计算相应稀疏矩阵的SVD(奇异值分解)。那么你可以把整个接口留给Python:
class Problem(object):
def __init__(self, values):
self.values = values
def solve(self):
return external_svd(self.values)
这里的external_svd
是一个Python的封装,用于调用一个Fortran/C/C++的子程序,这个子程序可以高效地计算给定格式(行,列,值)的矩阵的SVD,或者你喜欢的其他方式。
再次强调,首先尝试使用numpy
和scipy
,以及其他标准的Python工具。只有在你分析了代码的性能后,才应该编写实际的封装external_svd
。
如果你这样做,你将拥有一个用户友好的模块(用户与Python互动,而不是与Fortran/C/C++互动),最重要的是,你将能够使用不同的后端:external_svd_lapack
、external_svd_paradiso
、external_svd_gsl
等(每个后端对应一个)。
至于稀疏线性代数库,可以查看英特尔数学核心库、PARADISO稀疏求解器、以及哈威尔子程序库(HSL)中的“MA27”。我曾成功使用它们来解决非常稀疏、非常大的问题(可以查看非线性优化求解器IPOPT的页面,看看我所说的意思)。