Re: [eigen] matrix and vector ctors & speed

[ Thread Index | Date Index | More lists.tuxfamily.org/eigen Archives ]


Hi,

Your version #3 is not correct, you have to use y.insert(y.begin(),
x.data(), x.data()+x.size()); With gcc I get the exact same same
result for each version. See attached benchmark file. I also observed
that in some cases clang is able to optimize away memcpy when the copy
is actually not necessary. This is the case in the attached file.

gael

On Thu, May 30, 2013 at 4:58 AM, Bob Carpenter <carp@xxxxxxxxxxx> wrote:
> We refactored our application to use Eigen column vectors
> instead of std::vector and observed a fairly significant
> slowdown.  Profiling pointed to the copy constructor for
> Eigen vectors, so I'm wondering if there's something we're
> missing.  Here's what I tried.
>
> To copy a column vector
>
>        Matrix<double,Dynamic,1> x;
>
> there's the obvious copy constructor:
>
>   1.   Matrix<double,Dynamic,1> y(x);
>
> or the direct sizing + memcpy approach:
>
>   2.   Matrix<double,Dynamic,1> y(x.size());
>        std::memcpy(&y(0),&x(0),x.size() * sizeof(double));
>
> By comparison, we can use an iterator based on the
> memory used for x's values to construct a standard
> vector:
>
>   3.  std::vector<double> y(&x(0),&x(0) + x.size());
>
> I timed each version by repeatedly calling it, and found
> the times varied pretty widely:
>
>   1. 26s
>   2. 17s
>   3. 14s
>
> For Matrix<double,Dynamic,Dynamic> on the other hand, the
> copy constructor and the memcpy versions took about the same
> time.
>
> Is there a faster way to copy vectors?  I'm guessing we'll have
> the same issue if I were to pass in references, resize them and
> then assign (like copy ctor) or memcpy.
>
> This was using clang++ -O3 on a Macbook Pro with i7 CPU and clang
> version:
>
>   Apple clang version 4.1 (tags/Apple/clang-421.11.66) (based on LLVM
> 3.1svn)
>   Target: x86_64-apple-darwin12.3.0
>
> - Bob
>
>
#include <Eigen/Dense>
#include <vector>
#include <iostream>
#include <bench/BenchTimer.h>

using namespace Eigen;

EIGEN_DONT_INLINE
double* cp1(const VectorXd& A, int i = 0)
{
  VectorXd B(A);
  return &B(i);
}

EIGEN_DONT_INLINE
double* cp2(const VectorXd& A, int i = 0)
{
  VectorXd B(A.size());
  std::memcpy(B.data(), A.data(), A.size()*sizeof(double));
  return &B(i);
}

EIGEN_DONT_INLINE
double* cp3(const VectorXd& A, int i = 0)
{
  std::vector<double> B;
  B.insert(B.begin(), A.data(), A.data()+A.size());
  return &B[i];
}

int main(int argc, char** argv)
{
  using namespace std;
  
  BenchTimer t1,t2,t3;
  int tries = 10;
  int rep = 1000;
  int n = 100000;
  VectorXd A(n);
  A.setRandom();
  BENCH(t1,tries,rep,cp1(A));
  BENCH(t2,tries,rep,cp2(A));
  BENCH(t3,tries,rep,cp3(A));
  cout << t1.best() << " ; " << t2.best() << " ; " << t3.best() << endl;
}


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/