提问者:小点点

C#遍历三维数组的最快维度


我有一个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++)

共2个答案

匿名用户

您可以自己对其进行基准测试,例如:

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指令来向量化同一行中的问题。 因此,如果可以的话,避免在循环中跳行对性能会更好。 另一方面,您必须执行的迭代次数不会改变,所以我们讨论的是一些小的性能改进。