Похоже, вы используете результат поиска (печатая его с cout
* вне временной области, это хорошо). И данные + ключ рандомизированы, поэтому поиск не должен быть оптимизирован во время компиляции. (Тестирование с отключенной оптимизацией не имеет смысла, поэтому вам нужны такие приемы.)
Вы смотрели на timeElapsed
с помощью отладчика? Может быть, это очень маленький float
, который печатает как 0
с настройками по умолчанию cout
?
Или, может быть, float endTime
- float startTime
фактически равен 0.0f
, потому что округление до ближайшего float
сделало их равными . Вычитание двух больших соседних чисел с плавающей запятой приводит к «катастрофической отмене».
Помните, что float
имеет только 24 бита значений и , поэтому независимо от частоты, на которую вы делитесь, если значения PerformanceCounter отличаются менее чем на 1 часть в 2 ^ 24, вы получите ноль , (Если эта функция возвращает необработанные значения из x86 rdtsc
, то это произойдет, если последняя перезагрузка вашей системы была более чем в 2 ^ 24 раза дольше, чем временной интервал. X86 TSC начинается с нуля при загрузке системы, и (на процессорах за последние ~ 10 лет) учитывается при «эталонной частоте», которая (приблизительно) равна номинальной / «наклейке» частоты вашего ЦП, независимо от частоты турбо или холостого хода. См. Получить количество тактов ЦП? )
double
может помочь, но гораздо лучше вычесть в целочисленной области перед делением . Кроме того, перезапись этой части займет QueryPerformanceFrequency
из заданного интервала!
Как подсказывает @Jon, часто лучше тестировать код в цикле повтора в течение одного более длительного временного интервала, чтобы кэши (код) и предсказание переходов могли прогреться.
Но тогда у вас есть проблема, чтобы убедиться, что повторные вызовы не оптимизированы, и рандомизировать ключ поиска внутри цикла. (В противном случае умный компилятор может вывести поиск из цикла).
Может помочь что-то вроде volatile int result = binSearch(...);
, потому что присвоение (или инициализация) volatile
является видимым побочным эффектом, который нельзя оптимизировать. Таким образом, компилятор должен фактически реализовать каждый результат поиска в регистре.
Для некоторых компиляторов, например те, которые поддерживают встроенный ассемблер GNU C, вы можете использовать встроенный ассемблер, чтобы требовать, чтобы компилятор генерировал значение в регистре без , добавляя любые накладные расходы на его хранение в любом месте. AFAIK это невозможно с встроенным asm MSVC.