Научимся Правильно Проводить Бенчмаркинг (Включая Итераторы)

Скачал пример из предыдущего постинга, от запуска к запуску время колебалось до 1,5 раз, от 0,76 до 1,09 секунды.

Неясно, как можно оценить результаты таких тестов.

Проблема знакомая, столкнулся с ней и решил буквально вчера.

Короче говоря, виноват троттлинг процессора, а также странное сходство в коде.

Под катом идет борьба (успешная) и обсуждение.

Итак, выполняется предыдущий пример об итераторах, VS 2005, 4. Машина полностью разгружена, торренты и т.п.

в фоне не работают, даже Winamp выключен.

(Хотя, кстати, при нагрузках, связанных с CPU, наличие Winamp и даже торрентов особого лишнего джиттера не создает, максимум 1-2%.

) Результаты варьируются от 0,758 до 1,085, что почти в 1,5 раза.

На разных заездах опять же выигрывают разные вещи, что для гонки неприемлемо.

;)

   

x = 3256681784 iterator++.

Total time : 0.795557 x = 3256681784 ++iterator. Total time : 0.892076 x = 3256681784 iterator++.

Total time : 1.08741 x = 3256681784 ++iterator. Total time : 1.0848 x = 3256681784 iterator++.

Total time : 0.898355 x = 3256681784 ++iterator. Total time : 0.758123 x = 3256681784 iterator++.

Total time : 0.906159 x = 3256681784 ++iterator. Total time : 0.861794

В чем дело? Смотрим код, там есть QPC, а перед ним SetThreadAffinityMask. Измена, не наша в штабе.

Процессор C2D способен поддерживать разные частоты на разных ядрах.

А когда ОС простаивает, она этим пользуется и снижает частоту.

Если откалибровать таймер (QueryPerformanceFrequency) на одном ядре и прочитать данные счетчика (QueryPerformanceCounter) на другом, или на том же, но после повышения частоты будет фигня.

Меняем ровно один символ, второй параметр в SetThreadAffinityMask ставим равным 1, а не 0.

x = 3256681784 iterator++.

Total time : 0.751778 x = 3256681784 ++iterator. Total time : 0.685859 x = 3256681784 iterator++.

Total time : 0.737615 x = 3256681784 ++iterator. Total time : 0.686026 x = 3256681784 iterator++.

Total time : 0.736503 x = 3256681784 ++iterator. Total time : 0.688713 x = 3256681784 iterator++.

Total time : 0.772983 x = 3256681784 ++iterator. Total time : 0.68895

Намного лучше.

Первый тест дрожит от 0,736 до 0,772, т.е.

на 5%, а не на 50%.

Второй – от 0,686 до 0,689, т.е.

на 0,4%.

Почему такая разница? Гипотеза.

К моменту начала второго теста кэш нагревается.

Читаем внимательно код. Однако есть 5000 прогонов, холодный кэш что-то изменит только для первого.

Гипотеза неверна, отбросьте ее.

Гипотеза.

Первое испытание – это первое.

Возможно, в процессе происходит увеличение частоты ядра.

Что ж, давайте прогреем процессор перед всеми тестами.

Поскольку компилятор очень умен и стремится предварительно вычислить и оптимизировать константы, особенно те, которые не используются, мы помним о волшебном модификаторе voluty. Пересобрать, упс, не помогло.

Давайте вспомним о близости.

Прикрепляем к одному сердечнику весь процесс, а не только кусок, который рассчитан (иначе есть опасность нагреть не тот сердечник).

Перестройся, ой, победа! Итого мы поместили эти 4 строчки в самое начало программы.



SetProcessAffinityMask(GetCurrentProcess(), 1); volatile int zomg = 1; for ( int i=1; i<1000000000; i++ ) zomg *= i;

И наслаждаемся результатом.



x = 3256681784 iterator++.

Total time : 0.687585 x = 3256681784 ++iterator. Total time : 0.685685 x = 3256681784 iterator++.

Total time : 0.687524 x = 3256681784 ++iterator. Total time : 0.68579 x = 3256681784 iterator++.

Total time : 0.686004 x = 3256681784 ++iterator. Total time : 0.688326 x = 3256681784 iterator++.

Total time : 0.688472 x = 3256681784 ++iterator. Total time : 0.685775

Бинго.

Джиттер составляет менее 1%, что вполне нормально.

И вот наконец-то различий нет. Как, собственно, и должно быть по теории.

(В релизе оба итератора должны превратиться в обход указателя; в отладке с включенным SECURE_SCL, конечно, в полный ад с элементами Израиля.

) В Linux есть точно такая же проблема, она называется регулятор производительности.

Переключение говернора на что-то вроде производительности, а также прогрев игр с аффинити и т.п.

тоже помогает. Правильные ориентиры для вас.

Теги: #C++ #бенчмаркинг #C++

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.