[eigen] copy constructor / assignment operator potential issue?

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


All,

I'm trying to understand whether we're doing something wrong with the following code snippet. If we do, I'd appreciate
any feedback :)
----------------------
int
main (int argc, char** argv)
{
  Vector4f vec1;
  MatrixXf mat;// (300, 4);
  mat = MatrixXf (300, 4);
  {
    int nr = mat.rows ();
    ScopeTime t1 ("w/out rows");
    for (long i = 0; i < 1000000; ++i)
    {
      for (int j = 0; j < nr; ++j)
        vec1 = mat.row (j);
    }
  }
  std::cout << vec1;

  Vector4f vec2;
  {
    ScopeTime t2 ("w/ rows");
    for (long i = 0; i < 1000000; ++i)
    {
      for (int j = 0; j < mat.rows (); ++j)
        vec2 = mat.row (j);
    }
  }

  std::cout << vec2;
  return (0);
}
----------------------

The definition of ScopeTime is given in the CPP file attached to this e-mail. By compiling the code and running it we get:

$ g++ -DEIGEN_DEFAULT_TO_ROW_MAJOR -O3 -I/usr/include/eigen3 -o minimal minimal.cpp
$ ./minimal
w/out rows took 760ms.
w/ rows took 643ms.

By compiling the code without debugging (supposedly disabling Eigen asserts) and running it we get:
$ g++ -DEIGEN_DEFAULT_TO_ROW_MAJOR -O3 -I/usr/include/eigen3 -o minimal minimal.cpp -DEIGEN_NO_DEBUG
$ ./minimal
w/out rows took 345ms.
w/ rows took 394ms.

Now while I completely see that the asserts are different with or without the EIGEN_NO_DEBUG, I think there's something
wrong here. One would expect that getting the rows () of a MatrixXf should not be a penalty hit. However, we
consistently get a 50ms penalty in this example by simply calling mat.rows () in the inner for loop.


To summarize (run the script attached):

a) row major + EIGEN_NO_DEBUG
w/out rows took 345ms.
w/ rows took 394ms.

b) row major
w/out rows took 760ms.
w/ rows took 643ms.

c) column major + EIGEN_NO_DEBUG
w/out rows took 451ms.
w/ rows took 492ms.

c) column major
w/out rows took 612ms.
w/ rows took 469ms.

Ideally, under all conditions, the "with" and "without rows" should be close to equal, especially when compiled with the
EIGEN_NO_DEBUG flag, correct? Or am I missing something obvious here? :)


Just for testing, if we disable line:

mat = Eigen::MatrixXf (300, 4);

and write instead:

MatrixXf mat (300, 4);

we get:

a) row major + EIGEN_NO_DEBUG
w/out rows took 235ms.
w/ rows took 323ms.

b) row major
w/out rows took 343ms.
w/ rows took 325ms.

c) column major + EIGEN_NO_DEBUG
w/out rows took 248ms.
w/ rows took 229ms.

c) column major
w/out rows took 344ms.
w/ rows took 324ms.


I am sort of puzzled by the excellent performance of column major + EIGEN_NO_DEBUG, especially in the case of w/ rows.

Again, any insight on what's going on here would be highly appreciated.

Thanks in advance!

Cheers,
Radu.
--
http://pointclouds.org
#include <boost/date_time/posix_time/posix_time.hpp>
#include <Eigen/Core>
using namespace Eigen;

class StopWatch
{
  public:
    StopWatch ()
    {
      start_time_ = boost::posix_time::microsec_clock::local_time ();
    }

    inline float
    getTime ()
    {
      boost::posix_time::ptime end_time = boost::posix_time::microsec_clock::local_time ();
      return (float)((end_time - start_time_).total_milliseconds ());
    }

    inline float
    getTimeSeconds ()
    {
      return (getTime () * 0.001f);
    }

    inline void
    reset ()
    {
      start_time_ = boost::posix_time::microsec_clock::local_time();
    }

  protected:
    boost::posix_time::ptime start_time_;
};

class ScopeTime : public StopWatch
{
  public:
    inline ScopeTime (const char* title)
    {
      title_ = std::string (title);
    }

    inline ScopeTime ()
    {
      title_ = std::string ();
    }

    inline ~ScopeTime ()
    {
      std::cerr << title_ << " took " << getTime () << "ms.\n";
    }

  private:
    std::string title_;
};

int
main (int argc, char** argv)
{
  Vector4f vec1;
  MatrixXf mat;// (300, 4);
  mat = MatrixXf (300, 4);
  {
    int nr = mat.rows ();
    ScopeTime t1 ("w/out rows");
    for (long i = 0; i < 1000000; ++i)
    {
      for (int j = 0; j < nr; ++j)
        vec1 = mat.row (j);
    }
  }
  std::cout << vec1;

  Vector4f vec2;
  {
    ScopeTime t2 ("w/ rows");
    for (long i = 0; i < 1000000; ++i)
    {
      for (int j = 0; j < mat.rows (); ++j)
        vec2 = mat.row (j);
    }
  }

  std::cout << vec2;
  return (0);
}

Attachment: run.sh
Description: application/shellscript



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