我正在尝试学习缓存的用法。从我通过做一些示例实验程序看到的,如果我将数组大小增加到特定值之外,执行迭代数组并对元素执行某些操作的程序所花费的时间会突然增加。任何人都可以简单地解释术语缓存大小和数组大小如何影响数组上数学运算的性能?
答案 0 :(得分:0)
如果缓存无法累积数组,则对这些非累积元素的任何引用都将导致缓存未命中。访问数组元素的方式也有所不同,因为在每次丢失时,处理器都会将数据块带入缓存,认为可能很快就需要这些数据,为避免将来的缓存未命中做好准备。
示例:
如果您对连续位置的元素进行操作,性能将得到改善。因为根据高速缓存行的大小,处理器将在第一次高速缓存未命中时获取一块内存。
例如,采用Matrix Multiplication的一个实例,我们按照以下方式进行。
假设:矩阵太大而无法在缓存中累积。
for (i = 0; i < N; i = i + 1)
for (j = 0; j < N; j = j + 1)
A[i*N + j] = (double) random() / SOME_NUMBER;
for (i = 0; i < N; i = i + 1)
for (j = 0; j < N; j = j + 1)
B[i*N + j] = (double) random() / SOME_NUMBER;
for (i = 0; i < N; i = i + 1)
for (j = 0; j < N; j = j + 1)
for (k = 0; k < N; k = k + 1)
C[i*N + j] = C[i*N + j] + A[i*N + k]*B[k*N + j];
这里,在为每一行乘以时,我们继续按列访问第二个矩阵。在B
中,第一列存储在B[0],[N-1],B[2N-1].......
中,依此类推,而不是连续的内存位置。因此会有很多缓存未命中。因此,如果我们可以塑造解决方案,以便我们处理连续的内存位置,并可以获得一些性能提升。我们可以将它存储在“列主要形式”中,即以转置形式存储,而不是将第二个矩阵存储在“行主要形式”中。所以现在所有的列元素都在连续的位置。
A
将逐行访问,B
将按列访问,因此我们在连续的内存位置拥有所有“相应的东西”。
因此,当处理器遇到第一次未命中时,它将获取一块内存,因此将避免下一次未命中。在这里,我们利用了'空间位置',从而'缓存阻塞'。
现在,如果我们按如下方式更改代码,性能将会有显着提升
以换位形式存储B:
B[j*N + i] = random() / SOME_NUMBER;
您还必须按顺序访问转置数组:
C[i*N + j] = C[i*N + j] + A[i*N + k]*B[j*N + k];