Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Eigen types with STL containers and std::vector

It looks like using Eigen types with STL containers is very messy and requires special attention to alignment issues. My problem is that I'm planning to create complex class hierarchy with dozens of classes that might include one or more Eigen types as member variables. From the documentation it appears that as soon as you include Eigen type in member variables, your class gets "infected" with same issues as Eigen types. This means I've to take extra care for using STL containers not only for Eigen types but also for all of my dozens of classes.

Even more worse part that worries me is that anyone who uses instances of my classes in their code will have same issues and would be needed to be expert on this subject - even if my classes didn't expose any Eigen types in their public interface!

This is quite frustrating. Questions I have,

  1. Is my understanding above correct (I only need to support C++11 and modern compilers)?
  2. Is there any pattern people use so they don't have to pollute their code with special Eigen handling all over places?
  3. I'm thinking about disabling whole vectorization globally. Would that resolve above issues at the cost of performance? Can it be enabled selectively for only specific code?
  4. If I forget to take care of alignment issue somewhere in code, do I always get compile time error OR issue might remain hidden and there can be crash at runtime?
like image 333
Shital Shah Avatar asked Dec 11 '16 14:12

Shital Shah


1 Answers

Yes your understanding is mostly correct, but I should add that this only concerns Eigen's fixed size types that require alignment such as Vector4f, Matrix2d, etc. but not Vector3f or MatrixXd. Moreover, the core of the problem is that STL containers do not honor alignas requirements yet, though this should come in some future C++ version.

I think that the easiest way to avoid such difficulties is to use non-aligned Eigen's types for class members and container value-types such as:

typedef Eigen::Matrix<float,4,1,Eigen::DontAlign> UVector4f;
typedef Eigen::Matrix<double,2,2,Eigen::DontAlign> UMatrix2d;

This way you do not have to bother about alignment issues, and you won't loose explicit vectorization. In Eigen 3.3, unaligned objects are vectorized too.

EDIT:

Regarding your last question, unfortunately, there is no possibility in C++ to detect such a shortcoming at compile time. If assertions are not disabled and that an invalid unaligned allocation occurs at runtime, then you will get an explicit assertions message, but that's all we can do. Therefore, if your program runs fine on a given system with some given compilation flags, then this does not mean that your code is safe. For instance, on most 64 bits systems buffer are aligned on 16 bytes boundary and so, if you do not enable AVX instruction set, then your code will run fine. On the other hand, the same code may assert if moving to a more exotic platform, or enabling AVX instructions that required 32 bytes alignment by default. Nonetheless, static analysers are becoming more and more powerful, and I think that some of such issue could be detected by them.

Another strategy consists in checking your program with a custom malloc returning 8 bytes aligned buffers only. This way you should be able to catch all shortcomings, assuming your program is well covered by unit tests. To do so, you must compile with -DEIGEN_MALLOC_ALREADY_ALIGNED=0, for obvious reasons.

like image 72
ggael Avatar answered Oct 31 '22 11:10

ggael