我有一个3D多维数组,大小有20,240和20。
var stuff = new Stuff[20, 240, 20]
为了获得最佳性能,我应该以哪种顺序遍历数组?
目前我正在做:X,Z,Y在一个嵌套的for循环中,这是我所看到的其他人使用的。
for (byte x = 0; x < 20; x++)
for (byte z = 0; z < 20; z++)
for (byte y = 0; y < 240; y++)
您可以自己对其进行基准测试,例如:
public class Traversal
{
public static int[,,] stuff = new int[20,240,20];
[Benchmark]
public int[,,] XYZ()
{
var result = new int [20, 240, 20];
for (byte x = 0; x < 20; x++)
for (byte y = 0; y < 240; y++)
for (byte z = 0; z < 20; z++)
{
result[x, y, z] = stuff[x, y, z];
}
return result;
}
[Benchmark]
public int[,,] XZY()
{
var result = new int [20, 240, 20];
for (byte x = 0; x < 20; x++)
for (byte z = 0; z < 20; z++)
for (byte y = 0; y < 240; y++)
{
result[x, y, z] = stuff[x, y, z];
}
return result;
}
}
BenchmarkRunner.Run<Traversal>();
在我的计算机上,它给出了下一个结果:
| Method | Mean | Error | StdDev |
|------- |---------:|---------:|---------:|
| XYZ | 412.4 us | 9.73 us | 27.92 us |
| XZY | 429.0 us | 11.48 us | 33.50 us |
如CLI spec spec所述:
数组元素应在数组对象内按主要行顺序排列(即,与最右边数组维度相关联的元素应从最低到最高索引连续排列)。 为每个数组元素分配的实际存储可以包括特定于平台的填充。
因此,通常情况下,由于CPU缓存和可能的一些优化,按行处理项的速度应该更快(尤其是如果您将值类型存储在数组中),但对于大多数日常场景,改进应该很小,并且一如既往--首先对具体案例(和具体硬件)进行基准测试。
C#将数组存储在一个主要的行顺序中,因此如果您“将操作保持在同一行附近”,它会更快。 这是因为您的CPU将使用changing和在某些情况下使用SIMD指令来向量化同一行中的问题。 因此,如果可以的话,避免在循环中跳行对性能会更好。 另一方面,您必须执行的迭代次数不会改变,所以我们讨论的是一些小的性能改进。