【问题标题】:SSE alignment of 3D vector3D 向量的 SSE 对齐
【发布时间】:2016-09-19 01:26:54
【问题描述】:

我希望确保 SSE 用于我的 3D(96 位)浮点向量的算术运算。但是,我已经阅读了关于什么是必要的相互矛盾的观点。

有些文章/帖子说我需要使用 4D 向量并“忽略”第四个元素,有些人说我必须用 __declspec(align(16)) 之类的东西装饰我的类并覆盖 new 运算符,有些人说编译器是足够聪明地为我整理东西(我真的希望这是真的!)。

我正在使用 Eigen 库,但发现“不支持”AlignedVector3 类不适合目的(例如,在进行组件除法时除以零错误,lpNorm 函数包含虚拟的第 4 个元素) .

我读过的很多文章已经有好几年了,所以我希望现代编译器/SSE 版本/CPU 可以为我对齐数据,或者使用非 16 字节对齐的数据。任何有关这方面的最新知识将不胜感激!

【问题讨论】:

  • CPU 不能自行启动并开始对齐内容,它们只会执行代码告诉它们执行的操作。另外,如果可能的话,停止这个想法,而是在单独的坐标上使用 SIMD,这样你就不必浪费第 4 条车道(而且通常几乎所有的事情都会更好,SIMD 向量不打算用作 linalg 向量)
  • 感谢您的评论(不明白为什么这个问题被否决了......)。无论如何,我不确定您所说的“在单独的坐标中使用 SIMD”是什么意思——您的意思是批量处理多个 3D 矢量(如果可能的话,那也很酷)?我还刚刚发现了 C++11 alignas(16) 装饰器。我添加它来包装我的通用维度向量类,它没有导致崩溃 - 当然,没有证据证明正在使用 SIMD。
  • 是的,批量处理,也许使用 3 个指针 (x,y,z) 到您使用 _aligned_malloc 获得的块中。此外,如有必要,您可以加载/存储未对齐的。整个声明式对齐处理在 C++ 中并不能很好地工作,例如,如果您将该类型放入容器中,除非您使用自定义分配器,否则它仍然会中断。

标签: c++ memory vector 3d sse


【解决方案1】:

实际上我们在工作中使用 SIMD,也许我可以给你我的反馈。 对齐是您在处理 SIMD 时必须注意的事情,这是为了确保缓存行对齐。 但是我不确定如果它没有对齐或者CPU是否能够管理它是否仍然会导致崩溃(比如过去没有对齐的标量类型,它会导致崩溃,现在CPU会处理它但它会变慢表演)。 也许你可以看这里SSE, intrinsics, and alignment 对于问题的对齐部分,它似乎有很好的答案。

事实上,即使它实际上是 4D 向量,您也将其用作 3D 向量,这不是一个真正好的做法,因为您不会从 SIMD 指令的所有性能中获益。最好的匹配方法是使用数组结构 (SOA)。

注意:我假设 128 位 SIMD 寄存器映射到 4 种标量类型(int 或 float)

例如,如果您有 4 个 3D 点(或向量),按照您的方式,您将有 4 个 4D 向量,忽略每个点的第 4 个分量。 最终,您可以访问 4 * 4 个值。

通过使用 SOA,您将拥有 3 个 SIMD 128 位(12 个值)寄存器,并且您将通过以下方式存储您的积分。 单片机

  • r1: x x x x
  • r2: y y y y
  • r3: z z z z

这样您就可以填满整个 SIMD 寄存器,从而最大限度地利用 SIMD 优势。另一件事是您必须进行的许多计算(例如添加 2 组 4 个向量)只需要 3 个 SIMD 指令。使用和理解有点棘手,但是当你这样做时,收获是巨大的。

当然,您不能在所有情况下都以这种方式使用它,因此您将退回到忽略最后一个值的原始解决方案。

【讨论】:

  • 16字节。如果您使用 _mm_load_ps(即使使用 AVX 而不是 SSE),未对齐可能会崩溃,但如果您使用 _mm_loadu_ps,则不会。
  • 标量未对齐在 x86 上从未出现过故障。您可能还记得过去使用不同的架构。对我来说,我记得我在学校的带有 SPARC CPU 的 Solaris 机器上遇到了我的代码错误。
猜你喜欢
  • 1970-01-01
  • 2012-03-16
  • 1970-01-01
  • 2011-03-14
  • 2016-11-21
  • 1970-01-01
  • 1970-01-01
  • 2023-03-19
  • 2011-06-25
相关资源
最近更新 更多