我在计算机图形项目中使用Eigen库,网格会经常更改。
对所有顶点位置,法线等使用动态特征矩阵有什么性能影响?
我应该使用:
Eigen::Matrix<float, Eigen::Dynamic, 3, Eigen::RowMajor> vertices;
或
std::vector<Eigen::Vector3f> vertices;
我必须在每次更改后将网格数据复制到GPU,但据我了解,我可以使用memcpy以两种表示形式有效地完成此操作。
答案 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
)。
但是,如果你对表现仍然不满意,这里有我自己做出的提示,在这种情况下作出决定:
std::vector
以避免频繁重新分配。Eigen::Matrix
一起使用以避免过多的内存消耗。Eigen::Matrix
,stl
调试迭代器可能会破坏性能(仅适用于MSVC)还要考虑boost::shared_array(scoped_array),它们专门用于存储大块数据而不占用额外的内存。在你的场景中使用它们更有意义。
答案 1 :(得分:1)
动态分配矩阵数组通常有两个问题:
您将无法使用全局memcpy
复制整个结构:在动态分配的矩阵的情况下(例如,您有std::vector<float*>
而不是{ {1}}),你的数组只包含一系列指针,所有这些指针都指向内存中非常不同的位置。因此,执行std::vector<Eigen::Vector3f>
只会复制指针而不是数据,并且没有办法改变它,因为你的元素在内存中不是连续的(只有它们的指针是)。相反,您需要浏览memcpy
的每个元素,分别使用std::vector
和operator[]
元素访问它。例如,在执行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
...