在多维数组和单个数组之间存储数据的最有效方法是什么?

时间:2016-04-25 11:55:30

标签: c# arrays multidimensional-array unity3d jagged-arrays

基本上我不确定如何存储3D数据结构以实现最快的访问速度,因为我不确定多维数组的底层是什么。

注意:数组每次都是一个常量且已知的大小,每个元素都是16位。

选项一是拥有多维数组data[16, 16, 16],只需通过data[x, y, z]选项访问,选项二是拥有单维数组data[16 * 16 * 16]并通过data[x + (y * 16) + (z * 16 * 16)]进行访问。

由于每个元素只应该是16位长,并且我怀疑多维数组会在内部以至少32位的形式存储大量对其他数组的引用,这就是大量浪费的内存。但是,我担心它可能比每次运行第二个选项中指定的等式更快,速度是这个项目的关键。

那么,任何人都可以告诉我,与内存消耗的差异相比,速度有多大差异?

3 个答案:

答案 0 :(得分:3)

我认为值得指出的是,如果您的数组维度实际上都是16,那么您可以更有效地计算(x,y,z)数组的索引:

int index = x | y << 4 | z << 8;

逆向:

int x = index & 0xf;
int y = (index >> 4) & 0xf;
int z = (index >> 8) & 0xf;

如果是这种情况,那么我建议使用一维数组,因为它几乎肯定会更快。

请注意,JIT编译器完全可能会执行此优化(假设乘法是根据您的OP进行硬编码),但值得明确做。

我说单维数组更快的原因是因为the latest compiler is lacking some of the optimisations for multi-dimensional array access, as discussed in this thread

那就是说,你应该仔细检查时间,看看最快的是什么。

正如Eric Lippert所说:"If you want to know which horse is faster, race your horses"

答案 1 :(得分:3)

C#将多维数组存储为单个内存块,因此它们编译成几乎相同的东西。 (一个区别是有三组边界要检查)。

即。 arr[x,y,z]几乎相当于arr[x + y*ny +z*nz*ny],并且通常具有相似的性能特征。

然而,确切的性能将受到内存访问模式以及它如何影响缓存一致性(至少对于大量数据)的支配。您可能会发现嵌套循环超过x,然后y然后z可能比以不同顺序执行循环更快或更慢,如果更好地保留当前使用的数据在处理器缓存中。

这在很大程度上取决于确切的算法,因此不可能给出对所有算法都正确的答案。

与C或C ++相比,任何速度降低的另一个原因是边界检查,在一维数组的情况下仍然需要它。但是,这些通常会(但不总是)自动删除。

同样,确切的算法将影响优化器是否能够删除边界检查。

您的行动方针应如下:

  • 使用arr[x,y,z]编写一个简单的算法版本。
  • 如果足够快,您可以停止。
  • 否则会对算法进行概要分析,以检查实际上是数组访问的问题,分析内存访问模式等等。

答案 2 :(得分:1)

我会投票支持单维阵列,它的工作速度要快得多。基本上,您可以编写一些测试,执行最常见的任务并测量花费的时间。 此外,如果您有2 ^ n个数组大小,则使用左移操作而不是乘法来访问元素位置要快得多。