我使用Eigen进行类似于Cholesky更新的操作,这意味着在固定大小矩阵(通常是Matrix4d)的列上存在大量AXPY(总和加上标量乘)。简而言之,它是3倍更昂贵的访问的矩阵4的列比到Vector 4.Eigen:对矩阵的列访问速度很慢4
典型地,下面的代码:
for(int i=0;i<4;++i) L.col(0) += x*y[i];
比下面的代码少3倍高效:
for(int i=0;i<4;++i) l4 += x*y[i];
,其中L是典型的大小为4,X,Y的一个矩阵和L4 4.
此外大小的矢量,在第一行代码所花费的时间不依赖于米atrix存储组织(ColMajor的RowMajor)。
在Intel i7(2.5GHz)上,向量操作大约需要0.007us,矩阵操作需要0.02us(通过重复100000次同样的操作完成定时)。我的应用程序需要数千次这样的操作,希望远低于毫秒。
问题:在访问我的4x4矩阵的列时,我做了一些不正确的事情?有什么需要做的,使第一行代码更有效率?用于定时
完整代码如下:
#include <iostream>
#include <Eigen/Core>
#include <vector>
#include <sys/time.h>
typedef Eigen::Matrix<double,4,1,Eigen::ColMajor> Vector4;
//typedef Eigen::Matrix<double,4,4,Eigen::RowMajor,4,4> Matrix4;
typedef Eigen::Matrix<double,4,4,Eigen::ColMajor,4,4> Matrix4;
inline double operator- ( const struct timeval & t1,const struct timeval & t0)
{
/* TODO: double check the double conversion from long (on 64x). */
return double(t1.tv_sec - t0.tv_sec)+1e-6*double(t1.tv_usec - t0.tv_usec);
}
void sumCols(Matrix4 & L,
Vector4 & x4,
Vector4 & y)
{
for(int i=0;i<4;++i)
{
L.col(0) += x4*y[i];
}
}
void sumVec(Vector4 & L,
Vector4 & x4,
Vector4 & y)
{
for(int i=0;i<4;++i)
{
//L.tail(4-i) += x4.tail(4-i)*y[i];
L += x4 *y[i];
}
}
int main()
{
using namespace Eigen;
const int NBT = 1000000;
struct timeval t0,t1;
std::vector< Vector4> x4s(NBT);
std::vector< Vector4> y4s(NBT);
std::vector< Vector4> z4s(NBT);
std::vector< Matrix4> L4s(NBT);
for(int i=0;i<NBT;++i)
{
x4s[i] = Vector4::Random();
y4s[i] = Vector4::Random();
L4s[i] = Matrix4::Random();
}
int sample = int(z4s[55][2]/10*NBT);
std::cout << "*** SAMPLE = " << sample << std::endl;
gettimeofday(&t0,NULL);
for(int i=0;i<NBT;++i)
{
sumCols(L4s[i], x4s[i], y4s[i]);
}
gettimeofday(&t1,NULL);
std::cout << (t1-t0) << std::endl;
std::cout << "\t\t\t\t\t\t\tForce check" << L4s[sample](1,0) << std::endl;
gettimeofday(&t0,NULL);
for(int i=0;i<NBT;++i)
{
sumVec(z4s[i], x4s[i], y4s[i]);
}
gettimeofday(&t1,NULL);
std::cout << (t1-t0) << std::endl;
std::cout << "\t\t\t\t\t\t\tForce check" << z4s[sample][2] << std::endl;
return -1;
}
你是如何编译的? – Joel
g ++ -O3 -I/usr/include/eigen3。我在Linux 14.04上,3.2.0 Eigen和4.8.4 gcc。我也在同一台电脑上获得类似的结果与铛。 – NMsd
我无法复制。生成的ASM对于每个版本都完全相同。你可以用'g ++ -O3 -DNDEBUG -s'自己检查并在生成的asm文件中搜索'sumCols'和'sumVec'。 – ggael