Eigen::Vector3f
我正在使用 Eigen 处理非结构化点集(点云),表示为对象数组。为了启用 SIMD 矢量化,我Vector3f
使用 alignas(16) 将其子类化为一个类。数组中的每个对象都以 16 字节的边界开始,彼此之间有 4 字节的间隙,并且包含未初始化的数据。
子类目前看起来像这样:(仍然需要添加模板复制构造函数和运算符=
,如 Eigen 文档中所示)
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 的 clang++),两者都会为以下矩阵乘法(转换)生成对 Eigen 库函数的调用:
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;
(需要 for 循环和 cout 以便优化不会删除乘法或放入一个常数值)。
在 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
时,当 Eigen 的矢量化未禁用但两者都在 xmm 寄存器上运行时,会生成稍短的输出。
AlignedVector3<float>
似乎不支持与 的乘法Eigen::Transform
。我正在对使用 3 个(非同质)坐标表示的点集进行仿射变换。我不确定 Eigen 如何实现向量的Eigen::Transform<float, 3, Eigen::Affine>
转换Eigen::Vector4f
。即它是否只改变向量的前 3 个分量,第四个分量是否必须为零,或者它可以包含任意值,还是将 4 向量解释为齐次坐标?它是否取决于转换的内部表示 ( Affine
, AffineCompact
, Projective
)。