最も広く使用されているC ++ベクトル/行列数学/線形代数ライブラリ、およびそれらのコストと利益のトレードオフは何ですか?[閉まっている]


242

多くのプロジェクトは、マトリックス計算を行う必要性にゆっくりと遭遇し、最初にいくつかのベクトルクラスを構築し、機能が徐々に追加されて、中途半端なカスタム線形代数ライブラリの構築に巻き込まれ、それに依存するようになるのではないかと思われます。

いくつかの接線方向に関連するライブラリ(OpenCV、OpenSceneGraphなど)への依存を構築していない間は、それを回避したいと思います。

そこに一般的に使用される行列数学/線形代数ライブラリは何ですか、なぜ別のものを使用することにしたのですか?何らかの理由で使用しないようにアドバイスされるものはありますか?私はこれを幾何学的/時間のコンテキスト*(2,3,4 Dim)*で具体的に使用していますが、将来的にはより高次元のデータを使用する可能性があります。

API、速度、メモリ使用量、幅/完全性、狭さ/特異性、拡張性、成熟度/安定性のいずれかに関する違いを探しています。

更新

私は非常に満足しているEigen3を使用することになりました。


2
OSGとOpenCVについて言及したので、3Dグラフィックタイプのベクトル/行列、つまり3x3と4x4の行列が必要なだけだと思います。私はそれに基づいて答えを出しましたが、これをどの程度正確に使用しているかを指定したい場合があります-行列解法が必要ですか?高次元の行列の数学ですか?等
リードコプシー

現在、私は2Dジオメトリベースのものだけを実行していますが、仮に2Dデータに対して3x3演算が必要になる場合があり、3Dデータ、つまり4x4演算が必要かどうかは不明です。全社共通のライブラリを利用したい。私はトレードオフがどうなるのかについての良識がありません。より一般的な方が良いでしょうが、どのコストで問題なのでしょう。
Catskul

1
幾何学的な変換だけを行う場合は、回答で述べたように、GGTを確認することをお勧めします。それは非常に完全ですが、実際には何も行いません。そのため、非常にクリーンで簡単なオプションです。BLASとLAPACKは、科学的および数学的な幾何変換ではなく、複雑なマトリックスソリューション(つまり、50x50マトリックス、スパースマトリックスなど)に適しています。
リードコプシー、

回答:


114

このためにGeneric Graphics Toolkitに落ち着いたプロジェクトがかなりあります。そこにあるGMTLは素晴らしいです-それは非常に小さく、非常に機能的で、非常に信頼できるほど広く使用されています。OpenSG、VRJuggler、および他のプロジェクトはすべて、独自の手作業のvertor / matrix数学の代わりにこれを使用するように切り替えました。

私はそれが非常に良いことを発見しました-それはテンプレートを介してすべてを行うので、それは非常に柔軟で、非常に高速です。


編集:

コメントのディスカッションと編集の後、特定の実装のメリットとデメリット、および状況に応じてどちらかを選択する理由について、もう少し情報を捨てると思いました。

GMTL -

利点:グラフィックエンジン用に特別に設計されたシンプルなAPI。他のパッケージにはない、レンダリング向けの多くのプリミティブタイプ(プレーン、AABB、複数の補間を含むクォータニオンなど)が含まれています。非常に低いメモリオーバーヘッド、非常に高速で使いやすい。

欠点:APIは、レンダリングとグラフィックスに特に重点を置いています。汎用(NxM)行列、行列の分解と解法などは含まれていません。これらは従来のグラフィックス/ジオメトリアプリケーションの領域外にあるためです。

アイゲン -

利点:Clean API、かなり使いやすい。四元数と幾何学的変換を備えたGeometryモジュールが含まれています。メモリのオーバーヘッドが少ない。大規模なNxN行列およびその他の汎用数学ルーチンの完全で高性能な解法。

欠点:あなたが望んでいるよりも少し広い範囲かもしれません(?)。GMTLと比較すると、ジオメトリ/レンダリング固有のルーチンが少ない(つまり、オイラー角の定義など)。

IMSL -

利点:非常に完全な数値ライブラリ。非常に高速(おそらく最速のソルバー)。はるかに大きく、最も完全な数学的API。商業的にサポートされ、成熟し、安定しています。

欠点:コスト-安価ではありません。ジオメトリック/レンダリング固有のメソッドはほとんどないため、線形代数クラスの上に独自のメソッドを配置する必要があります。

NT2 -

利点:MATLABに慣れている場合に、より身近な構文を提供します。大きな行列などの完全な分解と解決を提供します。

