基本上我不确定如何存储3D数据结构以实现最快的访问速度,因为我不确定多维数组的底层是什么。
注意:数组每次都是一个常量且已知的大小,每个元素都是16位。
选项一是拥有多维数组data[16, 16, 16]
,只需通过data[x, y, z]
选项访问,选项二是拥有单维数组data[16 * 16 * 16]
并通过data[x + (y * 16) + (z * 16 * 16)]
进行访问。
由于每个元素只应该是16位长,并且我怀疑多维数组会在内部以至少32位的形式存储大量对其他数组的引用,这就是大量浪费的内存。但是,我担心它可能比每次运行第二个选项中指定的等式更快,速度是这个项目的关键。
那么,任何人都可以告诉我,与内存消耗的差异相比,速度有多大差异?
答案 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个数组大小,则使用左移操作而不是乘法来访问元素位置要快得多。