1

メッシュが頻繁に変更されるコンピューター グラフィックス プロジェクトでEigenライブラリを使用しています。

すべての頂点位置、法線などに動的固有行列を使用すると、パフォーマンスにどのような影響がありますか?

私は使用する必要があります:

Eigen::Matrix<float, Eigen::Dynamic, 3, Eigen::RowMajor> vertices;

また

std::vector<Eigen::Vector3f> vertices;

変更のたびにメッシュ データを GPU にコピーする必要がありますが、私が理解しているように、両方の表現で効率的に memcpy を使用してこれを行うことができます。

4

3 に答える 3

3

ベクターは通常、データを格納するために必要なスペースよりも多くのスペースを割り当て、ベクターはEigen::Vector3fサイズを変更するたびにデフォルトのコンストラクターとデストラクタを呼び出すため、おそらくより多くのメモリを消費します。私の知る限り、デフォルトのEigen::Vector3fコンストラクターは空であるため、リリース ビルドではコストがかかりません (ただし、これとデバッグ イテレーターが原因で、デバッグ ビルドでパフォーマンスの問題が発生する可能性があります)。反対に、Eigen::Matrixサイズを変更するたびにメモリを再割り当てします ( std::vectorconservativeResize を使用した場合と同様に、コンテンツもコピーします)。これは低速です。

ただし、より便利なので、ベクトルを使用することをお勧めします。要素を動的に追加し、再割り当てせずにサイズを変更できます。ベクターで標準アルゴリズムを使用する方が簡単です。ベクトルが必要以上にメモリを消費しないようにしたい場合は、次のトリックを使用してサイズを変更できます。

std::vector<Eigen::Vector3f> vertices;
vertices.swap( std::vector<Eigen::Vector3f>(size, Eigen::Vector3f()) );

または、shrink_to_fitを参照してください

はい、memcpy を使用して、両方の表現を使用してデータを効率的にコピーできます。しかし、を使用std::copyすると、リリース ビルドで同じパフォーマンスで同じ仕事ができます (場合によっては、コンパイラによって置き換えられることもありますmemcpy)。

ただし、それでもパフォーマンスに満足できない場合は、そのような場合に自分で決定を下すためのヒントを次に示します。

  • 頂点配列のサイズを頻繁に変更する場合 (要素の追加または削除) ->std::vector頻繁な再割り当てを避けるために使用します。
  • 頂点配列に大量のデータを格納する場合 ->Eigen::Matrix過度のメモリ消費を避けるために使用します。
  • デバッグ モードでのパフォーマンスに満足できない場合 (これは、頂点配列のデータを頻繁に処理する場合に幸いにも当てはまります) -> を使用するとEigen::Matrixstlデバッグ イテレータによってパフォーマンスが低下する可能性があります (MSVC の場合のみ当てはまります)。

また、boost::shared_array (scoped_array) も検討してください。これらは、余分なメモリを消費せずに大量のデータを保存するように特別に設計されています。それらを使用すると、シナリオでより理にかなっています。

于 2012-12-08T17:03:28.837 に答える
1

動的に割り当てられた行列の配列に関する一般的な 2 つの問題:

  • グローバルを使用して構造全体をコピーすることはできませんmemcpy。動的に割り当てられた行列の場合 (たとえば、 のstd::vector<float*>代わりに がありstd::vector<Eigen::Vector3f>ます)、配列には一連のポインターのみが含まれ、これらすべてのポインターは指すことができますメモリ内の非常に異なる場所に。したがって、を実行するmemcpyと、データではなくポインターのみがコピーされます。要素はメモリ内で連続していないため (ポインターのみが連続している)、それを変更する方法はありません。代わりに、 の各要素を調べて、と要素で別々std::vectorにアクセスする必要があります。たとえば、 を実行すると、(または同様のもの:ポインターと行と列の数が格納されます)、operator[]memcpymemcpysizeof(Eigen::Matrix<float, Eigen::Dynamic, 3, Eigen::RowMajor>) = sizeof(void*) + 2*sizeof(int)sizeof(Eigen::Vector3f) = 3*sizeof(float)ポインターではなく、実際にデータを格納するためです。

  • マトリックスを頻繁に作成および破棄する必要がある場合、動的に割り当てられたマトリックスでそれを行うと、はるかに遅くなります。固定サイズの行列を使用すると、割り当てをスタック上で行うことができるため、はるかに高速になります。

于 2012-12-06T07:33:11.623 に答える
1

両方の表現のメモリ レイアウトはまったく同じです。主な違いは、ベクトルなどを挿入する必要がある場合、 std::vector<> の方が柔軟であるということです。一方、 Matrix<.,3,Dynamic> は Eigen オブジェクトであるため、次のような操作を実行する方が簡単です。

Matrix<.,3,Dynamic> data;
data = Affine3f(...) * data; // apply an affine transformation
data.colwise().norm(); // get the norm of each vectors
...
于 2012-12-09T08:57:13.477 に答える