欠点:数学的、焦点を絞ったレンダリングではない。おそらくアイゲンほどパフォーマンスが良くない。

ラパック -

利点:非常に安定した実績のあるアルゴリズム。ずっと周りにいる。完全な行列解法など。不明瞭な数学の多くのオプション。

欠点:一部のケースではそれほどパフォーマンスが良くない。Fortranから移植され、使用法が変わったAPIになっています。

個人的に、私にとって、それは単一の質問に帰着します-これをどのように使用する予定ですか?レンダリングとグラフィックスだけに重点を置いている場合は、Generic Graphics Toolkitが気に入っています。これは、パフォーマンスが高く、独自の実装をしなくても、すぐに使用できる多くの便利なレンダリング操作をサポートするためです。汎用の行列解法(つまり、大きな行列のSVDまたはLU分解)が必要な場合は、Eigenを使用します。これは、それを処理し、いくつかの幾何学的演算を提供し、大規模な行列ソリューションで非常にパフォーマンスが高いためです。独自のグラフィックス/幾何学的演算(行列/ベクトルの上に)をさらに記述する必要があるかもしれませんが、それは恐ろしいことではありません。


GMTLを決定する前に他のライブラリを評価しましたか?表面的な比較から、アイゲンはよりよくサポートされていると私は信じるようになりましたが、それはそれぞれのウェブサイトをレビューすることに基づいています。どちらか一方が他方よりも優れている点を知っていますか?
Catskul

アイゲンもうまくいきます。調査を行った時点では成熟していませんでしたが、現時点では良い選択肢になると思います。GMTLはかなり広く使用されており、使用することを決定したとき、非常に成熟していてしっかりしていた。
リードコプシー

私の質問は非常に重要な部分に要約すると思います。主観的に「これは見栄えがいい」のように選択したのか、それとも特定の機能(api、速度、メモリ使用、幅、狭さ、拡張性)が違いをもたらしたのか。成熟度はこの基準に該当すると思いますが、成熟度が唯一の指標である場合は、BLASまたはLAPACKベースのオプションを選択したと思います。
Catskul

私は複数のオプションを試してからこれを選択し、それに基づいて、パフォーマンス、使いやすさ、およびランタイム/コンパイル時間のオーバーヘッドを低くしました。アイゲンはその時よりもずっとよく見えるので、それらの間で判断することはできません。しかし、私はGMTLを私たちの用途に使用して非常に満足しています。
リードコプシー

それが、私がGMTLを気に入って使用した理由の1つです。使用するのは非常に自然で、操作も非常に簡単でした。また、幾何学的変換とクォータニオン回転を直接処理することだけが心配だったため、この場合は必要なすべてをサポートしました。
リードコプシー

38

ですから、私はかなり批判的な人物です。図書館に投資するつもりなら、自分が何に興味を持っているのかをよく知っています。私は精査するとき批判に重きを置き、お世辞を軽くする方が良いと思います。何が悪いのかというと、正しいことよりも未来に多くの意味があります。だから、私はここで少し行き過ぎて、私を助けたであろう種類の答えを提供するつもりです、そして私はこの道を進むかもしれない他の人たちを助けたいと思います。これは、私がこれらのライブラリで行ったほとんどのレビュー/テストに基づいていることに注意してください。ああ、私はリードから肯定的な説明の一部を盗みました。

Eigen2の安全性の悪さが大きすぎるため、特異性にもかかわらずGMTLを採用したことを述べます。しかし、私は最近、Eigen2の次のリリースには、アライメントコードを遮断して安全にする定義が含まれることを知りました。だから私は切り替えるかもしれません。

更新:Eigen3に切り替えました。その特異性にもかかわらず、その範囲と優雅さは無視するのが難しすぎて、危険にさせる最適化は、defineでオフにすることができます。

Eigen2 / Eigen3

利点:LGPL MPL2、クリーンで適切に設計されたAPI、かなり使いやすい。活気のあるコミュニティでよく維持されているようです。メモリのオーバーヘッドが少ない。ハイパフォーマンス。一般的な線形代数用に作成されていますが、優れた幾何学的機能も利用できます。すべてのヘッダーライブラリ。リンクは不要です。

愚劣/欠点:(これらの一部/すべては、現在の開発ブランチ Eigen3で利用可能な定義によって回避できます)

  • 安全でないパフォーマンスの最適化では、ルールを慎重にフォローする必要があります。ルールに従わないと、クラッシュが発生します。
    • 安全に値渡しすることはできません
    • メンバーとしてEigen型を使用するには、特別なアロケーターのカスタマイズが必要です(またはクラッシュします)
    • stlコンテナータイプで使用し、場合によっては他のテンプレートで特別な割り当てのカスタマイズが必要です(そうしないとクラッシュします)
    • 特定のコンパイラーは、関数呼び出し(GCCウィンドウ)でのクラッシュを防ぐために特別な注意が必要です。

