Является ли этот популярный ответ StackOverflow неправильным? - PullRequest
4 голосов
/ 17 августа 2011

Пост, о котором я говорю, это this. Для меня не только первый работает быстрее (563 MS по сравнению с 630) при увеличении размера до 100000000, но и в прошлом, используя свойства в для циклов вызвало значительное замедление скорости.

Один раз при записи средства просмотра формы сигнала каждый кадр обрабатывался в среднем по 23 миллисекунды. Цикл for, который прошел через все пиксели изображения, стал причиной замедления. Вместо того, чтобы хранить ширину и высоту картинки перед циклом for, я получал к ней доступ во время каждой итерации. После его изменения время обработки одного кадра увеличилось с 23 миллисекунд до 3.

Кроме того, я сделал этот пример класса:

class LOL
{
    private int x;

    public LOL(int x)
    {
        this.x = x;
    }

    public int X
    {
        get
        {
            return x;
        }
    }
}

Затем я создал цикл for, который повторяется 500000000 раз. Один тест хранил X в целочисленной переменной еще до начала цикла, а другой обращался к свойству X во время каждой итерации. Первое заняло приблизительно 1500 миллисекунд, а второе около 8000.

Три теста, каждый из которых завершается тем, что предварительное сохранение предельного значения является оптимальным решением для повышения производительности. Я что-то пропустил? В настоящее время в моей программе требуется оптимизация, так как обрабатываются большие изображения, и во всех областях, критичных к производительности, я всегда сохраняю границы цикла перед рукой для повышения производительности, и эти тесты, кажется, подтверждают это.

Ответы [ 2 ]

5 голосов
/ 17 августа 2011

Нет, мне это кажется правильным;если я запустил это:

int[] values = new int[100000000];

var watch = Stopwatch.StartNew();
int length = values.Length;
for (int i = 0; i < length; i++)
    values[i] = i;
watch.Stop();
var hoisted = watch.ElapsedMilliseconds;

watch = Stopwatch.StartNew();
for (int i = 0; i < values.Length; i++)
    values[i] = i;
watch.Stop();
var direct = watch.ElapsedMilliseconds;

и собрал с оптимизацией, запустив из консоли;Я получаю direct как 71 и hoisted как 163, что связано с тем, что я ожидаю от JIT, исключая проверку за пределами вектора (но только при непосредственном доступе).

1 голос
/ 18 августа 2011

Скомпилировано в режиме release , длина кэша быстрее. На отладке все наоборот.

Метод испытания

public static class Performance
{
    public static void Test(string name, decimal times, bool precompile, Action fn)
    {
        if (precompile)
        {
            fn();
        }

        GC.Collect();
        Thread.Sleep(2000);

        var sw = new Stopwatch();

        sw.Start();

        for (decimal i = 0; i < times; ++i)
        {
            fn();
        }

        sw.Stop();

        Console.WriteLine("[{0,15}: {1,-15}]", name, new DateTime(sw.Elapsed.Ticks).ToString("HH:mm:ss.fff"));
        Debug.WriteLine("[{0,15}: {1,-15}]", name, new DateTime(sw.Elapsed.Ticks).ToString("HH:mm:ss.fff"));
    }
}

Тестовый код:

var testAmount = 100;

int[] a1 = new int[10000000];
int[] a2 = new int[10000000];

Performance.Test
(
    "Direct", testAmount, true,
    () =>
    {
        for (int i = 0; i < a1.Length; ++i)
        {
            a1[i] = i;
        }
    }
);

Performance.Test
(
    "Cache", testAmount, true,
    () =>
    {
        var l = a2.Length;
        for (int i = 0; i < l; ++i)
        {
            a2[i] = i;
        }
    }
);

Результаты отладки

[   Direct: 00:00:06.474   ]
[   Cache:  00:00:06.907   ]

Результаты релиза

[   Direct: 00:00:05.382   ]
[   Cache:  00:00:04.714   ]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...