使用 eigen3 将多个连续布置的 Vector3d 乘以 Matrix4d。
显然,我对矩阵的不同大小有疑问。
为了解决这个问题,我在磁盘上添加了 w 部分以在 Vector4d 上进行操作,但我想避免它以节省每个向量的双精度大小。
代码:
#include <array>
#include <eigen3/Eigen/Geometry>
#include <iostream>
using namespace std;
#define M 4
int main (){
#if M == 4
auto arr = std::to_array( {1., 2., 3., 1., 4., 5., 6., 1.} );
Eigen::Map <Eigen::MatrixXd> v( arr.data(), 4, 2 );
#elif M == 3
auto arr = std::to_array( {1., 2., 3., 4., 5., 6.} );
Eigen::Map <Eigen::MatrixXd> v( arr.data(), 3, 2 );
#endif
// This is just an example matrix
// I get a different one by parameter
// in the real code.
Eigen::Matrix4d w;
w.setIdentity();
w( 0, 3 ) = 10;
w( 1, 3 ) = 20;
cout << v.matrix() << "\n\n";
cout << w.matrix() << "\n\n";
auto res = w * v;
std::cout << res.matrix() << std::endl;
}
有没有办法让 Eigen 为我的 v 矩阵添加 w 部分,或者当 M == 3 时我应该将 w 部分存储在磁盘上,浪费空间?
我想谈谈以下几个方面:
从性能角度来看,使用
Vector4d
更好。对于 AVX2,这直接映射到单个 YMM 寄存器。使用 SSE 或其他矢量化硬件,它也可以很好地工作,例如作为两个 128 位向量。一般来说,二或四的倍数会以牺牲一些内存为代价获得更好的性能。
如果您仍然想使用
Vector3d
或相应的矩阵,Eigen 专门为此提供了 homogeneous
方法。所以这应该对你有用:
res = w * v.colwise().homogeneous();
MatrixXd
对于这样的应用程序,您应该使用固定在一维的矩阵类型定义。这告诉 Eigen 使用最适合小型、固定大小的向量/矩阵的专用代码。当你这样写时,你会得到更好的性能:
Eigen::Map<Eigen::Matrix4Xd> v( arr.data(), 4, 2 );
或者因为你似乎更喜欢
auto
,你可以使用这个:
auto v = Eigen::Matrix4Xd::Map(arr.data(), 4, 2);
第二个选项是首选,因为您可以给它一个
const
指针,并且返回类型将为 Eigen::Map<const Eigen::Matrix...>
而无需编写更长的类型。
auto
请阅读本手册的常见陷阱部分。您的行
auto res = w * v
不计算矩阵。它存储一个 expression 对象,该对象将按需计算为矩阵乘法。至关重要的是,它包含指向输入数据的指针,当内存被释放或重用时,这可能会导致内存安全问题。它还可能导致重复评估,而不仅仅是一次评估。
要么像这样专门分配给一个新矩阵:
Eigen::Matrix4Xd res = w * v;
或者像这样:
auto res = (w * v).eval();
matrix()
方法更多的旁注,但像
cout << res.matrix()
这样的东西是不必要的。 matrix()
及其对应物 array()
的存在是为了在 Eigen::Array
和 Eigen::Matrix
类型之间进行转换,以便您可以对同一对象使用两种操作风格。特别是对于 cout
来说应该没有区别。