Клонирование зубчатого массива медленнее, чем многомерного массива - PullRequest
0 голосов
/ 25 мая 2018

Я пытаюсь клонировать многомерный массив размером ~ 100x100, и каждый ресурс, который я нахожу, указывает на то, что использование зубчатых массивов должно быть более эффективным (по крайней мере, при поиске, поскольку многомерные массивы используют вызов функции).

Но моя проблема заключается в том, что я выполняю большое клонирование этих массивов, и кажется, что это гораздо медленнее, чем клонирование зубчатых массивов (выделение новых массивов в циклах), чем просто выполнение multArray.Clone ().

Пример кода:

class Program
    {
        static void Main(string[] args)
        {
            int matSize = 100;
            int iterations = 100000;
            Random r = new Random();
            Stopwatch sw = new Stopwatch();
            double[][] jaggedMat = new double[matSize][];
            double[,] multiMat = new double[matSize, matSize];
            for(int i = 0; i < matSize; i++)
            {
                jaggedMat[i] = new double[matSize];
                for (int j = 0; j < matSize; j++)
                {
                    double v = r.NextDouble();
                    jaggedMat[i][j] = v;
                    multiMat[i, j] = v;
                }
            }
            Console.WriteLine($"Cloning jagged matrix old school.");
            sw.Start();
            for (int i=0; i<iterations; i++)
            {
                double[][] copy = new double[matSize][];
                for(int j = 0; j <matSize; j++)
                {
                    copy[j] = new double[matSize];
                    for (int k = 0; k < matSize; k++)
                    {
                        copy[j][k] = jaggedMat[j][k];
                    }
                }
            }
            sw.Stop();
            Console.WriteLine($"Cloning took {sw.ElapsedMilliseconds}ms");
            Console.WriteLine($"Cloning using LINQ");
            sw.Reset();
            sw.Start();
            for (int i = 0; i < iterations; i++)
            {
                var clone = jaggedMat.Select(element => element.ToArray()).ToArray();
            }
            sw.Stop();
            Console.WriteLine($"Cloning took {sw.ElapsedMilliseconds}ms");
            Console.WriteLine($"Cloning multidimensional array.");
            sw.Reset();
            sw.Start();
            for(int i = 0; i < iterations; i++)
            {
                var clone = multiMat.Clone() as double[,];
            }
            sw.Stop();
            Console.WriteLine($"Cloning took {sw.ElapsedMilliseconds}ms");
            Console.ReadKey();
        }
    }

Это дает следующий вывод на мой компьютер:

Клонирование зубчатой ​​матрицы старой школы.Клонирование заняло 4913 мс. Клонирование с использованием LINQ. Клонирование заняло 2283 мс. Клонирование многомерного массива.Клонирование заняло 712 мс

Как вы можете видеть, примерно в 3 раза быстрее .Clone () на матрице того же размера, чем фактически выделяет новые зубчатые массивы.

У любого есть идеи, если естьболее быстрый способ клонирования зубчатых массивов?

Ответы [ 2 ]

0 голосов
/ 25 мая 2018

Сделайте следующее:

double[][] copy = new double[matSize][];
for (int j = 0; j < matSize; j++)
{
    copy[j] = jaggedMat[j].Clone() as double[];
}

Это сделает зазубренный массив всего в 2 раза медленнее, чем многомерный массив (на моей машине 2450мс против 1360мс).Проще говоря, создание 100 объектов (линий зубчатого массива) имеет свою стоимость.GC вас немного возненавидит :-) Все эти объекты должны быть выделены, а затем освобождены, если GC запустится.Это замедляет клонирование зубчатых массивов.Я скажу, что интересно, что затраты настолько медленны (кажется, что создание массива имеет ту же стоимость, что и его заполнение, учитывая, что многомерное клонирование - это чистое заполнение, в то время как клонирование зубчатых массивов - это наполовину копирование и наполовину созданиемассив)

0 голосов
/ 25 мая 2018

Я не измерял производительность.Но вы могли бы решить это намного проще с меньшим количеством кода.Мои решения сериализуют и десериализуют весь массив, чтобы получить его полную копию.

using System.Runtime.Serialization.Formatters.Binary;
BinaryFormatter formatter = new BinaryFormatter();
using(var ms = new MemoryStream())
{
   var array = new int[100, 100];
   array [0, 1] = 57; // simple test data to validate the output.
   formatter.Serialize(ms, array );
   ms.Position = 0; // rewind the stream to deserialize it.
   var copied = formatter.Deserialize(ms);
}
...