Я использую Eigen для обработки неструктурированного точечного набора (облака точек), представленного как массив объектов Eigen::Vector3f
. Для того, чтобы включить векторную идентификацию SIMD, я подклассифицировал Vector3f
в класс с alignas (16). Объекты в массиве начинаются с границы 16 байтов, имеют пробелы в 4 байта между собой и содержат неинициализированные данные.Eigen :: Vector3f alignment
Подкласс выглядит в настоящее время следующим образом: (Stil нужно добавить конструктор шаблонов копирования и оператор =
, как указано в Эйгене документации)
struct alignas(16) point_xyz : public Eigen::Vector3f {
using Eigen::Vector3f::Vector3f;
};
point_xyz cloud[n];
выход Ассамблея показывает, что используются инструкции SIMD и программа, которая применяется трансформация на каждом point_xyz
в массиве, похоже, работает правильно.
Безопасно ли использовать Eigen таким образом, или результаты зависят от содержимого неиспользуемых 4-байтовых зазоров и т. Д.?
Кроме того, было бы безопасно помещать данные цвета RGB или другое в неиспользуемые 4 байта (требуется переопределение выравнивания памяти)?
Редактировать: Кажется, что и clang ++, и g ++ выполняют некоторую векторизации, когда оптимизация включена. Без оптимизации (и ниже -O2 для лязга ++), как генерировать вызов библиотечной функции Эйгена для следующего умножения матриц (преобразование):
using transform_t = Eigen::Transform<float, 3, Eigen::Affine>;
transform_t t = Eigen::AngleAxisf(0.01*M_PI, Eigen::Vector3f::UnitX()) * Eigen::Translation3f(0.1, 0.1, 0.1);
Eigen::Vector3f p(123, 234, 345);
std::cout << p << std::endl;
for(;;) {
asm("# BEGIN TRANS");
p = t * p;
asm("# END TRANS");
}
std::cout << p << std::endl;
(для цикла и соиЬ необходимы, так что оптимизация Безразлично 't удалить умножение или поставить постоянное значение).
В GCC (-O1) это приводит к
# 50 "src/main.cc" 1
# BEGIN TRANS
# 0 "" 2
movss (%rsp), %xmm4
movaps %xmm4, %xmm2
mulss 64(%rsp), %xmm2
movss 4(%rsp), %xmm0
movaps %xmm0, %xmm1
mulss 80(%rsp), %xmm1
addss %xmm1, %xmm2
movss 8(%rsp), %xmm3
movaps %xmm4, %xmm5
mulss 68(%rsp), %xmm5
movaps %xmm0, %xmm1
mulss 84(%rsp), %xmm1
addss %xmm5, %xmm1
movaps %xmm3, %xmm5
mulss 100(%rsp), %xmm5
addss %xmm5, %xmm1
addss 116(%rsp), %xmm1
mulss 72(%rsp), %xmm4
mulss 88(%rsp), %xmm0
addss %xmm4, %xmm0
movaps %xmm3, %xmm4
mulss 104(%rsp), %xmm4
addss %xmm4, %xmm0
addss 120(%rsp), %xmm0
mulss 96(%rsp), %xmm3
addss %xmm3, %xmm2
addss 112(%rsp), %xmm2
movss %xmm2, (%rsp)
movss %xmm1, 4(%rsp)
movss %xmm0, 8(%rsp)
# 52 "src/main.cc" 1
# END TRANS
# 0 "" 2
Это приводит к тому же выходу и без #define EIGEN_DONT_VECTORIZE 1
. С Vector4f
генерируется несколько более короткий выход, когда векторизация Эйгена не отключена, но оба работают с регистрами xmm.
AlignedVector3<float>
, похоже, не поддерживает умножение с помощью Eigen::Transform
. Я делаю аффинные преобразования на множествах точек, представленных с использованием 3 (неоднородных) координат. Я не уверен, как Eigen реализует трансформацию с Eigen::Transform<float, 3, Eigen::Affine>
из Eigen::Vector4f
. То есть изменяет ли он только первые 3 компонента вектора, а четвертый компонент должен быть равен нулю или может содержать произвольное значение или он интерпретирует 4-вектор как однородные координаты? И зависит ли оно от внутреннего представления преобразования (Affine
, AffineCompact
, Projective
).
Я удивлен, что SIMD используется. Разумеется, Eigen не генерирует явно SIMD в таком случае. Проверьте неподдерживаемый/Eigen/AlignedVector3 модуль для явно векторизованного vector3f. – ggael
код кажется неэффективен. Конечно, «SIMD» будет использоваться, поскольку SSE используется по умолчанию для операций fp с большинством компиляторов (т. Е. Код 80x87 больше не генерируется). – user1095108
'mulss' = mul Scalar Single-precision. Он использует векторные регистры, но это ** не SIMD **. Это как amd64 делает математику; x87 устарел для всего, кроме 80-битного 'long double' (который намного быстрее, чем любой другой способ получения более 64-битных поплавков). –