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

时间:2011-09-20 10:45:37

标签: c# performance

我最近改变了

        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()版本更快。但另一位开发人员表示,他在独立程序中针对Array.Copy()定时for循环,并发现for循环速度更快。

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

3 个答案:

答案 0 :(得分:7)

根据我自己的经验,我发现在性能方面我无法相信自己的直觉。因此,我保留了一个快速而肮脏的基准测试应用程序(我称之为“StupidPerformanceTricks”),我用它来测试这些场景。这是非常宝贵的,因为我已经对性能技巧做了各种令人惊讶和反直觉的发现。同样重要的是要记住在发布模式下运行基准测试应用程序,而不附加调试器,否则您将无法获得JIT优化,并且这些优化可能会产生显着差异:技术A在调试模式下可能比技术B慢,但在发布模式下显着更快,优化代码。

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

但是所有这一切,真正的答案是,“编写自己的测试,尽可能地匹配这些精确的替代品,用循环包装它们,给它循环足够的迭代,让它至少咀嚼2-3几秒钟的CPU,然后自己比较备选方案。“

答案 1 :(得分:4)

.Net工作的方式,我想在优化的情况下,Array.Copy会避免边界检查。

如果对任何类型的集合执行循环,默认情况下CLR将检查以确保您没有传递集合的末尾,然后JIT将要么必须进行运行时评估或发出代码,不需要检查。 (查看我评论中的文章以获得更好的详细信息)

您可以修改此行为,但通常不会保存那么多。除非你处于一个紧密执行的内循环中,每一毫秒都是重要的,就是这样。

如果Array很大,我会使用Array.Copy,如果它很小,要么应该执行相同的操作。

我确实认为检查是否会为你创造不同的结果。

答案 2 :(得分:-3)

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

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

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

  

在多维数组之间进行复制时,数组的行为类似于   长一维数组,行(或列)所在的位置   概念上是端到端的。例如,如果数组有三行   (或列)每个有四个元素,复制六个元素   数组的开头将复制第一行的所有四个元素   (或列)和第二行(或列)的前两个元素。