Недавно мне стало известно о потенциальных проблемах выравнивания памяти для векторизуемых собственных объектов фиксированного размера .
Правильный код, как указано в do c:
class Foo
{
...
Eigen::Vector2d v;
...
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};
...
Foo *foo = new Foo;
Я хотел бы знать, в порядке ли этот код?
class Foo2
{
...
Foo foo;
...
};
...
Foo2 *foo = new Foo2; //?
Или нужно снова добавить EIGEN_MAKE_ALIGNED_OPERATOR_NEW
в класс Foo2
? Вот что предлагается здесь Я думаю:
Если бы мы добавили EIGEN_MAKE_ALIGNED_OPERATOR_NEW, это решило бы проблему только самой библиотеки Cartographer. Пользователи библиотеки также должны будут добавить EIGEN_MAKE_ALIGNED_OPERATOR_NEW к классам, содержащим векторизованные классы Cartographer. Это похоже на кошмар обслуживания.
У меня нет опыта работы с перегрузкой нового оператора. Я думаю, что вопрос более общий и как-то связан с тем, как новый оператор работает в C ++. Например, может ли перегруженный оператор new в Foo
вызываться оператором new по умолчанию в Foo2
? А как насчет наследования? Если Foo2
наследуется от Foo
, должны ли мы также поместить EIGEN_MAKE_ALIGNED_OPERATOR_NEW
в Foo2
?
Так как я знал об этом c только недавно, я провел много исследований и обнаружил следующее:
- выравнивание по умолчанию на x86-64 составляет 16 байт, так что нормально не иметь
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
(если включен только SSE) - , если ваш код не скомпилирован для более поздних наборов SIMD (например, AVX2 с
-march=native
для всех оптимизаций на локальном компьютере), теперь EIGEN_MAKE_ALIGNED_OPERATOR_NEW
нужно - как насчет другой архитектуры? Например, для ARM, возникнут какие-либо проблемы, если мы не объявляем
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
, а NEON включен? - Я нашел предложение использовать
template <typename Scalar> using Isometry3 = Eigen::Transform<Scalar, 3, Eigen::Isometry | Eigen::DontAlign>
вместо Isometry
- , все еще нужно подумать о том, как легко использовать тип Eigen (например,
Isometry3d
) в коде без проблем с выравниванием. Итак, добавьте новый тип MyIsometry3d
, который наследуется, например, от Eigen::Transform<double, 3, Eigen::Isometry | Eigen::DontAlign>
?
В общем, я хотел бы «отключить выравнивание» (или векторизацию) в типе Eigen фиксированного размера:
- Я хотел бы сохранить синтаксис, например, сохранить
Isometry3d
в коде - и не беспокоиться о проблеме выравнивания при использовании
Isometry3d
в классе или при использовании std::vector<Isometry3d>
- что-то, что нужно сказать Эйгену, чтобы он всегда использовал невыровненную загрузку / сохранение (например,
_loadu_
/ _storeu_
для встроенных функций x86-64, как насчет другой архитектуры, есть ли эквивалент?) Для всех фиксированных размеров Собственный тип? - иначе просто отключите векторизацию для собственного типа фиксированного размера, поскольку я считаю, что штраф должен быть (почти) нулевым между использованием векторизованных инструкций и только кодом C ++ для этих типов
- , поэтому я предполагаю, что решение - использовать
#define EIGEN_UNALIGNED_VECTORIZE 0
, это правильно? Поэтому я должен поставить это #define
везде перед любыми Eigen/Dense
include? - Я не хочу везде заменять что-то вроде
Matrix<double,2,2,DontAlign>
или новый класс
Наконец, глядя на страницу Векторизуемые собственные объекты фиксированного размера , я думаю, что некоторые типы отсутствуют. Для типов, которые я использую:
Eigen::Isometry3d
, Eigen::Isometry3f
? Eigen::AngleAxisd
, Eigen::AngleAxisf
?