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

Posted

技术标签:

【中文标题】什么是最广泛使用的 C++ 向量/矩阵数学/线性代数库,以及它们的成本和收益权衡? [关闭]【英文标题】:What are the most widely used C++ vector/matrix math/linear algebra libraries, and their cost and benefit tradeoffs? [closed] 【发布时间】:2010-11-25 16:58:20 【问题描述】:

似乎许多项目慢慢地需要做矩阵数学,并陷入首先构建一些向量类并慢慢添加功能的陷阱,直到他们发现构建一个半途而废的自定义线性代数库,并且依赖于在上面。

我想避免这种情况,同时不依赖于一些切向相关的库(例如 OpenCV、OpenSceneGraph)。

目前常用的矩阵数学/线性代数库有哪些,为什么会决定使用其中一个?是否有任何建议不要出于某种原因使用?我专门在几何/时间上下文中使用它*(2,3,4 Dim)*,但将来可能会使用更高维度的数据。

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

更新

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

【问题讨论】:

既然你提到了 OSG 和 OpenCV,我猜你只需要 3D 图形类型的向量/矩阵,即:3x3 和 4x4 矩阵。我的答案基于此,但您可能想指定您使用它的具体方式 - 您需要矩阵求解吗?高维矩阵数学?等等 现在我只做基于 2D 几何的东西,但假设您有时需要对 2D 数据进行 3x3 操作,并且不清楚 3D 数据是否需要因此 4x4 操作。我们想在整个公司使用一个通用库。我对权衡的结果没有很好的了解。更笼统会更好,但问题是要付出什么代价。 如果您只是在进行几何变换,我真的建议您查看 GGT,正如我在回答中提到的那样。它非常完整,但实际上什么也没做,所以它是一个非常干净、简单的选择。 BLAS 和 LAPACK 更适合用于科学和数学的复杂矩阵解决方案(即:50x50 矩阵、稀疏矩阵等),而不是几何变换。 C++ 矢量类库使用 SIMD 指令进行并行处理。 github.com/vectorclass/version2 【参考方案1】:

有不少项目为此选择了Generic Graphics Toolkit。那里的 GMTL 很好——它非常小,非常实用,并且被广泛使用,非常可靠。 OpenSG、VRJuggler 和其他项目都已转而使用它,而不是他们自己的手动旋转器/矩阵数学。

我发现它非常棒 - 它通过模板完成所有操作,因此非常灵活且速度非常快。


编辑:

在 cmets 讨论和编辑之后,我想我会抛出一些关于特定实现的优缺点的更多信息,以及根据你的情况为什么你可能会选择其中一个。

GMTL -

优点:简单的 API,专为图形引擎设计。包括许多其他包中没有的面向渲染的基元类型(例如平面、AABB、具有多重插值的四元数等)。非常低的内存开销,非常快,易于使用。

缺点: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,因为它可以处理这个问题,提供一些几何运算,并且在大型矩阵解决方案中非常高效。您可能需要编写更多自己的图形/几何运算(在它们的矩阵/向量之上),但这并不可怕。

【讨论】:

在决定使用 GMTL 之前,您是否评估过其他库?肤浅的比较让我相信 Eigen 得到了更好的支持,但那是在审查各自网站的基础上。您是否知道其中一种相对于另一种的特定优势? Eigen 也很好用。在我进行调查时,它还不够成熟,但我相信在这一点上它会是一个不错的选择。 GMTL 已经被相当广泛地使用,并且在我决定使用它时非常成熟和可靠。 我想把我的问题简化为关键问题:您是否主观地做出了选择,例如“这看起来更好”或有特定功能(api、速度、内存使用、广度、窄度、可扩展性) ),这有所作为。我想成熟度属于这个标准,但如果成熟度是唯一的指标,我想你会选择基于 BLAS 或 LAPACK 的选项。 我在尝试了多个选项后选择了这个,并且基于:性能、可用​​性和低运行时/编译时间开销。 Eigen 现在看起来比当时好多了,所以我无法在它们之间做出判断。不过,我对使用 GMTL 感到非常满意。 这也是我喜欢 GMTL 并使用它的部分原因。它使用起来非常自然,而且非常非常容易使用。它还支持我需要的一切,在这种情况下,因为我只是担心直接处理几何变换和四元数旋转。【参考方案2】:

所以我是一个非常挑剔的人,如果我要投资图书馆,我最好知道自己在做什么。我认为审查时最好重批评,轻奉承;它的错误对未来的影响比正确的要多得多。因此,我将在这里稍微过分,以提供对我有帮助的答案,我希望能帮助其他可能走这条路的人。请记住,这是基于我对这些库所做的少量审查/测试。哦,我从里德那里偷了一些正面的描述。

我会在上面提到我选择了 GMTL,尽管它有一些特殊性,因为 Eigen2 的不安全性是一个太大的缺点。但我最近了解到 Eigen2 的下一个版本将包含将关闭对齐代码并使其安全的定义。所以我可以切换。

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

特征2/特征3

优点:LGPL MPL2,干净,设计良好的API,相当容易使用。似乎在一个充满活力的社区中得到了很好的维护。低内存开销。高性能。专为一般线性代数而设计,但也提供良好的几何功能。所有头文件库,不需要链接。

独特性/缺点:(某些/所有这些都可以通过当前开发分支 Eigen3中可用的一些定义来避免)

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

格林威治标准时间

优点:LGPL,相当简单的 API,专为图形引擎设计。 包括许多面向渲染的原始类型(例如 平面、AABB、具有多重插值的四元数等) 不在任何其他包中。非常低的内存开销,非常快, 使用方便。所有基于标题,无需链接。

怪癖/缺点:

API 很古怪 另一个库中的 myVec.x() 只能通过 myVec[0] 获得(可读性问题) 数组或 stl::vector 点可能会导致您执行 pointsList[0][0] 之类的操作来访问第一个点的 x 分量 在天真的优化尝试中,删除了 cross(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 不包含向量的操作,VecOps.h 包含 例如,一些在 Generate.h 中。交叉(vec&,vec&,vec&)在 VecOps.h, [make]cross(vec&,vec&) 在 Generate.h 不成熟/不稳定的 API;还在变化。 例如,“cross”已从“VecOps.h”移动到“Generate.h”,并且 然后名称更改为“makeCross”。文档示例失败 因为仍然引用不再存在的旧版本的功能。

NT2

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

2 年前的最新版本。

显然没有英文文档,但据说某处有法语的东西。

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

LAPACK & BLAS

优点:老而成熟。

缺点:

像恐龙一样古老,API 非常糟糕

【讨论】:

关于 Eigen 对齐断言:要从 SSE(1,2,3 或 4) 小数据集的操作中获得高性能,您绝对需要对齐数据。未对齐的加载/存储操作要慢得多。对齐或非对齐加载/存储之间的决定也需要时间。任何“通用”实现都很难为每个人做正确的事情,除非他们将接口也分为“对齐”和“未对齐”操作 - 然后它又不是很通用。 @Catskul 我想使用 Eigen3。您能否扩展“可以通过定义关闭使其不安全的优化”?您在 Eigen2 下列出的其他问题在 与对齐问题相关的主题 下的doc 中有详细的详细说明。我可以忍受这些问题。 安全问题我指的是所有与对齐相关的问题,并且与 Eigen2 相同。如果你对 Eigen2 没问题,你对 Eigen3 没问题。 BLAS 和 LAPACK 实际上不是库,而是规范/API。您可以通过 netlib 或其他实现(例如 ATLAS 和 OpenBLAS)提及它们的初始实现。【参考方案3】:

对于它的价值,我已经尝试过 Eigen 和 Armadillo。下面是一个简短的评估。

特征 优点: 1. 完全独立——不依赖外部 BLAS 或 LAPACK。 2.文档不错。 3. 据说速度很快,虽然我还没有进行测试。

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

犰狳 优点: 1.广泛的分解和其他功能(包括QR)。 2. 相当快(使用表达式模板),但同样,我还没有真正将它推到高维度。

缺点: 1. 取决于外部 BLAS 和/或 LAPACK 进行矩阵分解。 2. 文档缺乏恕我直言(包括 LAPACK 的细节,除了更改#define 语句)。

如果有一个独立且易于使用的开源库,那就太好了。我已经遇到同样的问题 10 年了,这令人沮丧。有一次,我为 C 使用了 GSL,并围绕它编写了 C++ 包装器,但是使用现代 C++——尤其是利用表达式模板的优势——我们不应该在 21 世纪与 C 混为一谈。只是我的 tuppencehapenny。

【讨论】:

Armadillo 具有刻意的类似 Matlab 的语法,因此易于使用。我不确定您所说的“缺少文档......关于 LAPACK 的细节”是什么意思。该文档清楚地记录了所有用户可用的功能,以及如何使用它们的示例。关于 C++ 包装库的全部意义在于抽象出 LAPACK 的复杂性和冗长性。如果您想了解 Armadillo 如何调用 LAPACK,您可以随时浏览源代码。 关于Eigen中的QR分解,你是指Eigen2还是Eigen3?【参考方案4】:

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

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

很简单,它包括:

    基本向量-向量、向量-矩阵、 和矩阵-矩阵运算 矩阵分解(LU decomp、hermitian、sparse) 最小二乘拟合和特征值问题 稀疏线性系统求解器 非线性最小二乘求解器(信任区域) 加上 FFT 和卷积等信号处理例程 非常快速的随机数生成器(梅森扭曲) 更多……见:link text

缺点是 MKL API 可能非常复杂,具体取决于您需要的例程。您还可以查看他们的 IPP(集成性能基元)库,该库面向高性能图像处理操作,但范围非常广泛。

保罗

CenterSpace 软件、.NET 数学库、centerspace.net

【讨论】:

【参考方案5】:

我听说过关于Eigen 和NT2 的好消息,但也没有亲自使用过。还有Boost.UBLAS,我相信它有点长。 NT2 的开发人员正在构建下一个版本,旨在将其纳入 Boost,因此这可能很重要。

我的林。算法。需求不会超出 4x4 矩阵的情况,因此我无法评论高级功能;我只是指出一些选项。

【讨论】:

根据我的经验(更大的矩阵),Boost.UBLAS 用得更多。但是,当我查看它时,我不喜欢它(主要是因为文档),所以我专注于 Eigen。 Eigen 有一个geometry module,但我自己没用过。 Eigen 显然被 ROS(柳树车库)、Celestia、Koffice 和 libmv 使用。我看到一些关于 UBLAS 的讨论,但很难遇到使用它做广告的项目。 NT2 同上。你能详细说说你听到了什么好消息吗? 在 Boost 邮件列表中关于向 Boost 添加现代 LinAlg 库的讨论中 - Eigen 和 NT2 都被提及为可能的候选者,但只有 NT2 开发人员表示有兴趣追求它。两个图书馆看起来都不错。正如你所说,Eigen 更受欢迎,也更 C++-ish; NT2 旨在尽可能地模仿 MATLAB。【参考方案6】:

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

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

【讨论】:

【参考方案7】:

GLM 呢?

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

【讨论】:

嗯,它提供了图形编程矢量和矩阵。它引入了大量的开销来保持对 GLSL 的兼容(如果你可以在 GLSL 中做到这一点,大多数时候在 GLSL 中做到这一点会更好,尤其是在 GL 4.x 中),并且错过了许多图形编程原语(平截头体、AABB、BB、椭圆体)。它的调酒界面很肥胖。更好的选择是如果它具有通过一些代码生成生成的“.xyzz()”函数。当您必须对 opengl 应用程序进行原型设计并开始在更大的项目中显示其负面影响时,它是完美的。永远不要编写数学库。【参考方案8】:

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

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

【讨论】:

整个“如果你这样做,那么请确保......”这件事让我觉得有点危险。到目前为止,我已经两次遇到这些问题,我刚刚开始使用它。我真的希望不要让未来的开发人员因为了解每个库的各种特性而增加负担:特别是如果你每次有成员时不使用某些宏就会崩溃的对齐问题,以及它们已经为个人传播功能的事实跨多个标题的类。单独它可能不会阻止我选择它,但它发出了一点危险信号。 对齐,并且该宏仅在您使用 SSE 时才重要,这绝不是必需的。而且,如果您确实使用 SIMD,那么无论您使用什么库,这些问题都会出现。至少 Eigen 不只是崩溃,而是提供了直接指向问题的有意义的错误消息。 还有一种简单的方法可以避免对齐宏——使用指针或引用作为成员。 我认为这不是真的。我没有使用特殊的 SSE 选项,并且在将它与 stl 容器一起使用后发生了几次崩溃。是的,我知道它会为您提供有用的信息,并且是的,我知道有特殊说明,但这就是我的意思。我不想让其他开发人员对每个包含的库都有特殊说明。例如,不要通过价值传递的东西太多了。 我刚刚发现最新的开发分支有一些定义可以用来关闭对齐并避免相关问题。【参考方案9】:

好的,我想我知道你在寻找什么。正如 Reed Copsey 建议的那样,GGT 似乎是一个很好的解决方案。

就个人而言,我们推出了自己的小型库,因为我们经常处理有理点 - 大量有理 NURBS 和 Beziers。

事实证明,大多数 3D 图形库都使用没有投影数学基础的投影点进行计算,因为这就是您想要的答案。我们最终使用了 Grassmann 点,它具有坚实的理论基础并减少了点类型的数量。格拉斯曼点与人们现在使用的计算基本相同,具有稳健的理论。最重要的是,它让我们的思路更清晰,所以我们的 bug 更少。 Ron Goldman 在计算机图形学中写了一篇关于格拉斯曼点的论文,名为"On the Algebraic and Geometric Foundations of Computer Graphics"。

与您的问题没有直接关系,但读起来很有趣。

【讨论】:

这是故意开放式的,因为我不知道权衡是什么。可以公平地说,几何是我们主要关注的几何维度并不清楚。目前它是 2/3(2 + 时间)并且假设可能相当高(3dims + time + multi-dim-costmaps)。 我同意这个问题。例如,许多此类应用程序需要实时(一致的时间行为)性能,而许多其他应用程序则可以放弃一致性和/或速度以获得准确性。 那么您是说在您调查的库中,没有一个处理 NURBS 和 Beziers?不采用现有库之一并在其中构建 NURBS 和 Bezier 支持的任何特殊原因? 我想说的是,理性 NURBS 和 Beziers 使用理性控制点的次数比大多数 3D 应用程序多得多,因此我们犯了更多错误。通常,大多数 3d 应用程序只有在经过透视变换之后才有普通的 3d 点和向量。我们的许多算法必须能够正确处理加权/有理/投影和笛卡尔点,来回移动等。【参考方案10】:

FLENS

http://flens.sf.net

它还实现了很多LAPACK功能。

【讨论】:

【参考方案11】:

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

【讨论】:

截至 2019 年 12 月,链接已损坏

以上是关于什么是最广泛使用的 C++ 向量/矩阵数学/线性代数库,以及它们的成本和收益权衡? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

Pytorch之线性代数

线性代数精华——矩阵的特征值与特征向量

数学基础系列----矩阵矩阵的秩向量特征值与特征向量

线性代数好的外国教材

直观详解线性代数的本质

直观详解线性代数的本质