网格使用Eigen:MatrixX3f或std :: vector <vector3f>?</vector3f>

时间:2012-12-05 11:17:20

标签: c++ graphics gpu eigen

我在计算机图形项目中使用Eigen库,网格会经常更改。

对所有顶点位置,法线等使用动态特征矩阵有什么性能影响?

我应该使用:

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

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

我必须在每次更改后将网格数据复制到GPU,但据我了解,我可以使用memcpy以两种表示形式有效地完成此操作。

3 个答案:

答案 0 :(得分:3)

Vector可能会占用更多内存,因为它通常会分配比存储数据所需的空间更多的空间,每次调整大小时,vector都会调用Eigen::Vector3f的默认构造函数和析构函数。 AFAIK,默认的Eigen::Vector3f构造函数是空的,因此在发布版本中它将花费你零(但是由于这个和调试迭代​​器,你可能会遇到调试构建中的性能问题)。另一方面,Eigen::Matrix每次调整大小时都会重新分配内存(如果使用conservativeResize,它也会将内容复制为std::vector),这很慢。

但是,我仍然建议你使用矢量,因为它更方便。您可以动态添加元素,无需重新分配就可以调整大小,在向量上使用标准算法更简单。如果你想确定你的向量不会消耗比所需更多的内存,你可以使用这个技巧来调整它的大小:

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

或者查看shrink_to_fit

是的,您可以使用memcpy使用两种表示方式有效地复制数据。但是使用std::copy将在发布版本中以相同的性能执行相同的工作(有时它甚至被编译器替换为memcpy)。

但是,如果你对表现仍然不满意,这里有我自己做出的提示,在这种情况下作出决定:

  • 如果您要经常调整顶点数组的大小(添加或删除元素) - &gt;请使用std::vector以避免频繁重新分配。
  • 如果您在顶点数组中存储大量数据 - &gt;与Eigen::Matrix一起使用以避免过多的内存消耗。
  • 如果您对调试模式下的性能不满意(如果您经常处理顶点数组中的数据,这将很幸运) - &gt;使用Eigen::Matrixstl调试迭代器可能会破坏性能(仅适用于MSVC)

还要考虑boost::shared_array(scoped_array),它们专门用于存储大块数据而不占用额外的内存。在你的场景中使用它们更有意义。

答案 1 :(得分:1)

动态分配矩阵数组通常有两个问题:

  • 您将无法使用全局memcpy复制整个结构:在动态分配的矩阵的情况下(例如,您有std::vector<float*>而不是{ {1}}),你的数组只包含一系列指针,所有这些指针都指向内存中非常不同的位置。因此,执行std::vector<Eigen::Vector3f>只会复制指针而不是数据,并且没有办法改变它,因为你的元素在内存中不是连续的(只有它们的指针是)。相反,您需要浏览memcpy的每个元素,分别使用std::vectoroperator[]元素访问它。例如,在执行memcpy时,您将拥有memcpy(或类似的东西:它存储指针和多个行和列),而sizeof(Eigen::Matrix<float, Eigen::Dynamic, 3, Eigen::RowMajor>) = sizeof(void*) + 2*sizeof(int)因为它确实存储数据和没有指针。

  • 如果您需要经常创建和销毁矩阵,那么使用动态分配的矩阵执行此操作将会慢得多。固定大小的矩阵允许在堆栈上进行分配,这使得它更快。

答案 2 :(得分:1)

两种表示的内存布局完全相同。主要区别在于std :: vector&lt;&gt;如果您需要插入矢量或类似的东西,则更灵活。另一方面,矩阵&lt;。,3,Dynamic&gt;是一个特征对象,因此更容易对它执行某些操作,例如:

Matrix<.,3,Dynamic> data;
data = Affine3f(...) * data; // apply an affine transformation
data.colwise().norm(); // get the norm of each vectors
...