假设我们有两个基本类型的数组a
和b
(例如,float
),我们需要为每个有效索引{{1}计算a[i] + b[i]
,以及存储结果。迭代数组以最大化缓存命中的最佳方法是什么?它是从前到后,从前到后还是其他什么东西?
答案 0 :(得分:1)
为了利用缓存预取功能,您需要按顺序从前到后读取数组。
此外,阵列应该是SSE对齐的(16字节)。更重要的是项目(例如浮点数)将按其大小对齐(浮点数为4个字节)。这很重要,因此数据不会跨越缓存行(读取速度较慢)。
阵列对齐后,您可以使用SSE / AVX读取,添加和存储结果,在一条指令中执行4或8次操作。
修改强> 您可以在here中详细了解缓存预取Intel SW Developer Manual和深度说明。
答案 1 :(得分:1)
对于这种操作,您应该使用编译器的自动矢量化。将小i
迭代为大i
。此外,答案取决于“存储结果”的含义以及要迭代的项目项目的数量n
。
如果您的意思是c[i] = a[i] + b[i]
且n
不是太小,那么编译器的自动矢量化程序将优化这一点而不需要进行任何更改。甚至MSVC也会得到正确的(至少对于SSE而言)。您的编译器必须对n进行一些调整,而不是4的倍数(或AVX的8)和对齐,但是这个成本将在n中摊销,除了小n
之外,这种开销将产生微不足道的影响。如果n
很小,那么您可能需要考虑对齐。有多小是必须确定的,但我猜它远远小于100.
如果你的意思是sum + = a[i] + b[i]
,减少,那么你需要考虑这个问题。这有一个依赖关系链,因此您需要展开循环3-10 times。此外,您需要使用自floating point arithmetic is not associative and the auto-vectorization won't kick in without it以来的宽松浮点模型,因此将-ffast-math
添加到GCC(/fp:fast
到MSVC)。如果您展开循环并使用宽松的浮点模型,那么GCC,ICC,Clang和MSVC应该有效地自动矢量化您的缩减。