Ответ 1
Пока ваш поток остается на одном ядре ЦП, инструкция RDTSC будет продолжать увеличивать число, пока оно не обернется. Для CPU с частотой 2 ГГц это происходит через 292 года, поэтому это не проблема. Вероятно, вы этого не увидите. Если вы так долго будете жить, убедитесь, что ваш компьютер перезагружается, скажем, каждые 50 лет.
Проблема с RDTSC заключается в том, что у вас нет гарантии, что он начнется в тот же момент времени на всех ядрах старого многоядерного процессора и не будет гарантировать, что он начнется с той же точки времени на всех процессорах пожилого мульти -CPU.
Современные системы, как правило, не имеют таких проблем, но проблему можно также проработать на более старых системах, установив сходство потоков, чтобы он работал только на одном CPU. Это не очень хорошо для производительности приложения, поэтому обычно не следует это делать, но для измерения тиков это просто отлично.
(Еще одна "проблема" заключается в том, что многие люди используют RDTSC для измерения времени, а это не то, что он делает, но вы написали, что хотите циклы процессора, так что это нормально. Если вы используете RDTSC для измерения времени, вы можете есть сюрпризы, когда энергосбережение или гипербонус или что-то другое, что называется частотным изменением, называется kicks in. В течение фактического времени syscall clock_gettime
на удивление хорош в Linux.)
Я бы просто написал rdtsc
внутри оператора asm
, который отлично подходит для меня и более читабельен, чем какой-то неясный шестнадцатеричный код. Предполагая, что это правильный шестнадцатеричный код (и поскольку он не падает и возвращает постоянно увеличивающееся число, кажется, что так), ваш код хорош.
Если вы хотите измерить количество тиков, которые занимает кусок кода, вам нужно отметить разницу, вам просто нужно вычесть два значения постоянно увеличивающегося счетчика. Что-то вроде uint64_t t0 = rdtsc(); ... uint64_t t1 = rdtsc() - t0;
Обратите внимание, что если необходимы очень точные измерения, выделенные из окружающего кода, вам необходимо сериализовать, то есть скрыть конвейер, до вызова rdtsc
(или использовать rdtscp
, который поддерживается только на более новых процессорах). Одна команда сериализации, которая может использоваться на каждом уровне привилегий, - cpuid
.
В ответ на следующий вопрос в комментарии:
TSC начинается с нуля при включении компьютера (и BIOS сбрасывает все счетчики на всех процессорах на одно и то же значение, хотя некоторые BIOS несколько лет назад не делали этого надежно).
Таким образом, с вашей программной точки зрения счетчик начал "некоторое неизвестное время в прошлом", и он всегда увеличивается с каждым тактом, который видит процессор. Поэтому, если вы выполните команду, возвращающую этот счетчик сейчас и в любое время позже в другом процессе, она вернет большее значение (если CPU не был приостановлен или не отключен между ними). Различные прогоны той же программы получают большее количество, потому что счетчик продолжает расти. Всегда.
Теперь clock_gettime(CLOCK_PROCESS_CPUTIME_ID)
- это другое дело. Это время CPU, которое ОС предоставила процессу. Он начинается с нуля, когда начинается процесс. Новый процесс также начинается с нуля. Таким образом, два процесса, которые работают друг за другом, получат очень похожие или одинаковые числа, а не растущие.
clock_gettime(CLOCK_MONOTONIC_RAW)
ближе к тому, как работает RDTSC (и на некоторых старых системах реализовано с ним). Он возвращает значение, которое когда-либо увеличивается. В настоящее время это, как правило, HPET. Однако это действительно время, а не тики. Если ваш компьютер переходит в низкое энергопотребление (например, работает на 1/2 нормальной частоте), он все равно будет двигаться с одинаковым темпом.