什么是最广泛使用的C ++向量/矩阵数学/线性代数库,以及它们的成本和收益权衡?

时间:2009-09-04 16:45:59

标签: c++ math matrix linear-algebra

似乎许多项目慢慢需要进行矩阵数学运算,并陷入首先构建一些向量类并缓慢添加功能的陷阱,直到它们被捕获构建一个半定制的自定义线性代数库,并且依赖于在上面。

我想避免这种情况,而不依赖于某些与切向相关的库(例如OpenCV,OpenSceneGraph)。

那里常用的矩阵数学/线性代数库是什么,为什么决定使用另一个?有什么建议不要因某些原因使用?我特意在几何/时间上下文*(2,3,4 Dim)*中使用它,但将来可能会使用更高维数据。

我正在寻找以下任何方面的差异:API,速度,内存使用,广度/完整性,狭隘/特异性,可扩展性和/或成熟度/稳定性。

更新

我最终使用了Eigen3,我非常满意。

11 个答案:

答案 0 :(得分:105)

为此,有很多项目已经确定Generic Graphics Toolkit。那里的GMTL非常好 - 它非常小,非常实用,并且被广泛使用,非常可靠。 OpenSG,VRJuggler和其他项目都转而使用它而不是自己的手动滚动/矩阵数学。

我发现它非常好 - 它通过模板完成所有工作,所以它非常灵活,速度非常快。


编辑:

在评论讨论和编辑之后,我想我会抛出一些关于具体实施的好处和缺点的更多信息,以及为什么你可以根据你的情况选择一个而不是另一个。

GMTL -

优点:简单的API,专为图形引擎而设计。包括许多面向渲染的原始类型(例如平面,AABB,具有多个插值的quatenrions等),这些类型不在任何其他包中。内存开销非常低,速度非常快,易于使用。

缺点:API非常专注于渲染和图形。不包括通用(NxM)矩阵,矩阵分解和求解等,因为它们不在传统图形/几何应用领域。

Eigen -

好处:Clean API,相当容易使用。包括带有四元数和几何变换的Geometry module。内存开销低。完整的,highly performant求解大型NxN矩阵和其他通用数学例程。

缺点:可能比你想要的范围更广(?)。与GMTL相比较少的几何/渲染特定例程(即:欧拉角定义等)。

IMSL -

好处:非常完整的数字库。非常非常快(据说是最快的解算器)。迄今为止最大,最完整的数学API。商业支持,成熟和稳定。

下行:成本 - 并不便宜。很少有几何/渲染特定的方法,所以你需要在它们的线性代数类之上自己动手。

NT2 -

好处:如果您习惯使用MATLAB,则提供更熟悉的语法。为大型矩阵等提供完全分解和求解。

下行:数学,而不是重点。可能不像Eigen那样高效。

LAPACK -

优点:非常稳定,经过验证的算法。已经很久了。完整的矩阵求解等。模糊数学的许多选项。

缺点:在某些情况下表现不佳。从Fortran移植,使用奇怪的API。

就我个人而言,它归结为一个问题 - 你打算如何使用它。如果你专注于渲染和图形,我喜欢Generic Graphics Toolkit,因为它表现良好,并支持许多有用的渲染操作,而无需实现自己的渲染。如果你需要通用矩阵求解(即:大矩阵的SVD或LU分解),我会选择Eigen,因为它处理它,提供一些几何运算,并且对大矩阵解决方案非常有效。您可能需要编写更多自己的图形/几何操作(在它们的矩阵/向量之上),但这并不可怕。

答案 1 :(得分:32)

所以我是一个非常挑剔的人,如果我打算投资一个图书馆,我会更清楚自己是在做什么。我认为,在仔细审查时,最好是对批评和对奉承的谴责;它的错误对未来有更多的影响而不是正确的。所以我会在这里稍微过一点,提供一些可以帮助我的答案,我希望能帮助那些可能沿着这条道路走下去的人。请记住,这是基于我对这些库所做的很少的审查/测试。哦,我从里德那里偷走了一些积极的描述。

我会提到我用GMTL去的顶部,尽管它的特质是因为Eigen2的不安全性太大了。但我最近了解到,Eigen2的下一个版本将包含将关闭对齐代码并使其安全的定义。所以我可以转换。

