Переходный эффект Эйгена EIGEN_MAKE_ALIGNED_OPERATOR_NEW? - PullRequest
0 голосов
/ 02 августа 2020

Недавно мне стало известно о потенциальных проблемах выравнивания памяти для векторизуемых собственных объектов фиксированного размера .

Правильный код, как указано в 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?
...