【问题标题】:Performance issue about swap loops关于交换循环的性能问题
【发布时间】:2017-10-30 03:51:16
【问题描述】:

我从 c 测试中得到了这个问题。我很好奇问题的表现肯定。我不知道该怎么回应。我的问题完全一样。为什么性能提高了?

假设您有以下代码迭代一个大型(2000 到 2000 年)平方二维数组并计算非零元素的数量 数组。您交换两个内部循环的顺序,以便 x 循环是 现在是 y 循环。这极大地提高了您的性能 代码。为什么?

int total = 0;
for (int x = 0; x < side_length; x++) {
   for (int y = 0; y < side_length; y++) {
      if(array[y][x] != 0) {
         total += 1;
      }
   }
}

【问题讨论】:

  • 我没有看到任何数组!仅仅因为某物被称为“数组”并不意味着它是一个。提供minimal reproducible example
  • 因为你是按顺序访问内存的,这对于cpu来说效率更高,因为他可以优化内存访问。如果你反转循环,内存访问将被稀疏,因此效率较低。
  • 它被称为“locality”属性。它被更有效地缓存。
  • @EugeneSh。我不知道这个概念。有用。

标签: c performance


【解决方案1】:

原因在于cpu硬件。

C 中的数组是其元素的连续列表(二维数组是内部数组的连续列表)。

cpu 加载小数据和数据宽度与其数据总线宽度(许多现代 cpu 为 64 位)所花费的时间相同。 如此多的 cpu 加载数据的宽度与其数据总线的宽度一样宽;一些 CPU 甚至执行顺序“宽”传输的短而快速的突发传输。数据被加载到缓存中(一种非常大的寄存器)。 请求的部分数据直接加载到cpu寄存器中。

如果有后续请求,则可以立即从缓存中获取下一个数据,而无需花费时间访问内存。

如果cpu访问数据随机分布,缓存中的数据会被新数据过载,缓存的好处就丧失了。

【讨论】:

    【解决方案2】:

    如果您有一个 2000 到 2000 的矩阵,那么您将有 2000 个包含 2000 个元素的数组。逐个元素访问数组将按顺序访问内存,因为一个数组的内存是连续的。这是最好的情况,因为 cpu 可以优化您的内存访问。

    有两种方法可以遍历二维数组:行优先和列优先。在 row-first 迭代中,您在迭代下一个数组之前完全迭代所有数组时顺序访问内存。在列优先中,您访问所有数组的所有第一个索引,然后是第二个索引,依此类推。这些是随机内存访问,cpu 无法对其进行优化。

    您可以在维基百科上阅读article 了解更多信息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多