是否可以实现一个类,该类将C风格的指针作为模板参数并以提供的内存解析为静态Eigen矩阵?声明可能如下所示:
EIGEN_ALIGN16 double array[9];
CMatrix<double,3,3,array> :: m;
我对地图有所了解,但是下面提供的示例代码已经证明相比静态Eigen矩阵,使用它们会慢20%。
下面是前提条件:
- 我需要提供自己的C指针,这样我就可以高效地重用C代码而不需要进行拷贝。
- 结果矩阵应该对Eigen来说看起来是静态的,这样Eigen就可以像在编译时处理静态数组一样进行优化。请看我的上面的示例,在编译时我会同时提供矩阵大小(静态)和C指针。
- CMatrix 应该回退到 Eigen::Matrix。当未提供C数组的附加模板参数时,我将获得普通的Eigen矩阵。
- 我不打算制作完整的Eigen扩展。我的意思是,我不关心提供所有类型的检查以为其他用户提供一个整洁的扩展。我只想找到这个问题的最有效的解决方案。
通过添加一个新的构造函数实现一个解决方案是否可能?比如:
EIGEN_ALIGN16 double data[9];
Eigen::Matrix<double,3,3> m(data); //where data is NOT copied but used to replace the static allocation used by default.
在下面找到了我的用于基准测试Map和Matrix效率的代码。它是自包含的,您可以使用以下方式进行编译:
g++ -Ofast -DNDEBUG -DEIGEN_NO_MALLOC -I/path_to_my_Eigen benchmark1.cpp -o benchmark1 -lrt
这里是代码:
#include <Eigen/Eigen>
#include <bench/BenchTimer.h>
#include <iostream>
using namespace Eigen;
using namespace std;
//#define CLASSIC_METHOD
#define USE_MAPS
EIGEN_DONT_INLINE void classic(double VO[4], double AT[4][4], double VI[4])
{
for (int ii=0; ii<4; ii++)
{
VO[ii] = AT[ii][0] * VI[0] +
AT[ii][1] * VI[1] +
AT[ii][2] * VI[2] +
AT[ii][3] * VI[3];
}
};
template <typename OutputType, typename MatrixType, typename VectorType>
EIGEN_DONT_INLINE void modern(MatrixBase<OutputType>& VOE, const MatrixBase<MatrixType>& A44, const MatrixBase<VectorType>& VIE)
{
VOE.noalias() = A44.transpose()*VIE;
};
int main()
{
EIGEN_ALIGN16 double AT[4][4] = {0.1, 0.2, 0.3, 2.0, 0.2, 0.3, 0.4, 3.0, 0.3, 0.4, 0.5, 4.0, 0.0, 0.0, 0.0, 1.0};
EIGEN_ALIGN16 double VI[4] = {1, 2, 3, 4};
EIGEN_ALIGN16 double VO[4];
//Eigen matrices
#ifndef USE_MAPS
Matrix4d A44 = Matrix4d::MapAligned(AT[0]);
Vector4d VIE = Vector4d::MapAligned(VI);
Vector4d VOE(0,0,0,0);
#else
Map<Matrix4d,Aligned> A44(AT[0]);
Map<Vector4d,Aligned> VIE(VI);
Map<Vector4d,Aligned> VOE(VO);
// Map<Matrix4d> A44(AT[0]);
// Map<Vector4d> VIE(VI);
// Map<Vector4d> VOE(VO);
#endif
#ifdef EIGEN_VECTORIZE
cout << "EIGEN_VECTORIZE defined" << endl;
#else
cout << "EIGEN_VECTORIZE NOT defined" << endl;
#endif
cout << "VIE:" << endl;
cout << VIE << endl;
VI[0] = 3.14;
cout << "VIE:" << endl;
cout << VIE << endl;
BenchTimer timer;
const int num_tries = 5;
const int num_repetitions = 200000000;
#ifdef CLASSIC_METHOD
BENCH(timer, num_tries, num_repetitions, classic(VO, AT, VI));
std::cout << Vector4d::MapAligned(VO) << std::endl;
#else
BENCH(timer, num_tries, num_repetitions, modern(VOE, A44, VIE));
std::cout << VOE << std::endl;
#endif
double elapsed = timer.best();
std::cout << "elapsed time: " << elapsed*1000.0 << " ms" << std::endl;
return 0;
}
Eigen::MatrixBase
的数据在Eigen::DenseStorage
中。也许你应该先看一下Eigen/DenseStorage.h
,了解你应该如何替换其默认存储模式为你设计的存储模式。无论如何,如果你想扩展 Eigen 的功能,你的“快速而肮脏”的计划都失败了,因为你肯定需要制作一个“正确的”Eigen扩展... - Massa