Spec-Zone.ru › Eigen3

Использование контейнеров STL с Eigen

Резюме

Если вы компилируете только в режиме [c++17] с достаточно новым компилятором (например, GCC>=7, clang>=5, MSVC>=19.12), то всё выполняется компилятором, и вы можете прекратить чтение.

В противном случае, использование контейнеров STL с фиксированными векторными типами Eigen или классами, имеющими члены таких типов, требует использования выравнивающегося аллокатора. То есть, аллокатора, способного выделять буферы с выравниванием 16, 32 или даже 64 байта. Eigen предоставляет такой аллокатор: aligned_allocator.

До [c++11], если вы хотите использовать std::vector контейнер, вам также необходимо #include <Eigen/StdVector> .

Эти проблемы возникают только с фиксированными векторными типами Eigen и структурами, имеющими такие объекты Eigen в качестве членов. Для других типов Eigen, таких как Vector3f или MatrixXd, при использовании контейнеров STL особый уход не требуется.

Использование выравнивающегося аллокатора

Контейнеры STL принимают необязательный шаблонный параметр, тип аллокатора. При использовании контейнеров STL с фиксированными векторными типами Eigen необходимо указать контейнеру использовать аллокатор, который всегда будет выделять память в местах с выравниванием 16 байтов (или больше). К счастью, Eigen предоставляет такой аллокатор: Eigen::aligned_allocator.

Например, вместо

std::map<int, Eigen::Vector4d>

необходимо использовать

std::map<int, Eigen::Vector4d, std::less<int>, 
         Eigen::aligned_allocator<std::pair<const int, Eigen::Vector4d> > >

Обратите внимание, что третий параметр std::less<int> — это просто значение по умолчанию, но мы должны его включить, так как хотим указать четвёртый параметр, который является типом аллокатора.

Случай std::vector

Этот раздел только для пользователей c++98/03. Пользователи [c++11] (или выше) могут прекратить чтение здесь.

Итак, в c++98/03 ситуация с std::vector усложняется из-за ошибки в стандарте (объяснение ниже). Для решения этой проблемы нам пришлось специализировать его для типа Eigen::aligned_allocator. На практике вы обязаны использовать Eigen::aligned_allocator (а не другой выравнивающийся аллокатор) и #include <Eigen/StdVector>.

Вот пример:

#include<Eigen/StdVector>
/* ... */
std::vector<Eigen::Vector4f,Eigen::aligned_allocator<Eigen::Vector4f> >

Объяснение: Метод resize() объекта std::vector принимает аргумент value_type (по умолчанию value_type()). Так, с std::vector<Eigen::Vector4d>, некоторые объекты Eigen::Vector4d будут передаваться по значению, что отбрасывает любые модификаторы выравнивания, поэтому Eigen::Vector4d может быть создан в невыровненном месте. Для избежания этого единственным увиденным решением было специализировать std::vector для того, чтобы это работало с небольшой модификацией, здесь Eigen::Vector4d, способной должным образом обрабатывать эту ситуацию.

Альтернатива — специализация std::vector для типов Eigen

В качестве альтернативы рекомендованному подходу выше, вы можете специализировать std::vector для типов Eigen, требующих выравнивания. Преимущество заключается в том, что вам не нужно объявлять std::vector повсюду с Eigen::aligned_allocator. С другой стороны, недостатком является то, что специализация должна быть определена до всех фрагментов кода, в которых, например, std::vector<Vector2d> используется. В противном случае, без знания специализации компилятор скомпилирует этот конкретный экземпляр с по умолчанию std::allocator, и ваша программа, скорее всего, вызовет ошибку.

Вот пример:

#include<Eigen/StdVector>
/* ... */
EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Matrix2d)
std::vector<Eigen::Vector2d>

© Eigen.
Licensed under the MPL2 License.
https://eigen.tuxfamily.org/dox/group__TopicStlContainers.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API