更新:我已切换到Eigen3。尽管它具有特殊性,但它的范围和优雅都难以忽视,并且可以通过定义来关闭使其不安全的优化。

EIGEN2 / Eigen3

好处: LGPL MPL2,干净,设计精良的API,相当容易使用。似乎与充满活力的社区保持良好的关系。内存开销低。高性能。适用于一般线性代数,但也有良好的几何功能。所有标题库,无需链接。

Idiocyncracies / downsides: 当前开发分支 Eigen3中可用的某些定义可以避免部分/全部

     
  • 不安全的性能优化导致需要仔细遵循规则。不遵守规则会导致崩溃。  
        
    • 你根本无法安全地传递价值   
    • 使用Eigen类型作为成员需要特殊的分配器定制(或者你崩溃)   
    • 与stl容器类型以及可能需要的其他模板一起使用 特殊分配定制(或者你会崩溃)   
    • 某些编译器需要特别小心以防止函数调用崩溃(GCC窗口)  

GMTL

优点:LGPL,Fairly Simple API,专为图形引擎而设计。 包括许多适合渲染的原始类型(例如 飞机,AABB,具有多个插值的quatenrions等) 没有任何其他包裹。内存开销非常低,非常快, 使用方便。所有标题均基于,无需链接。

Idiocyncracies /缺点:

     
  • API很古怪  
    • 另一个lib中的myVec.x()可能只能通过myVec [0]获得(可读性问题)   
      • 一个数组或stl :: vector的点可能会让你做一些像pointsList [0] [0]这样的东西来访问第一个点的x分量
       
    • 在天真的优化尝试中,删除了交叉(vec,vec)和 当编译器消除时,用makeCross(vec,vec,vec)替换 反正不必要的临时工  
    • 除非您关闭,否则正常的数学运算不会返回正常类型 关闭一些优化功能,例如:vec1 - vec2不会返回 法线向量,即使length( vecA - vecB )有效,vecC = vecA - vecB也会失败。你必须像:length( Vec( vecA - vecB ) )那样换行  
    • 对向量的操作由外部函数提供而不是 成员。这可能需要您在任何地方使用范围解析 因为常见的符号名称可能会发生碰撞  
    • 你必须这样做         length( makeCross( vecA, vecB ) )
            或
             gmtl::length( gmtl::makeCross( vecA, vecB ) )
         否则你可能会试试         vecA.cross( vecB ).length()
     
  • 维护得不好  
        
    • 仍称为“测试版”   
    • 文档缺少基本信息,例如需要哪些标题 使用正常的功能   
           
      • Vec.h不包含Vector的操作,VecOps.h包含 一些,其他人在Generate.h中。交叉(vec&,vec&,vec&)in VecOps.h,[make]在Generate.h中交叉(vec&,vec&)
     
  • 不成熟/不稳定的API;还在改变。  
        
    • 例如,“cross”已从“VecOps.h”移至“Generate.h”,并且 然后名称改为“makeCross”。文档示例失败 因为仍然引用不再存在的旧版本的函数。

NT2

无法分辨,因为他们似乎对其网页的分形图像标题比内容更感兴趣。看起来更像是一个学术项目,而不是一个严肃的软件项

2年前的最新版本。

显然没有英文文档,虽然据说某处有法语版本。

无法找到项目周围社区的踪迹。

LAPACK& BLAS

好处:古老而成熟。

缺点:

  • 作为具有非常糟糕的API的恐龙而

答案 2 :(得分:11)

如果您正在寻找英特尔处理器上的高性能矩阵/线性代数/优化,我会看看英特尔的MKL库。

MKL经过精心优化,具有快速的运行时间性能 - 大部分基于非常成熟的BLAS / LAPACK fortran标准。其性能随可用内核数量而变化。具有可用内核的免提可扩展性是计算的未来,我不会将任何数学库用于新项目,也不支持多核处理器。

