【问题标题】:how the cache size and array size affect the performance of mathematical operations on an array?缓存大小和数组大小如何影响数组上数学运算的性能?
【发布时间】:2013-10-05 16:36:22
【问题描述】:

我正在尝试学习缓存的用法。从我通过一些示例实验程序看到的情况来看,如果我将数组大小增加到超过特定值,那么执行迭代数组并对元素进行一些操作所花费的时间会突然增加很多。谁能简单地解释一下术语缓存大小和数组大小如何影响数组上数学运算的性能?

【问题讨论】:

标签: caching processor


【解决方案1】:

如果缓存无法累积数组,则对那些未累积元素的任何引用都将导致缓存未命中。您访问数组元素的方式也有所不同,因为每次未命中时,处理器都会将数据块放入缓存中,并认为可能很快就会需要这些数据,从而为避免未来的缓存未命中做好准备。

例子:

如果您对来自连续位置的元素进行操作,性能将会提高。因为根据缓存行的大小,处理器将在第一次缓存未命中时获取一块内存。

以矩阵乘法为例,我们按如下方式进行。

假设:矩阵太大而无法在缓存中累积。

 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];

【讨论】:

  • 感谢您的回答。但是我的问题是,为什么达到缓存大小时执行时间会突然增加?
  • 因为此后任何非缓存元素引用都是缓存未命中。然后处理器将先查看 L2,然后再查看 L3(如果有多级缓存)或最后查看主内存。与访问缓存相比,内存访问非常耗时(CPU 周期数)。
  • 但是每次缓存未命中都会发生这种情况,对吧。所以性能取决于是否使用已经加载到缓存的数据。它不应该取决于缓存是否已满。那么为什么缓存未命中取决于缓存大小?
  • 缓存未命中是指元素不在缓存中。由于这些原因,一个元素不会在缓存中 - 缓存已满,由于数据组织和缓存行大小不佳,没有预取元素,缺乏时间和空间局部性。
  • 我有一个数组,对数组做了一些操作。我有一个大小为 1MB 的单级缓存,缓存行大小为 32 字节。然后每次请求当前不在缓存中的数组元素时,32 个字节将被加载到缓存中。当缓存也已满时,同样的事情也会发生,唯一的区别是缓存行需要被覆盖。所以缓存未命中计数将仅取决于这 32 个字节(即缓存行大小)。我仍然不明白缓存大小所起的作用。
猜你喜欢
  • 2012-05-20
  • 1970-01-01
  • 2017-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-09
  • 1970-01-01
相关资源
最近更新 更多