对于2D数组,Array.Copy()是否比for循环快?

本文关键字:是否 for 循环 数组 2D Array Copy 对于 | 更新日期: 2023-09-27 18:09:11

我最近改变了

        this.FieldValues = new object[2, fieldValues.GetUpperBound(1) + 1];
        for (int i = 0; i < FieldCount; i++)            
        {
            this.FieldValues[Current, i] = fieldValues[Current, i];
            this.FieldValues[Original, i] = fieldValues[Original, i];
        }

        FieldValues = new object[2, fieldValues.GetLength(1)];
        Array.Copy(fieldValues, FieldValues, FieldValues.Length); 

其中Current和Original的值分别为常数0和1。FieldValues是一个字段,FieldValues是一个参数。

在我使用它的地方,我发现Array.Copy()版本更快。但另一位开发人员说,他在一个独立的程序中对for循环与Array.Copy()进行了计时,发现for循环更快。

是否有可能Array.Copy()不是真的更快?我以为它应该是超级优化的!

对于2D数组,Array.Copy()是否比for循环快?

根据我自己的经验,当涉及到性能时,我发现我不能相信我的直觉。因此,我保留了一个快速而肮脏的基准测试应用程序(我称之为"StupidPerformanceTricks"),用它来测试这些场景。这是非常宝贵的,因为我已经发现了各种关于性能技巧的令人惊讶和违反直觉的发现。同样重要的是要记住在发布模式下运行基准测试应用程序,而不附加调试器,否则你就无法获得JIT优化,而这些优化可能会产生显著的差异:在调试模式下,技术a可能比技术B慢,但在发布模式下,使用优化的代码,速度要快得多。

也就是说,一般来说,我自己的测试经验表明,如果您的数组是<~32个元素时,您将通过滚动自己的复制循环获得更好的性能—可能是因为您没有方法调用开销,这可能很重要。但是,如果循环大于~32个元素,则使用Array.Copy()可以获得更好的性能。(如果你正在复制整型或浮点数或类似类型的东西,你可能还想研究一下Buffer.BlockCopy(),对于小数组,它比Array.Copy()快10%。)

但是,真正的答案是,"编写您自己的测试,尽可能地匹配这些精确的替代方案,将它们每个包裹在一个循环中,给循环足够的迭代,使其消耗至少2-3秒的CPU,然后自己比较替代方案。"

. net在底层工作的方式,我猜在优化的情况下,数组。复制会避免边界检查。

如果你对任何类型的集合进行循环,默认情况下CLR将检查以确保你没有通过集合的结束,然后JIT将不得不进行运行时评估或发出不需要检查的代码。(查看我评论中的文章,了解更多细节)

您可以修改此行为,但通常不会保存那么多。除非你在一个严格执行的内循环中,每一毫秒都很重要,那就是。

如果数组很大,我将使用Array。复制,如果它很小,两者都应该执行相同的操作。

我认为是边界检查为你创造了不同的结果

在您的特定示例中,有一个因素可能(理论上)表明for循环更快。

Array.Copy是一个O(n)操作,而你的for循环是O(n/2),其中n是你的矩阵的总大小。

Array.Copy需要遍历二维数组中的所有元素,因为:

在多维数组之间进行复制时,数组的行为类似于长一维数组,其中的行(或列)概念上首尾相连的例如,如果一个数组有三行(或列),每个包含四个元素,从数组的开始部分将复制第一行的所有四个元素(或列)和第二行(或列)的前两个元素。