GMTL

メリット:グラフィックエンジン用に特別に設計されたLGPL、Fairly Simple API。他のパッケージにはない、レンダリング向けの多くのプリミティブタイプ(プレーン、AABB、複数の補間を含むクォータニオンなど)が含まれています。非常に低いメモリオーバーヘッド、非常に高速で使いやすい。すべてヘッダーベースで、リンクは不要です。

愚劣/欠点:

  • APIは風変わりです
    • 別のlibの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にあります。VecOps.hのcross(vec&、vec&、vec&)、Generate.hの[make] cross(vec&、vec&)
  • 未成熟/不安定なAPI; まだ変化しています。
    • たとえば、「cross」が「VecOps.h」から「Generate.h」に移動し、名前が「makeCross」に変更されました。ドキュメントの例は、もはや存在しない古いバージョンの関数を参照しているため失敗します。

NT2

彼らはコンテンツよりもウェブページのフラクタル画像ヘッダーに興味を持っているように見えるため、わかりません。本格的なソフトウェアプロジェクトというよりは、学術プロジェクトのように見えます。

2年以上前の最新リリース。

どうやら英語のドキュメントがないようですが、フランス語のどこかに何かがあると思われます。

カントは、プロジェクトの周りのコミュニティの痕跡を見つけます。

ラパックとブラス

利点:古くて成熟しています。

欠点:

  • 恐ろしいAPIを備えた恐竜の古さ

1
Eigen整合アサートについて:小さなデータセットのSSE(1,2,3または4)演算から高いパフォーマンスを引き出すには、整合データが絶対に必要です。調整されていないロード/ストア操作ははるかに遅くなります。整列または非整列のロード/ストアの決定にも時間がかかります。「一般目的」の実装では、インターフェースを「整列」操作と「非整列」操作に分けない限り、誰にとっても正しいことを実行するのは本当に大変なことです。
Joris Timmermans、

@Catskul Eigen3を使用したいと思います。「安全でなくなる最適化は、定義によって無効にできる」について詳しく説明していただけませんか?Eigen2でリストする他の問題は、アライメントの問題に関連するトピックドキュメントで詳細に説明されています。私はこれらの問題に耐えることができます。
アリ

安全に関する問題私はすべてのアラインメントに関連して言及していて、Eigen2から同じです。Eigen2で問題がなければ、Eigen3で問題ありません。
Catskul

2
BLASとLAPACKは実際にはライブラリではなく、仕様/ APIです。netlibまたは他の実装(ATLASやOpenBLASなど)による最初の実装に言及したかもしれません。
Foad 2017

12

それが価値があるもののために、私はアイゲンとアルマジロの両方を試しました。以下は簡単な評価です。

固有の利点:1.完全に自己完結型-外部のBLASまたはLAPACKに依存しません。2.適切なドキュメント。3.まだ高速ではありませんが、テストには入れていません。

短所:QRアルゴリズムは、R行列が上三角に埋め込まれた単一の行列のみを返します。マトリックスの残りの部分がどこから来るのかわからず、Qマトリックスにアクセスできません。

Armadilloの利点:1.幅広い分解とその他の機能(QRを含む)。2.かなり高速(式テンプレートを使用)ですが、繰り返しますが、実際には高次元にプッシュしていません。

