特征:缓慢访问Matrix 4的列

时间:2016-11-16 17:15:48

标签: c++ matrix eigen

我使用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;
}

1 个答案:

答案 0 :(得分:1)

正如我在评论中所说,生成的程序集对于这两个函数完全相同。

问题在于,L4sz4s大4倍,你的基准是有偏见的,因此你在矩阵的情况下比在矢量情况下得到更多的缓存未命中。