我使用Eigen进行类似于Cholesky更新的操作,这意味着在固定大小矩阵(通常是Matrix4d)的列上有很多AXPY(加上乘以标量)。简而言之,访问Matrix 4的列比使用Vector 4贵3倍。
通常,以下代码:
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的向量。
此外,在第一行代码中花费的时间不依赖于矩阵存储组织(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;
}
答案 0 :(得分:1)
正如我在评论中所说,生成的程序集对于这两个函数完全相同。
问题在于,L4s
比z4s
大4倍,你的基准是有偏见的,因此你在矩阵的情况下比在矢量情况下得到更多的缓存未命中。