SIMD内在函数:对齐操作不同于未对齐?

时间:2015-08-18 07:30:07

标签: c++ x86 simd intrinsics

我开始学习一点点SIMD内在函数。我注意到,对于某些函数,存在对齐和未对齐的版本,例如_mm_store_si128_mm_storeu_si128。我的问题是,这些功能的表现是否有所不同,如果不是,为什么会有两个不同的版本?

3 个答案:

答案 0 :(得分:2)

在较旧的CPU上,对齐和未对齐的加载/存储之间存在显着的性能差异。在最近的CPU上,差异不那么显着,但作为一个经验法则,#34;你应该尽可能选择对齐的版本。

答案 1 :(得分:2)

我说"总是对齐(尽可能)",这样你无论如何都会被覆盖。某些平台不支持未对齐访问,其他平台会出现严重的性能下降。如果您选择对齐访问,则无论如何都将获得最佳性能。在某些平台上可能会有很小的内存成本,但这是值得的,因为如果你去SIMD意味着你要求性能。我认为没有理由为什么要实现未对齐的代码路径。也许如果你必须处理一些旧的设计,这个设计并没有考虑到SIDM,但是我说这种可能性很小甚至没有。

我也说这同样适用于标量,在任何情况下都要正确对齐,并在实现最佳性能时省去一些麻烦...

为什么未对齐的访问可能会更慢甚至不受支持 - 这是因为硬件的工作原理。假设你有一个64位整数和一个64位内存控制器,如果你的整数正确对齐,内存控制器可以一次性访问它。但如果偏移,内存控制器将不得不进行2次操作,加上CPU可能需要移动数据才能正确组合。由于这不是最理想的,一些平台甚至不会隐含地支持它,作为提高效率的手段。

答案 2 :(得分:2)

如果数据实际上已对齐,则未对齐的加载/存储将与对齐的商店具有相同的性能。

  • 未对齐的操作:未对齐的数据会导致性能下降,但您的程序仍然有效。

  • 对齐的操作:未对齐的数据会导致错误,让您检测到意外未对齐的数据,而不是无声地导致性能下降。

现代CPU对未对齐的负载有很好的支持,但是当负载越过缓存线边界时,仍然会有很大的性能损失。

使用SSE时,对齐的载荷可以作为内存操作数折叠到其他操作中。这略微改善了代码大小和吞吐量。

使用AVX时,两种负载都可以折叠到其他操作中。 (AVX默认行为是允许未对齐的内存操作数)。如果对齐的载荷没有折叠,并产生movdqamovaps,那么它们仍将在未对齐的地址上出错。这甚至适用于128位操作的VEX编码,使用正确的编译选项,使用128b内在函数对代码没有源更改。

对于内在函数入门,我建议始终使用未对齐的加载/存储内在函数。 (但尝试至少在常见情况下使数据保持一致)。如果您担心未对齐的数据导致问题,请在性能调整时使用对齐。