非常简短,它包括:

  1. 基本矢量矢量,矢量矩阵, 和矩阵矩阵运算
  2. 矩阵分解(LU分解,hermitian,稀疏)
  3. 最小二乘拟合和特征值问题
  4. 稀疏线性系统求解器
  5. 非线性最小二乘求解器(信任域)
  6. Plus信号处理程序,如FFT和卷积
  7. 非常快的随机数发生器(mersenne twist)
  8. 更多......见:link text
  9. 缺点是MKL API可能非常复杂,具体取决于您需要的例程。您还可以查看他们的IPP(Integrated Performance Primitives)库,该库面向高性能图像处理操作,但是相当广泛。

    保罗

    CenterSpace Software,.NET Math libraries,centerspace.net

答案 3 :(得分:11)

为了它的价值,我已经尝试了Eigen和Armadillo。以下是一个简短的评估。

本征 好处: 1.完全独立 - 不依赖于外部BLAS或LAPACK。 2.文件体面。 虽然我还没有对它进行测试,但据称速度很快。

缺点: QR算法仅返回单个矩阵,R矩阵嵌入在上三角形中。不知道矩阵的其余部分来自何处,也无法访问Q矩阵。

犰狳 好处: 1.广泛的分解和其他功能(包括QR)。 2.合理快速(使用表达模板),但同样,我还没有把它推到高维度。

缺点: 1.取决于外部BLAS和/或LAPACK以进行矩阵分解。 2.文档缺少恕我直言(除了更改#define语句之外,还包括LAPACK的具体内容)。

如果有一个自包含且易于使用的开源库,那将会很不错。我已经遇到了同样的问题已有10年了,而且令人沮丧。有一次,我使用GSL for C并在其周围编写了C ++包装器,但是使用现代C ++ - 特别是利用表达模板的优点 - 我们不应该在21世纪弄乱C语言。只是我的tuppencehapenny。

答案 4 :(得分:8)

我听说过有关EigenNT2的好消息,但还没有亲自使用过。还有Boost.UBLAS,我认为这有点长。 NT2的开发人员正在构建下一个版本,目的是将其纳入Boost,因此这可能算是事情。

我的林。 ALG。需求不超出4x4矩阵的情况,所以我不能评论高级功能;我只是指出了一些选择。

答案 5 :(得分:8)

我是这个话题的新手,所以我不能说很多,但BLAS几乎是科学计算的标准。 BLAS实际上是一个API标准,它有许多实现。老实说,我不确定哪种实现最受欢迎或为什么。

如果您还希望能够进行常见的线性代数运算(求解系统,最小二乘回归,分解等),请查看LAPACK

答案 6 :(得分:6)

GLM怎么办?

它基于OpenGL着色语言(GLSL)规范,并在MIT许可下发布。 明确针对图形程序员

答案 7 :(得分:5)

我将为Eigen添加投票:我将大量代码(3D几何,线性代数和微分方程)移植到不同的库中 - 几乎在所有情况下都提高了性能和代码可读性。

未提及的一个优点:使用带有Eigen的SSE非常容易,这显着提高了2D-3D操作的性能(所有内容都可以填充到128位)。

答案 8 :(得分:4)

好的,我想我知道你在找什么。看来GGT是一个非常好的解决方案,正如Reed Copsey建议的那样。

就个人而言,我们推出了自己的小型图书馆,因为我们经常处理理性点 - 很多理性的NURBS和Beziers。

事实证明,大多数3D图形库都使用在投影数学中没有基础的投影点进行计算,因为这就是为您提供所需答案的原因。我们最终使用了Grassmann点,它具有坚实的理论基础并减少了点类型的数量。 Grassmann点基本上与人们现在使用的计算相同,具有强大的理论。最重要的是,它使我们的思想更加清晰,因此我们减少了错误。罗恩·戈德曼(Ron Goldman)写了一篇关于计算机图形学中格拉斯曼点的文章"On the Algebraic and Geometric Foundations of Computer Graphics"

与您的问题没有直接关系,但是有趣的阅读。

答案 9 :(得分:0)

FLENS

http://flens.sf.net

它还实现了许多LAPACK功能。

答案 10 :(得分:0)

我发现这个库非常简单和实用(http://kirillsprograms.com/top_Vectors.php)。这些是通过C ++模板实现的裸骨矢量。没有花哨的东西 - 只是你需要做的向量(加,减乘,点等)。