短所:1.マトリックス分解は、外部のBLASやLAPACKに依存します。2.文書にIMHOが欠如している(#defineステートメントを変更する以外のLAPACKに関する詳細を含む)。

自己完結型で簡単に使用できるオープンソースライブラリが利用できると便利です。私はこの同じ問題に10年間遭遇しました、そしてそれはイライラします。ある時点で、私はCにGSLを使用し、その周りにC ++ラッパーを作成しましたが、最近のC ++では(特に式テンプレートの利点を使用して)、21世紀のCをいじる必要はありません。ちょうど私のtuppencehapenny。


2
Armadilloは意図的にMatlabのような構文を持っているので、簡単に使用できます。「ドキュメントにLAPACKに関する詳細が欠けています...」についてどういう意味かわかりません。ドキュメントには、ユーザーが使用できるすべての機能と、それらの使用例が明確に記載されています。C ++ラッパーライブラリに関する重要な点は、LAPACKの複雑さと冗長性を抽象化することです。ArmadilloがLAPACKを呼び出す方法を確認したい場合は、いつでもソースを参照できます。
mtall

固有値のQR分解について、固有値2または固有値3を意味しますか?
2013

11

インテルプロセッサーで高性能の行列/線形代数/最適化を探している場合は、インテルのMKLライブラリを調べます。

MKLは、実行時のパフォーマンスが高速になるように慎重に最適化されています。その多くは、非常に成熟したBLAS / LAPACK fortran標準に基づいています。そして、そのパフォーマンスは、利用可能なコアの数に比例します。利用可能なコアを使用したハンズフリーのスケーラビリティはコンピューティングの未来であり、マルチコアプロセッサをサポートしない新しいプロジェクトでは数学ライブラリを使用しません。

非常に簡単に言えば、次のものが含まれます。

  1. 基本的なベクトル-ベクトル、ベクトル-マトリックス、およびマトリックス-マトリックスの演算
  2. 行列分解(LU decomp、hermitian、sparse)
  3. 最小二乗フィッティングと固有値問題
  4. スパース線形システムソルバー
  5. 非線形最小二乗ソルバー(信頼領域)
  6. さらに、FFTやたたみ込みなどの信号処理ルーチン
  7. 非常に高速な乱数ジェネレーター(メルセンヌツイスト)
  8. もっともっと...参照:リンクテキスト

欠点は、必要なルーチンによってはMKL APIが非常に複雑になる可能性があることです。また、高性能の画像処理操作向けのIPP(Integrated Performance Primitives)ライブラリを参照することもできますが、それでもかなり広範です。

ポール

CenterSpace Software、.NET数学ライブラリ、centerspace.net


8

EigenNT2について良いことは聞いたことがありますが、個人的にも使用していません。Boost.UBLASあり、これは少し長くなっていると思います。NT2の開発者は、Boostに組み込むことを意図して次のバージョンを構築しているので、それが何かを意味するかもしれません。

私の林。alg。ニーズは4x4マトリックスの場合を超えないので、高度な機能についてはコメントできません。私はいくつかのオプションを指摘しています。


私の経験では(より大きな行列)、Boost.UBLASがより多く使用されています。しかし、調べてみると、それが気に入らなかったので(主にドキュメンテーションのため)、Eigenに集中しました。Eigenにはジオメトリモジュールがありますが、私は自分で使用していません。
Jitse Niesen

Eigenは明らかにROS(willow garage)、Celestia、Koffice、およびlibmvで使用されています。私はUBLASについておしゃべりをいくつか見ますが、それを使用して宣伝するプロジェクトに出くわすのに苦労しました。NT2の同上。聞いたことのある良いことについて詳しく教えてください。
Catskul

最新のLinAlgライブラリをBoostに追加することに関するBoostメーリングリストでの議論の中で、EigenとNT2の両方が候補として挙げられましたが、それを追求することに関心を示したのはNT2開発者だけでした。どちらのライブラリもまともです。あなたが言ったように、アイゲンはもう少し人気があり、C ++っぽいです。NT2は、MATLABをできるだけ模倣するように設計されています。
ジェフハーディ

8

私はこのトピックに慣れていないため、多くのことを言うことはできませんが、BLASは科学計算における標準です。BLASは実際にはAPI標準であり、多くの実装があります。正直なところ、どの実装が最も人気があるのか​​、またはその理由はわかりません。

一般的な線形代数演算(解法システム、最小二乗回帰、分解など)も実行できるようにしたい場合は、LAPACKを調べてください。


7

何についてのGLM

OpenGLシェーディング言語(GLSL)仕様に基づいており、MITライセンスでリリースされています。明らかにグラフィックプログラマを対象としています


まあ、それはグラフィックプログラミングベクトルと行列を提供します。GLSLに準拠するためにかなりのオーバーヘッドが発生し(GLSLで実行できる場合、ほとんどの場合GLSLで実行するのが特にGL 4.xの方が優れています)、多くのグラフィックスプログラミングプリミティブ(錐台、AABB、BB、楕円体)がありません。 )。そのスウィズルインターフェイスは肥満です。はるかに優れた代替案は、コード生成で ".xyzz()"関数を生成した場合です。openglアプリケーションのプロトタイプを作成する必要があり、より大きなプロジェクトでそのマイナス面を示し始めたときに最適です。数学ライブラリをコーディングしないでください。
CoffeDeveloper 2015

5

Eigenへの投票を追加します。さまざまなライブラリからこのライブラリに多くのコード(3Dジオメトリ、線形代数、微分方程式)を移植しました。ほとんどすべての場合で、パフォーマンスとコードの読みやすさの両方が向上しています。

