【问题标题】:Extremely fast way to clone the values of a jagged array into a second array?将锯齿状数组的值克隆到第二个数组中的极快方法?
【发布时间】:2011-06-07 22:18:00
【问题描述】:

我目前正在开发一个负责计算锯齿状数组的随机排列的应用程序。

目前,应用程序中的大部分时间都用于在每次迭代中复制数组(总共 100 万次迭代)。在我当前的系统上,整个过程需要 50 秒才能完成,其中 39 秒用于克隆阵列。

我的数组克隆例程如下:

    public static int[][] CopyArray(this int[][] source)
    {
        int[][] destination = new int[source.Length][];
        // For each Row
        for (int y = 0; y < source.Length; y++)
        {
            // Initialize Array
            destination[y] = new int[source[y].Length];
            // For each Column
            for (int x = 0; x < destination[y].Length; x++)
            {
                destination[y][x] = source[y][x];
            }
        }
        return destination;
    }

有什么方法,安全或不安全,可以更快地达到与上述相同的效果吗?

【问题讨论】:

  • 您是否尝试过使用多维数组而不是锯齿状数组,即static int[,] 而不是static int [][]

标签: c# arrays performance


【解决方案1】:

其中任何一个都应该适合您。它们的运行时间大致相同,并且都比您的方法快得多。

// 100 passes on a int[1000][1000] set size

// 701% faster than original (14.26%)
static int[][] CopyArrayLinq(int[][] source)
{
    return source.Select(s => s.ToArray()).ToArray();
}

// 752% faster than original (13.38%)
static int[][] CopyArrayBuiltIn(int[][] source)
{
    var len = source.Length;
    var dest = new int[len][];

    for (var x = 0; x < len; x++)
    {
        var inner = source[x];
        var ilen = inner.Length;
        var newer = new int[ilen];
        Array.Copy(inner, newer, ilen);
        dest[x] = newer;
    }

    return dest;
}

【讨论】:

  • 找到这个让我松了一口气:顺便说一句,将其扩展到更多维度看起来很容易:return source.Select(s => s.Select(p => p.ToArray() ).ToArray()).ToArray();
【解决方案2】:

您可以将Array.Clone 用于内部循环:

public static int[][] CopyArray(this int[][] source)
{
    int[][] destination = new int[source.Length][];
    // For each Row
    for(int y = 0;y < source.Length;y++)
    {
        destination[y] = (int[])source[y].Clone();
    }
    return destination;
}

内循环的另一个替代方案是Buffer.BlockCopy,但我还没有测量它与Array.Clone 相比的性能——也许它更快:

destination[y] = new int[source[y].Length];
Buffer.BlockCopy(source[y], 0, destination[y], 0, source[y].Length * 4);

编辑:Buffer.BlockCopybytes 的数字用于 count 参数,而不是数组元素的数量。

【讨论】:

  • 我尝试了您的第一个解决方案。不幸的是,它只将整个运行时间缩短了几秒钟。我会尝试你的第二个解决方案。
  • 您的第二个选项与第一个选项非常相似。与我原来的方法相比,总时间只减少了一两秒。
【解决方案3】:

序列化/反序列化数组怎么样,如果你使用内存流和二进制序列化,我认为它应该很快。

【讨论】:

  • 序列化可能比他当前的实现慢几个数量级。
【解决方案4】:

复制对象的更快方法是根本不复制它们 - 您是否考虑过这个选项?如果您只需要生成排列,则不需要在每个排列上复制数据 - 只需更改数组即可。如果您需要保留以前调用的结果,这种方法将无法正常工作。无论如何,请检查您的代码,看看您是否没有复制更多次数据。

【讨论】:

  • 我需要数组的单独副本,因为每个排列都需要有一个原始工作集。
猜你喜欢
  • 2018-11-04
  • 1970-01-01
  • 2020-01-27
  • 1970-01-01
  • 2015-10-18
  • 2014-12-26
  • 2014-03-16
  • 1970-01-01
  • 2015-09-23
相关资源
最近更新 更多