2008-10-03 3 views
5

Насколько эффективнее иметь двумерный массив (type[,]) или массив массивов (type[][]) в C#?Что лучше в отношении производительности? type [,] или type [] []?

В частности, для первоначального распределения и доступа пункта

+0

Также см. [Why-are-many-array-arrays-in-net-slower-than-normal-arrays?] (Http://stackoverflow.com/questions/468832/why-are-multi- размерные массивы в сетке-медленнее, чем нормальные-массивы?) – nawfal 2013-10-13 13:36:52

ответ

5

Конечно, если все остальное терпит неудачу ... испытайте его! После дает (в «Release», в консоли):

Size 1000, Repeat 1000 
    int[,] set: 3460 
    int[,] get: 4036 (chk=1304808064) 
    int[][] set: 2441 
    int[][] get: 1283 (chk=1304808064) 

Так зазубренный массив быстрее, по крайней мере, в этом тесте. Интересно! Однако, это относительно небольшой фактор, поэтому я все равно придерживаюсь того, что лучше описывает мои требования. За исключением некоторых конкретных сценариев (высокая производительность процессора/обработки), читаемость/ремонтопригодность должны превзойти небольшое увеличение производительности. До вас, правда.

Обратите внимание, что этот тест предполагает, что вы получаете доступ к массиву гораздо чаще, чем его создаете, поэтому я не включил тайминги для создания, где я бы ожидал, что будет немного быстрее, если память сильно фрагментирована.

using System; 
using System.Diagnostics; 
static class Program 
{ 
    static void Main() 
    { 
     Console.WriteLine("First is just for JIT..."); 
     Test(10,10); 
     Console.WriteLine("Real numbers..."); 
     Test(1000,1000); 

     Console.ReadLine(); 
    } 

    static void Test(int size, int repeat) 
    { 
     Console.WriteLine("Size {0}, Repeat {1}", size, repeat); 
     int[,] rect = new int[size, size]; 
     int[][] jagged = new int[size][]; 
     for (int i = 0; i < size; i++) 
     { // don't cound this in the metrics... 
      jagged[i] = new int[size]; 
     } 
     Stopwatch watch = Stopwatch.StartNew(); 
     for (int cycle = 0; cycle < repeat; cycle++) 
     { 
      for (int i = 0; i < size; i++) 
      { 
       for (int j = 0; j < size; j++) 
       { 
        rect[i, j] = i * j; 
       } 
      } 
     } 
     watch.Stop(); 
     Console.WriteLine("\tint[,] set: " + watch.ElapsedMilliseconds); 

     int sum = 0; 
     watch = Stopwatch.StartNew(); 
     for (int cycle = 0; cycle < repeat; cycle++) 
     { 
      for (int i = 0; i < size; i++) 
      { 
       for (int j = 0; j < size; j++) 
       { 
        sum += rect[i, j]; 
       } 
      } 
     } 
     watch.Stop(); 
     Console.WriteLine("\tint[,] get: {0} (chk={1})", watch.ElapsedMilliseconds, sum); 

     watch = Stopwatch.StartNew(); 
     for (int cycle = 0; cycle < repeat; cycle++) 
     { 
      for (int i = 0; i < size; i++) 
      { 
       for (int j = 0; j < size; j++) 
       { 
        jagged[i][j] = i * j; 
       } 
      } 
     } 
     watch.Stop(); 
     Console.WriteLine("\tint[][] set: " + watch.ElapsedMilliseconds); 

     sum = 0; 
     watch = Stopwatch.StartNew(); 
     for (int cycle = 0; cycle < repeat; cycle++) 
     { 
      for (int i = 0; i < size; i++) 
      { 
       for (int j = 0; j < size; j++) 
       { 
        sum += jagged[i][j]; 
       } 
      } 
     } 
     watch.Stop(); 
     Console.WriteLine("\tint[][] get: {0} (chk={1})", watch.ElapsedMilliseconds, sum); 
    } 
} 
+0

Я видел те же результаты в блоге оптимизации .NET в msdn. – dalle 2008-10-04 08:36:20

2

Я считаю, что [,] может выделить один непрерывный кусок памяти, в то время как [] [] является N + 1 порции распределения, где N является размером первого измерения. Поэтому я предполагаю, что [,] быстрее при первоначальном распределении.

Доступ, вероятно, примерно такой же, за исключением того, что [] [] будет включать в себя еще одно разыменование. Если вы не находитесь в исключительно узкой петле, это, вероятно, стирка. Теперь, если вы делаете что-то вроде обработки изображений, где вы ссылаетесь на между строками, а не пересекаете строку за строкой, локальность ссылки будет играть большой фактор, и [,], вероятно, будет крайнее [] [] в зависимости от вашего кеша размер.

Как уже упоминалось Марк Gravell, использование является ключевым для оценки эффективности ...

-1

типа [,] будет работать быстрее. Не только из-за меньших расчетных расчетов. В основном из-за меньшей проверки ограничений, уменьшения объема памяти и большей локализации в памяти. type [] [] не является одним объектом - это 1 + N объектов, которые должны быть выделены и могут быть друг от друга.

+0

Этот ответ начинается с абсолютного утверждения, которое (в моем скромном опыте) неверно ... Как я понимаю (я не знаю все) -подписной массив на самом деле делает БОЛЬШЕ вычислений для каждого доступа, потому что мы должны «сгладить» индексы в фактический одноцепочечный индекс ... Например, заданный var a = int [16,16], тогда [1,1] на самом деле является [16 * 1 + 1] -> a [17] ... и что вычисление строки * ROWS + col занимает больше времени (в среднем), чем две разницы, необходимые для возврата значения [1] [1] в эквивалентном jagged array ... Вот почему я отказался от этого ответа.Извините за это, но ИМХО это вводит в заблуждение. – corlettk 2012-10-27 05:49:57

2

На самом деле это зависит. В статье MSDN Magazine, Harness the Features of C# to Power Your Scientific Computing Projects, говорит, что это:

Хотя прямоугольные массивы, как правило, превосходят неровными массивы с точки зрения структуры и производительности, могут быть некоторые случаи, когда неровные массивы обеспечивают оптимальное решение. Если ваше приложение не требует сортировки, перераспределения, разделения, разрежения или большого размера массивов, вы можете обнаружить, что массивы с зубчатыми колесами работают достаточно хорошо.

Смежные вопросы