Итак, как обсуждалось в комментариях, проблема заключается в том, что quick-bench.com показывает не абсолютное время для кода, измеренного в тестах, а скорее время относительно времени, которое занял тест без опций. Контрольный тест no-op можно найти в исходных файлах quick-bench.com:
static void Noop(benchmark::State& state) {
for (auto _ : state) benchmark::DoNotOptimize(0);
}
Все тесты прогона скомпилированы вместе. Поэтому флаги оптимизации применимы и к нему.
Воспроизведение и сравнение безоперационного бенчмарка для разных уровней оптимизации можно видеть, что с 6 до 7 раз происходит ускорение-O0
до -O1
версия. При сравнении прогонов тестов, выполненных с различными флагами оптимизации, этот фактор в базовой линии должен учитываться для сравнения результатов. Таким образом, 4-кратное ускорение, наблюдаемое в контрольном задании вопроса, более чем компенсировано, и поведение действительно такое, как можно было бы ожидать. что для -O0
в коде google-benchmark есть некоторые утверждения и другие дополнительные ветви, оптимизированные для более высоких уровней оптимизации.
Кроме того, при -O0
каждая итерация цикла загружается в регистр,изменять и сохранять в памяти части state
несколько раз, например, для уменьшения счетчика цикла и условных выражений на счетчике цикла, в то время как версия -O1
будет хранить state
в регистрах, что делает ненужной загрузку / сохранение памяти в цикле,Первый из них гораздо медленнее, он занимает не менее нескольких циклов на итерацию для необходимых пересылок хранилища и / или перезагрузок из памяти.