似乎许多项目慢慢需要进行矩阵数学运算,并陷入首先构建一些向量类并慢慢添加功能的陷阱,直到它们被捕获构建一个半定制的自定义线性代数库,并依赖于它.
我想避免这种情况,而不依赖于一些切向相关的库(例如OpenCV,OpenSceneGraph).
有哪些常用的矩阵数学/线性代数库,为什么会决定使用另一个?有什么建议不要因某些原因使用?我特意在几何/时间上下文*(2,3,4 Dim)*中使用它,但将来可能会使用更高维数据.
我正在寻找以下任何方面的差异:API,速度,内存使用,广度/完整性,狭窄/特异性,可扩展性和/或成熟度/稳定性.
我最终使用了Eigen3,我非常满意.
为此,有很多项目已经确定了通用图形工具包.那里的GMTL非常好 - 它非常小,非常实用,并且被广泛使用,非常可靠.OpenSG,VRJuggler和其他项目都转而使用它而不是自己的手动滚动/矩阵数学.
我发现它非常好 - 它通过模板完成所有工作,所以它非常灵活,速度非常快.
编辑:
在评论讨论和编辑之后,我想我会抛出一些关于特定实现的好处和缺点的更多信息,以及为什么你可以根据你的情况选择一个而不是另一个.
GMTL -
优点:简单的API,专为图形引擎而设计.包括许多面向渲染的原始类型(例如平面,AABB,具有多个插值的quatenrions等),这些类型不在任何其他包中.内存开销非常低,非常快速,易于使用.
缺点:API非常专注于渲染和图形.不包括通用(NxM)矩阵,矩阵分解和求解等,因为它们不在传统图形/几何应用领域之内.
本征 -
优点:清洁API,相当容易使用.包括带四元数和几何变换的几何模块.内存开销低.完整,高性能的大型NxN矩阵和其他通用数学例程的求解.
缺点:可能比你想要的范围更广(?).与GMTL相比较少的几何/渲染特定例程(即:欧拉角定义等).
IMSL -
好处:非常完整的数字库.非常非常快(据说是最快的解算器).迄今为止最大,最完整的数学API.商业支持,成熟和稳定.
缺点:成本 - 不便宜.很少有几何/渲染特定的方法,所以你需要在它们的线性代数类之上自己滚动.
NT2 -
优点:如果您习惯使用MATLAB,则提供更熟悉的语法.为大型矩阵等提供完全分解和求解.
缺点:数学,而不是重点.可能不像Eigen那样高效.
LAPACK -
优点:非常稳定,经过验证的算法.已经很久了.完整的矩阵求解等.模糊数学的许多选项.
缺点:在某些情况下表现不佳.从Fortran移植,使用奇怪的API.
就个人而言,它归结为一个问题 - 你打算如何使用它.如果您只专注于渲染和图形,我喜欢Generic Graphics Toolkit,因为它表现良好,并支持许多有用的渲染操作,而无需实现自己的渲染.如果你需要通用矩阵求解(即:大矩阵的SVD或LU分解),我会选择Eigen,因为它处理它,提供一些几何运算,并且非常适合大矩阵解决方案.您可能需要编写更多自己的图形/几何操作(在它们的矩阵/向量之上),但这并不可怕.
所以我是一个非常关键的人,如果我要投资一个图书馆,我会更好地了解自己的成就.我认为,在仔细审查时,最好是批评和恭维奉承; 它的错误对未来有更多的影响而不是正确的.所以我会在这里稍微过一点,提供一些可以帮助我的答案,我希望能帮助那些可能沿着这条道路走下去的人.请记住,这是基于我对这些库所做的很少的审查/测试.哦,我从里德那里偷走了一些积极的描述.
我会提到我用GMTL去的顶部,尽管它的特质是因为Eigen2的不安全性太大了.但我最近了解到,Eigen2的下一个版本将包含将关闭对齐代码并使其安全的定义.所以我可能会转过来.
更新:我已切换到Eigen3.尽管它的特性,它的范围和优雅太难以忽视,并且可以通过定义来关闭使其不安全的优化.
优点:LGPL MPL2,干净,设计良好的API,相当容易使用.似乎与充满活力的社区保持良好的关系.内存开销低.高性能.适用于一般线性代数,但也有良好的几何功能.所有标题库,无需链接.
异步性/缺点:( 当前开发分支 Eigen3 中可用的某些定义可以避免这些/所有这些)
不安全的性能优化导致需要仔细遵循规则.不遵守规则会导致崩溃.
你根本无法安全地传递价值
使用特征类型作为成员需要特殊的分配器定制(或你崩溃)
使用stl容器类型和可能需要特殊分配自定义的其他模板(或者你会崩溃)
某些编译器需要特别小心以防止函数调用崩溃(GCC窗口)
优点:LGPL,Fairly Simple API,专为图形引擎而设计.包括许多面向渲染的原始类型(例如平面,AABB,具有多个插值的quatenrions等),这些类型不在任何其他包中.内存开销非常低,非常快速,易于使用.所有标题都基于,无需链接.
Idiocyncracies /缺点:
API很古怪
可能是另一个lib中的myVec.x()只能通过myVec [0]获得(可读性问题)
一个数组或stl ::点向量可能会导致你做像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不包含Vectors的操作,VecOps.h包含一些,其他的则在Generate.h中.在VecOps.h中交叉(vec&,vec&,vec&),[make]在Generate.h中交叉(vec&,vec&)
不成熟/不稳定的API; 还在改变.
例如,"cross"已从"VecOps.h"移至"Generate.h",然后名称更改为"makeCross".文档示例失败,因为仍然引用不再存在的旧版本的函数.
无法分辨,因为他们似乎对其网页的分形图像标题比内容更感兴趣.看起来更像是一个学术项目,而不是一个严肃的软件项
2年前的最新版本.
显然没有英文文档,虽然据说某些地方有法语版本.
无法找到项目周围社区的踪迹.
好处:古老而成熟.
缺点:
古老的恐龙与非常糟糕的API
为了它的价值,我尝试了Eigen和Armadillo.以下是简要评估.
特征优势:1.完全独立 - 不依赖于外部BLAS或LAPACK.2.文件体面.虽然我没有经过考验,但据称速度很快.
缺点:QR算法只返回一个矩阵,R矩阵嵌入在上三角形中.不知道矩阵的其余部分来自何处,并且不能访问Q矩阵.
犰狳的优点:1.广泛的分解和其他功能(包括QR).2.合理快速(使用表达式模板),但同样,我还没有把它推到高维度.
缺点:1.取决于外部BLAS和/或LAPACK进行矩阵分解.2.缺少IMHO的文档(除了更改#define语句之外,还包括LAPACK的详细信息).
如果一个开源库可以自包含且易于使用,那将会很不错.我已经遇到了同样的问题已有10年了,而且令人沮丧.有一次,我使用GSL for C并围绕它编写了C++包装器,但是使用现代C++ - 尤其是使用表达式模板的优点 - 我们不应该在21世纪弄乱C语言.只是我的tuppencehapenny.
如果您正在寻找英特尔处理器上的高性能矩阵/线性代数/优化,我会看看英特尔的MKL库.
MKL经过精心优化,具有快速的运行时性能 - 大部分基于非常成熟的BLAS/LAPACK fortran标准.其性能随可用内核数量而变化.具有可用内核的免提可扩展性是计算的未来,我不会将任何数学库用于新项目不支持多核处理器.
简而言之,它包括:
基本矢量矢量,矢量矩阵和矩阵矩阵运算
矩阵分解(LU分解,hermitian,稀疏)
最小二乘拟合和特征值问题
稀疏线性系统求解器
非线性最小二乘求解器(信任域)
加上信号处理程序,如FFT和卷积
非常快的随机数发生器(mersenne twist)
更多......请参阅:链接文字
缺点是MKL API可能非常复杂,具体取决于您需要的例程.您还可以查看他们的IPP(Integrated Performance Primitives)库,该库面向高性能图像处理操作,但是相当广泛.
保罗
CenterSpace软件,.NET数学库,centerspace.net
我听说过Eigen和NT2的好东西,但还没有亲自使用过.还有Boost.UBLAS,我认为它有点长.NT2的开发人员正在构建下一个版本,目的是将其纳入Boost,因此这可能算是一件事.
我的林.ALG.需求不超出4x4矩阵的情况,所以我不能评论高级功能; 我只是指出了一些选择.
我是这个话题的新手,所以我不能说很多,但BLAS几乎是科学计算的标准.BLAS实际上是一个API标准,它有许多实现.老实说,我不确定哪种实现最受欢迎或者为什么.
如果你想也能够进行常见的线性代数运算(求解系统,最小二乘回归,分解等),请查看LAPACK.
GLM怎么样?
它基于OpenGL着色语言(GLSL)规范,并在MIT许可下发布.显然针对图形程序员
我将为Eigen添加投票:我将大量代码(3D几何,线性代数和微分方程)移植到不同的库中 - 几乎在所有情况下都提高了性能和代码可读性.
未提及的一个优点是:使用带有Eigen的SSE非常容易,这显着提高了2D-3D操作的性能(所有内容都可以填充到128位).