【问题标题】:creating a cache efficient version of a loop创建循环的缓存高效版本
【发布时间】:2019-04-10 19:28:50
【问题描述】:

我正在尝试创建嵌套循环的缓存高效版本。循环的长度使得与循环相关的数据将大于缓存大小。我希望能够在块中迭代循环,以便更有效地使用缓存,但我不知道这是否可能。

我尝试过传统的阻塞方法,但显然这不是循环的正确解决方案,因为 j 每次都从 0 开始迭代。

#define N     65536
#define BLOCK 4096

int min(int a, int b);

int main() {

  double a[N];
  double d_a;
  int i,j;
  int bbegin; 
  int bend;

  for(bbegin = 0;bbegin < N;bbegin += BLOCK) {

    bend = min(bbegin + BLOCK, N);

    for(i=bbegin;i<bend;i++){
      for(j=0;j<i;j++){

        /* array a has been filled up elsewhere */
        d_a = a[i] - a[j];
        /* do some stuff with d_a */

      }
    }
  }

}

inline int min(int a, int b) { return (a < b) ? a : b; }

【问题讨论】:

  • 对我来说,gcc 8.3.1xorl %eax, %eax; ret 生成 main(),我不确定您希望如何改进这一点。
  • 对不起 - 我在这里真的很愚蠢,没有在循环中发布正确的中间部分。
  • 缓存大小是多少? “用 d_a 做一些事情”中使用了多少数据?
  • 缓存为 32k、64 B、8 路关联。使用 d_a 进行一些计算,并将结果输出到由 i 索引的另一个大小为 N 的数组中。
  • 您的BLOCK 太大。在处理一个块时,您将在缓存中有一个由i 索引的a 块,即4096 个元素,每个元素8 个字节(假设double 是8 个字节),它会填满您的缓存。您还将有一个结果块也由i 索引,因此还有另外 4096 个元素,每个元素大概有 8 个字节。您将拥有a[j] 和一些杂项数据。所以你的BLOCK 需要小于当前大小的一半。

标签: c loops caching


【解决方案1】:

变化:

for (i = bbegin; i < bend; i++)
    for (j = 0; j < i; j++)

到:

for (j = 0; j < bend-1; j++)
    for (i = max(bbegin, j+1); i < bend; i++)

这会以不同的顺序处理相同的元素,结果是 当下一个a[j] 是时,块中的每个a[i] 将被最近使用 已加载,因此该块中的元素将保留在缓存中。

max当然有明确的定义,类似于min的节目。)

【讨论】:

  • 感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多