What does EIGEN_MAKE_ALIGNED_OPERATOR_NEW do exactly?
-
Eigen vectorizable types (e.g. Vector4d, Quaterniond, small fixed‐size Matrix<…>) carry an alignment requirement (usually 16 bytes, sometimes 32 on AVX machines).
1 2 3 4 5 6 7 8 9
template<typename Scalar, int Rows, int Cols /*…*/> struct Matrix { // this expands (on compilers that support it) to: // alignas(EIGEN_MAX_ALIGN_BYTES) EIGEN_ALIGN16 Scalar data[Rows * Cols]; }; using Vector4d = Matrix<double,4,1>;
- In compile time, Vector4d expands to
1
2
3
4
struct alignas(16) Vector4d {
double data[4];
// …
};
- The standard
::operator newon some platforms (or older compilers) doesn’t promise alignments above what the C++ ABI requires (often only 8 or maybe 16 bytes).- In C++ (since C++11), there’s a special POD type called
std::max_align_t(in<cstddef>) whose sole purpose is to have an alignment requirement at least as big as that of any scalar (fundamental) type on your platform - opeator new
void *operator new(std::size_t);must return memory that is suitably aligned for any object whose alignment requirement does NOT exceedalignof(std::max_align_t) - On many platforms,
std::max_align_t = 16
- In C++ (since C++11), there’s a special POD type called
- Macro
EIGEN_MAKE_ALIGNED_OPERATOR_NEWwill yield memory that is actually aligned to EIGEN_MAX_ALIGN_BYTES (16, 32, etc).- But when using
operator new, or STL containers (which calls operator new inT* allocate(std::size_t n) {}), we need to use the Macro to override the global new / delete for your class. It injects below definitions of into your class, and makes each call go through Eigen’s aligned‐allocation routines (EIGEN_ALIGNED_MALLOC / EIGEN_ALIGNED_FREE).
- But when using
1
2
3
4
void* operator new(std::size_t size);
void operator delete(void* ptr);
void* operator new[](std::size_t size);
void operator delete[](void* ptr);
-
Therefore, EVERY TIME your class contains fixed-size Eigen, add EIGEN_MAKE_ALIGNED_OPERATOR_NEW to your class/struct
1 2 3 4 5 6
struct Pose { EIGEN_MAKE_ALIGNED_OPERATOR_NEW; Sophus::SO3d rot; // internally holds a quaternion (4 doubles) Eigen::Vector3d trans; // 3 doubles };
Add `EIGEN_MAKE_ALIGNED_OPERATOR_NEW when you have all of the following
- The class has Eigen members like:
Eigen::Vector4d,Eigen::Matrix4d,Eigen::QuaterniondEigen::Isometry3d,Eigen::Affine3d,Eigen::Transform<...>- any fixed-size type whose size is a multiple of the SIMD packet (common: 16 bytes for SSE, 32 for AVX)
- The class can be allocated dynamically:
new MyTypestd::make_shared<MyType>- stored in containers like
std::vector<MyType>(orstd::vector<std::shared_ptr<MyType>>if the objects themselves are heap-allocated) - or generally lives in places where alignment isn’t guaranteed by default allocators (older toolchains especially)
When you usually don’t need it
- The object is only stack-allocated (
PoseThing x;) and you’re on modern compilers/platforms (stack alignment is typically OK). - The class only has dynamic-size Eigen types (
Eigen::VectorXd,MatrixXd) — those manage their own aligned heap buffers internally. - You never store it in STL containers by value / never allocate it on heap.