我开始学习一点点SIMD内在函数。我注意到,对于某些函数,存在对齐和未对齐的版本,例如_mm_store_si128
和_mm_storeu_si128
。我的问题是,这些功能的表现是否有所不同,如果不是,为什么会有两个不同的版本?
答案 0 :(得分:2)
在较旧的CPU上,对齐和未对齐的加载/存储之间存在显着的性能差异。在最近的CPU上,差异不那么显着,但作为一个经验法则,#34;你应该尽可能选择对齐的版本。
答案 1 :(得分:2)
我说"总是对齐(尽可能)",这样你无论如何都会被覆盖。某些平台不支持未对齐访问,其他平台会出现严重的性能下降。如果您选择对齐访问,则无论如何都将获得最佳性能。在某些平台上可能会有很小的内存成本,但这是值得的,因为如果你去SIMD意味着你要求性能。我认为没有理由为什么要实现未对齐的代码路径。也许如果你必须处理一些旧的设计,这个设计并没有考虑到SIDM,但是我说这种可能性很小甚至没有。
我也说这同样适用于标量,在任何情况下都要正确对齐,并在实现最佳性能时省去一些麻烦...
为什么未对齐的访问可能会更慢甚至不受支持 - 这是因为硬件的工作原理。假设你有一个64位整数和一个64位内存控制器,如果你的整数正确对齐,内存控制器可以一次性访问它。但如果偏移,内存控制器将不得不进行2次操作,加上CPU可能需要移动数据才能正确组合。由于这不是最理想的,一些平台甚至不会隐含地支持它,作为提高效率的手段。
答案 2 :(得分:2)
如果数据实际上已对齐,则未对齐的加载/存储将与对齐的商店具有相同的性能。
未对齐的操作:未对齐的数据会导致性能下降,但您的程序仍然有效。
对齐的操作:未对齐的数据会导致错误,让您检测到意外未对齐的数据,而不是无声地导致性能下降。
现代CPU对未对齐的负载有很好的支持,但是当负载越过缓存线边界时,仍然会有很大的性能损失。
使用SSE时,对齐的载荷可以作为内存操作数折叠到其他操作中。这略微改善了代码大小和吞吐量。
使用AVX时,两种负载都可以折叠到其他操作中。 (AVX默认行为是允许未对齐的内存操作数)。如果对齐的载荷没有折叠,并产生movdqa
或movaps
,那么它们仍将在未对齐的地址上出错。这甚至适用于128位操作的VEX编码,使用正确的编译选项,使用128b内在函数对代码没有源更改。
对于内在函数入门,我建议始终使用未对齐的加载/存储内在函数。 (但尝试至少在常见情况下使数据保持一致)。如果您担心未对齐的数据导致问题,请在性能调整时使用对齐。