qt — Время выполнения функций уменьшается во время выполнения. (C ++) Почему?

Для некоторых целей тестирования я написал фрагмент кода для измерения времени выполнения нескольких быстрых операций в своем коде обработки видео в реальном времени. И все работает нормально. Я получаю очень реалистичные результаты, но я заметил одну интересную особенность.

Я использую POSIX функция clock_gettime с CLOCK_MONOTONIC приписывать. Итак, я получаю временные характеристики с точностью до наносекунды (1 / 1000000000сек), и говорят, что получение временного значения таким образом занимает всего несколько тактов процессора.

Вот две функции, которые я использую для сохранения временных характеристик. Я также добавил определения используемых структур данных:

QVector<long> timeMemory;
QVector<std::string> procMemory;
timespec moment;

void VisionTime::markBegin(const std::string& action) {
if(measure){
clock_gettime(CLOCK_MONOTONIC, &moment);
procMemory.append(action + ";b");
timeMemory.append(moment.tv_nsec);
}
}

void VisionTime::markEnd(const std::string& action) {
if(measure){
clock_gettime(CLOCK_MONOTONIC, &moment);
procMemory.append(action + ";e");
timeMemory.append(moment.tv_nsec);
}
}

Я собираю результаты в пару QVectors, которые будут использованы позже.

Я заметил, что когда эти две функции выполняются в первый раз (сразу после друг друга, между ними ничего нет), разница между двумя сохраненными временными характеристиками составляет ~ 34000 нс. В следующий раз разница будет примерно в 2 раза меньше. И так далее. Если я выполняю их сотни раз, то средняя разница составляет ~ 2000 нс.
Таким образом, среднее повторяющееся выполнение этих функций занимает в 17000 раз меньше времени, чем первая.
Поскольку я делаю сотни измерений подряд, для меня не имеет значения, что некоторые первые исполнения длятся немного дольше. Но в любом случае это меня просто интересует, почему так?

У меня есть различный опыт в Java, но я довольно плохо знаком с C ++. Я не знаю, как много здесь работает.
Я использую флаг O3 для уровня оптимизации.
Мой QMake conf:
QMAKE_CXXFLAGS += -O3 -march=native

Итак, кто-нибудь может сказать, какая часть этого маленького кода становится быстрее во время выполнения, как и почему? Я сомневаюсь, добавив в QVector. Оптимизация как-то влияет на это?

Это мой первый вопрос здесь о stackoverflow, надеюсь, он не слишком длинный 🙂 Большое спасибо за все ваши ответы!

1

Решение

В вашем измерительном коде довольно много потенциальных первоначальных затрат, вот пара и как вы можете их проверить.

Выделение памяти: Этим QVectors не будет выделено никакой памяти в куче, пока вы не используете их в первый раз.

Кроме того, вектор, скорее всего, начнется с выделения небольшого объема памяти, а затем будет экспоненциально распределяться по мере добавления данных (стандартный компромисс для таких контейнеров). Следовательно, у вас будет много выделений памяти к началу вашей среды выполнения, тогда частота будет уменьшаться со временем.

Вы можете убедиться, что это происходит, посмотрев на возвращаемое значение QVector::capacity()и настроить поведение QVector::reserve(int) — например, если вы делаете timeMemory.reserve(10000);, procMemory.reserve(10000);Вы можете зарезервировать достаточно места для первых десяти тысяч измерений до начала измерений.

Ленивая привязка символов: динамический компоновщик по умолчанию не разрешает символы из Qt (или других общих библиотек), пока они не понадобятся. Итак, если эти измерительные функции занимают первое место в вашем коде, где некоторые QVector или же std::string При вызове функций динамический компоновщик должен будет выполнить некоторую разовую работу для разрешения этих функций, что требует времени.

Если это действительно так, вы можете отключить отложенную загрузку, установив переменную окружения LD_BIND_NOW=1 в Linux или DYLD_BIND_AT_LAUNCH=1 на Mac.

2

Другие решения

Вероятно, это связано с предсказанием ветвлений. http://en.wikipedia.org/wiki/Branch_predictor

2

По вопросам рекламы [email protected]