Что лучше в отношении производительности? введите [,] или введите [] []? - PullRequest
5 голосов
/ 04 октября 2008

Является ли более эффективным иметь двумерный массив (type[,]) или массив массивов (type[][]) в C #?

Особенно для начального распределения и доступа к элементу

Ответы [ 4 ]

5 голосов
/ 04 октября 2008

Конечно, если ничего не помогает ... проверьте это! Вот что дает (в «Release», на консоли):

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

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

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

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);
    }
}
2 голосов
/ 04 октября 2008

Это действительно зависит. В статье MSDN Magazine, Использование возможностей C # для поддержки ваших научных вычислительных проектов , говорится следующее:

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

2 голосов
/ 04 октября 2008

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

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

Как отметил Марк Гравелл, использование - это ключ к оценке производительности ...

0 голосов
/ 04 октября 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...