точность rdtsc по ядрам ЦП
Я отправляю сетевые пакеты из одного потока и получаю ответы на 2-й поток, который работает на другом ядре процессора. Мой процесс измеряет время между отправкой и получением каждого пакета (аналогично ping). Я использую rdtsc для получения времени с высоким разрешением и низкими накладными расходами, что необходимо для моей реализации.
все измерения выглядят надежными. Тем не менее, я беспокоюсь о точности rdtsc по ядрам, так как я читал некоторые тексты, которые подразумевали, что tsc не синхронизируется между ядрами.
Я нашел следующую информацию о TSC в Википедии
постоянное поведение TSC гарантирует, что продолжительность каждого такта является форма и поддерживает использование TSC как таймер настенных часов, даже если частота изменения ядра процессора. Этот движется ли архитектурное поведение вперед для всех процессоров Intel.
все еще я беспокоюсь о аккрурация по ядрам, и это мой вопрос
Подробнее
- я запускаю свой процесс на машине Intel nehalem.
- операционная система Linux.
- в "constant_tsc" флаг cpu установлен для всех ядер.
6 ответов
X86_FEATURE_CONSTANT_TSC
+ X86_FEATURE_NONSTOP_TSC
биты в cpuid (edx=x80000007, бит #8; проверка unsynchronized_tsc
функции ядра linux для дополнительных проверок)
vol3b конструктора Intel, раздел 16.11.1 инвариантный TSC он говорит следующее
"16.11.1 инвариантный TSC
счетчик отметок времени в новых процессорах может поддерживать улучшение, называемое инвариантным TSC. Поддержка процессором инвариантного TSC обозначается CPUID.80000007H: EDX[8].
инвариантный TSC будет работать с постоянной скоростью во всех ACPI P -, C -. и Т-состояния. Это архитектурное поведение движется вперед. На процессорах с инвариантной поддержкой TSC ОС может использовать TSC для служб таймера настенных часов (вместо таймеров ACPI или HPET). Чтения TSC намного эффективнее и не несут накладных расходов, связанных с кольцевым переходом или доступом к ресурсу платформы."
Итак, если TSC можно использовать для wallclock, они гарантируется синхронизация.
в linux вы можете использовать clock_gettime (3) с CLOCK_MONOTONIC_RAW, который дает вам результат в наносекундах и не подлежит обновлениям ntp (если таковые имели место).
на самом деле, кажется, что ядра не разделяют TSC, проверьте этот поток: http://software.intel.com/en-us/forums/topic/388964
суммируя, разные ядра не разделяют TSC, иногда TSC может выйти из синхронизации, если ядро изменится на определенное энергетическое состояние, но это зависит от типа процессора, поэтому вам нужно проверить документацию Intel. Похоже, что большинство операционных систем синхронизируют TSC при загрузке.
Я проверил различия между TSC on различные ядра, используя алгоритм захватывающей реакции, на машине Linux Debian с процессором core i5. Процесс возбудителя (в одном ядре) записал TSC в общую переменную, когда реагирующий процесс обнаружил изменение в этой переменной, он сравнивает ее значение и сравнивает его со своим собственным TSC. Это пример вывода моей тестовой программы:
TSC ping-pong test result:
TSC cores (exciter-reactor): 0-1
100 records, avrg: 159, range: 105-269
Dispersion: 13
TSC ping-pong test result:
TSC cores (exciter-reactor): 1-0
100 records, avrg: 167, range: 125-410
Dispersion: 13
время реакции, когда возбудитель ЦП 0 (159 Тики в среднем) почти то же самое, чем когда возбудитель ЦП 1 (167 тики). Этот указывает, что они довольно хорошо синхронизированы (возможно, с несколькими тиками разницы). На других парах ядра результаты были очень похожи.
С другой стороны, инструкция по сборке rdtscp возвращает значение, указывающее процессор, в котором был прочитан TSC. Это не ваш случай, но это может быть полезно, когда вы хотите измерить время в простом сегменте кода, и вы хотите убедиться, что процесс не был перемещен CPU в середине кода.
на последних процессорах вы можете сделать это между отдельными ядрами одного и того же пакета (т. е. системой с одним процессором core iX), вы просто не можете сделать это в отдельных пакетах (процессорах), потому что они не будут делиться rtc. Вы можете уйти с ним через сродство cpu (блокировка соответствующих потоков к определенным ядрам), но опять же это будет зависеть от того, как ведет себя ваше приложение.
в linux вы можете проверить constant_tsc на /proc / cpuinfo, чтобы увидеть, имеет ли процессор один tsc действителен для всего пакета. Необработанный регистр находится в CPUID.80000007H: EDX[8]
то, что я прочитал, но еще не подтвердил программно, заключается в том, что процессоры AMD от версии 11h и далее имеют то же значение для этого бита cpuid.
Я рекомендую вам не использовать rdtsc. Мало того, что он не портативный, он не надежен и вообще не будет работать - на некоторых системах rdtsc не обновляется равномерно (например, если вы используете speedstep и т. д.). Если вам нужна точная информация о времени, вы должны установить параметр SO_TIMESTAMP в сокете и использовать recvmsg() для получения сообщения с меткой времени (с разрешением микросекунды).
кроме того, метка времени, которую вы получаете с SO_TIMESTAMP, на самом деле-это время, когда ядро получило пакет, не тогда, когда ваша задача заметила.
вы можете установить сродство потоков с помощью sched_set_affinity()
API для запуска вашего потока на одном ядре процессора.