为什么特征向量点比循环手动慢

时间:2014-09-17 13:45:00

标签: c++ performance eigen

我是eigen的新手。

我测试了本征的矢量点性能,发现它比手动循环慢。

代码如下:

#include <Eigen/Dense>
#include <iostream>
#include <vector>

int main()
{
  Eigen::VectorXf neu1 = Eigen::VectorXf::Random(100000000);
  std::vector<float> x(100000000);

  for(int i = 0; i < 100000000; ++i)
    x[i] = neu1[i];

  clock_t t1 = clock();
  float r = 0.0f;
  for(int i = 0; i < 100000000; ++i)
    r += x[i]*x[i];

  clock_t t2 = clock();
  std::cout<<"time: "<<t2-t1<<std::endl;

  t1 = clock();
  r = neu1.dot(neu1);
  t2 = clock();
  std::cout<<"time: "<<t2-t1<<std::endl;
}

结果是:

g++ test.cpp -otest -I/usr/local/include/eigen/
time: 1070000
time: 1910000

g++ test.cpp -otest -I/usr/local/include/eigen/ -Ofast -march=native
time: 0
time: 50000

而且,#define EIGEN_NO_DEBUG似乎没有效果。

我认为应该对eigen进行优化,并且没有理由比循环慢。

我做错了吗?

或者,我如何优化本征绩效?

THX

2 个答案:

答案 0 :(得分:4)

您没有对第一次计算的结果做任何事情,之后又分配给它。第一个计算完全优化。您可以通过在计算后打印r的值来解决此问题:

#include <iostream>
#include <vector>
#include <eigen3/Eigen/Core>
#include <time.h>

int main()
{
  Eigen::VectorXf neu1 = Eigen::VectorXf::Random(100000000);
  std::vector<float> x(100000000);

  for(int i = 0; i < 100000000; ++i)
    x[i] = neu1[i];

  clock_t t1 = clock();
  float r = 0.0f;
  for(int i = 0; i < 100000000; ++i)
    r += x[i]*x[i];

  clock_t t2 = clock();
  std::cout<<"time: "<<t2-t1<<std::endl;
  std::cout << r << std::endl;

  t1 = clock();
  r = neu1.dot(neu1);
  t2 = clock();
  std::cout<<"time: "<<t2-t1<<std::endl;  
  std::cout << r << std::endl;
  return 0;
}

这是一个示例运行产生:

/tmp $ g++ -Wall -Wextra -pedantic -O3 -std=c++14 bla.cpp
/tmp $ ./a.out 
time: 272958
1.67772e+07
time: 29003
3.29441e+07

/tmp $ g++ -Wall -Wextra -pedantic -Ofast -std=c++14 bla.cpp
/tmp $ ./a.out 
time: 29953
3.23292e+07
time: 28853
3.29441e+07

这种变化不会让你的基准更好,但结果不会再是错误了。

您仍应考虑使用不同数据集进行多次运行的平均值。也不要为每次运行生成不同的测试数据,因为您的结果不可重复。

答案 1 :(得分:2)

您正在进行过度优化:编译器比您更智能并优化循环计算。

我在我的机器上得到了这些时间:

time: 0
time: 23422

如果您需要确保在基准测试中读取/写入某些内容,请使用volatile

#include <Eigen/Dense>
#include <iostream>
#include <vector>

int main()
{
  Eigen::VectorXf neu1 = Eigen::VectorXf::Random(100000000);
  std::vector<float> x(100000000);

  for(int i = 0; i < 100000000; ++i)
    x[i] = neu1[i];

  clock_t t1 = clock();
  float temp = 0.0f;
  for(int i = 0; i < 100000000; ++i)
    temp += x[i]*x[i];
  volatile float result = temp;    

  clock_t t2 = clock();
  std::cout<<"time: "<<t2-t1<<std::endl;

  t1 = clock();
  result = neu1.dot(neu1);
  t2 = clock();
  std::cout<<"time: "<<t2-t1<<std::endl;
}

然后,我的机器上的时间成为:

time: 79060
time: 21542