言及されなかった1つの利点:SSEをEigenで使用するのは非常に簡単です。これにより、2Dから3Dの操作のパフォーマンスが大幅に向上します(すべてを128ビットに埋め込むことができます)。


1
全体の「これを行う場合は、必ず確認してください...」ということは、少し赤い旗のように私を襲います。これまでのところ、私はこれらの問題に2回遭遇し、それを使い始めました。私は本当に、含まれている各ライブラリのあらゆる種類の特異性を知るために将来の開発者に負担をかけないように望んでいました:特に、メンバーがいるたびに特定のマクロを使用しないとクラッシュする整列の問題、およびそれらが個々に機能を広げているという事実複数のヘッダーにわたるクラス。単独でそれを選択することを妨げないかもしれませんが、それは少し赤い旗を送られました。
Catskul 2009

1
アラインメントとそのマクロは、SSEを使用する場合にのみ重要です。SSEを使用する必要はありません。また、SIMDを使用すると、使用するライブラリに関係なく、これらの問題が発生します。少なくともEigenはクラッシュするだけでなく、問題を直接指摘する意味のあるエラーメッセージを提供します。
ima

そして、整列マクロを回避する簡単な方法があります-メンバーとしてポインターまたは参照を使用します。
ima

1
私はそれが本当だとは思いません。特別なSSEオプションを使用せず、stlコンテナーで使用した後、いくつかのクラッシュが発生しました。はい、それはあなたに役立つメッセージを与えることを知っています、そして、はい、私は特別な指示があることを知っていますが、それが私のポイントです。含まれているライブラリごとに特別な指示を他の開発者に課したくありません。たとえば、値渡ししないことは多すぎます。
Catskul 2009

最近の開発ブランチには、アラインメントをオフにして関連する問題を回避するために使用できるいくつかの定義があることがわかりました。
Catskul

4

さて、私はあなたが探しているものを知っていると思います。Reed Copseyが示唆したように、GGTはかなり良いソリューションのようです。

個人的には、合理的なポイント、つまり多くの合理的なNURBSとベジエを扱うため、独自の小さなライブラリを作成しました。

ほとんどの3Dグラフィックライブラリは、射影演算の根拠のない射影点を使用して計算を行うことがわかります。最終的には、グラスマン点を使用することになりました。グラスマン点は、理論上の根拠がしっかりしており、点タイプの数が減っています。グラスマン点は、基本的に人々が現在使用しているのと同じ計算であり、堅牢な理論の利点があります。最も重要なのは、それによって私たちの心の中で物事がより明確になるため、バグが少なくなります。ロンゴールドマンは、グラフィックスの代数的および幾何学的基礎について」と呼ばれる、コンピュータグラフィックスのグラスマンポイントに関する論文を書きました。

あなたの質問に直接関係はありませんが、興味深い読み物です。


私はトレードオフが何であるかを知らないという点で、意図的に自由回答です。幾何学が私たちの主な関心事であると言っても、幾何学の次元は明確ではありません。現在は2/3(2 +時間)であり、仮に非常に高くなる可能性があります(3dims +時間+ multi-dim-costmaps)。
Catskul

私はその質問に同意します。たとえば、この種のアプリケーションの多くは、リアルタイム(一貫した時間動作)のパフォーマンスを必要としますが、他の多くのアプリケーションは、正確さのために一貫性や速度を放棄するだけで十分です。
TED

では、調査したライブラリのうち、NURBSとBeziersを処理したものはないと言っているのですか。既存のライブラリのいずれかを使用せず、それに沿ってNURBSおよびBezierサポートを構築する特別な理由はありますか?
Catskul 2009

私が言おうとしていたのは、有理NURBSとベジエは、ほとんどの3Dアプリケーションよりも有理コントロールポイントをはるかに多く使用するため、より多くの間違いを犯していたということです。通常、ほとんどの3Dアプリには、遠近法変換を通過するまで、バニラ3Dポイントとベクターしかありません。私たちのアルゴリズムの多くは、正しくなど、背中を行くと述べ、/ /合理的な射影とデカルトの点を加重処理するためにできるようにする必要があります
tfinniga


0

このライブラリは非常にシンプルで機能的であることがわかりました(http://kirillsprograms.com/top_Vectors.php)。これらは、C ++テンプレートを介して実装されたベアボーンベクトルです。派手なものはありません-ベクトルで必要なこと(加算、減算、乗算、ドットなど)だけです。


1
2019年12月の時点で、リンクは残念ながら壊れています
10762409は、Reinstate Monica
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.