首页 > 解决方案 > 为什么在执行 SIMD 指令时需要 SSE 对齐?

问题描述

我是 C++ 新手,我只有 1.5 年的 C++ 经验。

我必须使用具有预制数据结构的库,它提供了一种按照某些规则制作我们自己的数据结构的方法,以便使其适应库。

这是PCL 库。我说的数据结构是Point Type

这些“规则”之一是 SSE 将点类型的数据对齐到 16 个字节(我认为这是 16 个字节)。但我不明白为什么。

我必须建立奇怪的工会和结构才能做到这一点。为什么我不能只做一个简单的结构,把我需要的每一个浮点数都放进去?

我看到强烈建议将 SSE 对齐用于 SIMD 指令,我怀疑 PCL 库会使用它。SIMD 指令有用吗?

标签: c++data-structurespoint-cloud-library

解决方案


SIMD 的意思是“单指令多数据”。

现代计算机有多种方法可以同时做不止一件事。物理限制使得构建运行速度远高于 5 GHz 的计算机变得困难。因此,现代计算机反而更擅长一次做不止一件事,而不是更快地运行一组指令。

为了利用它,我们需要在我们的计算机程序中一次做不止一件事。

一次做不止一件事的一种方法是同时运行多个进程——程序。

另一个是程序中的线程,每个线程都有自己的指令和数据。

指令的 CPU 流水线化发生在单个线程中。其中,每条指令所需的一些工作以重叠的方式完成。根据架构,机器代码可能需要也可能不需要知道这些延迟;在 x64 AMD/Intel 中,如果在下一条指令之前需要其输出,通常 CPU 会“停止”计算。编译器试图避免这种停顿。

SIMD 是另一种同时做多件事的方法。它也称为矢量化。SIMD 在多条数据上运行相同的指令。因此,如果您有一堆数学向量(每个向量都有多个分量:例如,x、y、z、w),并且您想要分段相加,则单个 SIMD 指令可以分别添加 xs、ys、zs 和 ws同时。

SIMD 指令通常要求您的数据在内存中以某种方式对齐。对于 4 个 32 位整数的 128 SIMD 指令,通常它要求使用的地址是 128 位(或 16 字节)的倍数——地址中的最低 4 位必须为 0。

SIMD 指令最适合用于大型数据缓冲区,因为它们是流水线的。因此,对齐数据的成本很低,而 CPU 中的收益很高。

在某些架构中,即使是非 SIMD 数据也需要对齐,而且通常对齐会提高读取速度。

SIMD 指令可以比天真的执行要快很多倍。现代 SIMD 指令有时是 512 字节宽,接近对单个 16 位或 8 位或 32 位值执行单条指令的速度;这样他们就可以将程序速度提高 10 倍;这篇 SO 博客文章有一个超过 10 倍加速的例子

当然,这是一个理想的情况。提升通常较小,但即使是 2 倍的加速也可能对用户体验很重要。


推荐阅读