производительность c # и возможная оптимизация - PullRequest
0 голосов
/ 30 ноября 2011

У нас есть довольно интересный эффект в небольшом тестовом приложении, которое мы не можем объяснить.

У нас есть блок кода:

while (true)
{
    for (int i = 0; i < 1920; i++)
    {
        for (int j = 0; j < 1080; j++)
        {
            //l += rand.Next(j);
            l += matcher.Next(j);
        }
    }
    k++;

    Console.WriteLine("{0}: Iteration {1}, l: {2}", DateTime.Now.ToString("hh:mm:ss"), k, l);
    l = 0;
    handle.WaitOne(100);
}

И класс Matcher делает только одну вещьего Next(j) вызов.Он возвращает метод Next(j) своего внутреннего объекта Random (поэтому мы добавляем простой вызов функции).

Вот определение класса Matcher:

class Matcher
{
    private Random rand = new Random();

    internal int Next(int j)
    {
        return rand.Next(j);
    }
}

Когда мы выполняем этот кодОдна итерация занимает около 6 секунд на Intel Core 2 Quad.Однако, если мы прокомментируем строку l += matcher.Next(j); и раскомментируем строку l += rand.Next(j);, единственная итерация начнет занимать вторую секунду.

У кого-нибудь есть идеи, почему это происходит?

Ответы [ 4 ]

3 голосов
/ 30 ноября 2011

Это не просто простой вызов функции, это также разыменование внутреннего объекта rand, который там происходит. JIT-компилятор может сильно оптимизировать ваш цикл при непосредственном вызове следующего случайного числа, но не когда он находится внутри другого класса.

Функция вызывается более 2 000 000 раз, и для ее оценки требуется три микросекунды. Это не самая быстрая функция в мире, но и не слишком медленная: эффект умножения убивает производительность.

Если matcher не блокируется или если можно создать несколько его копий, вы можете ускорить его, распараллеливая ваш алгоритм, скажем, восьмипроцессорный для Core2-Quad. Код должен заканчиваться менее чем за секунду.

1 голос
/ 30 ноября 2011

Конечно, дополнительный вызов занимает некоторое время (короткий ответ: P). Сложно сказать, почему это в 6 раз. Когда вы смотрите на производительность, вам лучше посмотреть на сгенерированный IL (используйте, например, ILSpy), так как компилятор может оптимизировать в одной ситуации и не сможет оптимизировать в другой.

В конце одна строка C # может компилироваться в разные инструкции IL или даже переводиться в другой нативный код (так что быстрее работайте на своем компьютере, но медленнее на другом). В некоторых случаях сборщик мусора может даже быть причиной разницы.

0 голосов
/ 30 ноября 2011

Сообщество, большое спасибо за вашу помощь. Проблема заключалась в том, что я запускал это с VS2010 с включенным IntelliTrace: события и вызовы, а не только события. Это было простое объяснение.

0 голосов
/ 30 ноября 2011

Код выглядит нормально.Обязательно запустите это в режиме релиза, так как это может иметь большое значение.Кроме того, я даже видел, как установка целевых показателей платформы оказала значительное влияние на некоторые операции низкого уровня.Так что попробуйте и x86, и x64.

Я настроил его на запуск в режиме выпуска для «Любого ЦП» с включенным «Оптимизировать код», и он работает за 39 мс.

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