std::chrono::clock, аппаратные часы и счетчик тактов

std::chrono предложить несколько часов, чтобы измерить время. В то же время, я полагаю, что единственный способ, которым процессор может оценивать время, - это подсчет циклов.

Вопрос 1: Есть ли у процессора или графического процессора какой-либо другой способ оценивать время, кроме подсчета циклов?

Если это так, потому что способ, которым компьютер считает циклы, никогда не будет столь же точным, как атомные часы, это означает, что "секунда" (period = std::ratio<1>) для компьютера может быть на самом деле короче или больше, чем фактическая секунда, вызывая различия в долгосрочной перспективе для измерения времени между компьютерными часами и, скажем, GPS.

Вопрос 2: это правильно?

Некоторые аппаратные средства имеют различные частоты (например, режим ожидания и турбо-режимы). В этом случае это будет означать, что число циклов будет меняться в течение секунды.

Вопрос 3: Изменяется ли "количество циклов", измеренное процессором и процессором, в зависимости от аппаратной частоты? Если да, то как std::chrono иметь дело с этим? Если нет, то чему соответствует цикл (например, каково "фундаментальное" время)? Есть ли способ получить доступ к преобразованию во время компиляции? Есть ли способ получить доступ к конвертации во время выполнения?

2 ответа

Решение

Подсчет циклов, да, но циклы чего?

На современном x86, источник времени, используемый ядром (внутренне и для clock_gettime и другие системные вызовы), как правило, представляет собой счетчик с фиксированной частотой, который подсчитывает "опорные циклы" независимо от режима турбонаддува, энергосбережения или останова по времени. (Это счетчик, который вы получаете от rdtsc, или же __rdtsc() в C / C++).

Нормальный std::chrono реализации будут использовать функцию, предоставляемую ОС, например, clock_gettime на Unix. (В Linux это может выполняться исключительно в пользовательском пространстве, код + данные масштабного коэффициента на странице VDSO, отображаемой ядром в адресное пространство каждого процесса. Хорошие временные источники с низкими издержками хороши. Избегайте двусторонней обработки user->kernel->user очень помогает с включенным смягчением Meltdown + Spectre.)

Для профилирования замкнутого цикла, который не связан с памятью, может потребоваться использование фактических тактов ядра, поэтому он будет нечувствителен к фактической скорости текущего ядра. (И не нужно беспокоиться о том, чтобы увеличить процессор до макс. Турбо и т. Д.), Например, используя perf stat ./a.out или же perf record ./a.out, Например, может ли MOV x86 действительно быть "свободным"? Почему я не могу воспроизвести это вообще?


Некоторые системы не имеют / не имеют встроенного в ЦП счетчика, эквивалентного настенным часам, поэтому либо ОС будет поддерживать время в ОЗУ, которое она обновляет при прерываниях по таймеру, либо функции запроса времени будут считывать время из отдельной микросхемы.

(Системный вызов + аппаратный ввод / вывод = более высокие издержки, что является одной из причин того, что x86 rdtsc инструкция превратилась из профилирующей вещи в хронометраж.)

Все эти тактовые частоты в конечном итоге получены из кварцевого генератора на mobo. Но масштабные коэффициенты для экстраполяции времени из числа циклов могут быть скорректированы, чтобы синхронизировать часы с атомным временем, обычно используя сетевой протокол времени (NTP), как указывает @Tony.

Вопрос 1: Есть ли у процессора или графического процессора какой-либо другой способ оценивать время, кроме подсчета циклов?

Различное оборудование может предоставлять разные возможности. Например, на компьютерах x86 для синхронизации использовалось несколько аппаратных средств: в течение последнего десятилетия или около того в процессорах x86 использовались счетчики отметок времени, работающие на частоте их обработки или, в последнее время, на некоторой фиксированной частоте ("постоянная скорость", то есть "инвариантная" TSC).; может быть высокоточный таймер событий, и в дальнейшем были программируемые таймеры прерываний ( https://en.wikipedia.org/wiki/Programmable_interval_timer).

Если дело обстоит так, потому что способ подсчета циклов компьютера никогда не будет таким же точным, как атомные часы, это означает, что "секунда" (period = std::ratio<1>) для компьютера может быть на самом деле короче или больше чем фактическая секунда, вызывая различия в долгосрочной перспективе для измерения времени между компьютерными часами и, скажем, GPS.

Да, компьютер без атомных часов (теперь они доступны на чипе) не будет столь же точным, как атомные часы. Тем не менее, такие службы, как сетевой протокол времени, позволяют поддерживать более тесную согласованность на нескольких компьютерах.

Вопрос 3: Изменяется ли "количество циклов", измеренное процессором и процессором, в зависимости от аппаратной частоты?

Это зависит от. Для TSC более новые реализации TSC с "постоянной скоростью" не меняются, другие меняются.

Если да, то как std::chrono справится с этим?

Я ожидаю, что большинство реализаций будут вызывать службу времени, предоставляемую ОС, так как ОС обычно лучше знает и имеет доступ к аппаратному обеспечению. Есть много факторов, которые необходимо учитывать - например, синхронизированы ли показания TSC между ядрами, что происходит, если ПК переходит в какой-то режим ожидания, какой тип ограждений памяти желателен во время выборки TSC...,

Если нет, то чему соответствует цикл (например, каково "фундаментальное" время)?

Для процессоров Intel смотрите этот ответ.

Есть ли способ получить доступ к преобразованию во время компиляции? Есть ли способ получить доступ к конвертации во время выполнения?

std::chrono::duration::count выставляет счетчики необработанных тиков за любой использованный источник времени, и вы можете duraction_cast в другие единицы времени (например, секунды). C++20, как ожидается, представит дополнительные возможности, такие как clock_cast, AFAIK, нет constexpr Доступное преобразование: кажется сомнительным, если программа может в конечном итоге работать на машине с другой скоростью TSC, чем на машине, на которой она была скомпилирована.

Другие вопросы по тегам