数组数组与多维数组的性能比较

当我在大学里使用C ++时,我被告知尽可能使用多维数组(特此是MDA),因为它在一个大块中分配后表现出更好的内存局部性。 另一方面,arraysarrays(AoA)被分配在多个较小的块中,可能散布在物理存储器中的任何位置,无论何处发现空位。

所以我想第一个问题是:这是一个神话,还是值得关注的建议?

假设它是后者,那么接下来的问题就是如Java这样没有真正MDA的语言。 当然,用1DA模拟MDA并不难。 从本质上讲,具有MDA的语言的语法糖可以实现为对没有MDA的语言的库支持。

这值得努力吗? 对于像Java这样的语言来说,这是一个太低的优化问题吗? 我们应该放弃数组并使用List甚至原语吗?


另一个问题:在Java中,一次分配AoA( new int[M][N] )可能会产生不同于分层次的内存分配( new int[M][]; for (... new int[N] )?

Java和C#以与C ++不同的方式分配内存。 事实上,在.NET中,如果AoA的所有数组都是一个接一个地分配的话,它们将会紧密相连,因为内存中只有一个连续的块而没有任何碎片。

但对于C ++来说仍然如此,如果你想要最高速度仍然有意义。 虽然每次你想要多维数组时都不应该遵循这个建议,但是你应该首先编写可维护的代码,然后在缓慢的情况下对其进行分析,过早的优化是这世界上所有邪恶的根源。

这值得努力吗? 对于像Java这样的语言来说,这是一个太低的优化问题吗?

一般来说,这是不值得的。 在应用程序的第一个版本中忘记此问题的最佳策略,并以直接(即易于维护)的方式实现。 如果第一个版本运行速度太慢而无法满足您的要求,请使用分析工具查找应用程序的瓶颈。 如果分析表明arrays数组可能是问题,那么做一些实验来将您的数据结构更改为模拟的多维数组和配置文件,看它是否有显着差异。 [我怀疑它不会产生太大的影响。 但最重要的是不要浪费你的时间来不必要地优化某些东西。

我们应该放弃数组并使用列表甚至原语吗?

我不会那么远。 假设您正在处理预定大小的数组:

  • 对象数组将比同等的对象列表快一点,并且
  • 基元数组将比原始包装器的等效列表快得多并且占用的空间要少得多。

另一方面,如果您的应用程序需要“增长”数组,使用List将简化您的代码。

我不会浪费精力在Java中使用1D数组作为multidim数组,因为没有语法可以提供帮助。 当然,可以定义函数(方法)来为您隐藏工作,但是在使用数组数组时,您最终会使用函数调用而不是跟随指针。 即使编译器/解释器为您加速,我仍然认为这不值得。 此外,在尝试使用期望作为数组数组的2D(或N-Dim)数组的代码时,可能会遇到并发症。 我敢肯定,大多数通用代码都是用Java编写的。 还可以廉价地重新分配行(或列,如果你决定这样思考)。

如果您知道这个多维arrays是一个瓶颈,您可以忽略我所说的内容,看看手动优化是否有帮助。

根据Java的个人经验,如果加载大量数据或访问位于不同位置的数据中的元素,则多维数组远比一维数组慢。 我编写了一个以BMP格式拍摄屏幕截图的程序,然后在屏幕截图中搜索了一个较小的图像。 将屏幕截图图像(约3 mb)加载到多维数组(三维,[xPos] [yPos] [颜色](颜色= 0为红色值,等等))需要14秒。 将它加载到一维数组中需要1秒钟。 在较大图像中找到较小图像的增益是相似的。 当两个图像都存储为多维数组时,在较大的图像中找到较小的图像花了大约28秒。 当两个图像都存储为一维数组时,花费大约一秒钟才能在较大的图像中找到较小的图像。 也就是说,为了便于阅读,我首先使用维数组编写程序。