точность rdtsc между ядрами процессора - PullRequest
28 голосов
/ 02 августа 2010

Я отправляю сетевые пакеты из одного потока и получаю ответы во втором потоке, который работает на другом ядре ЦП.Мой процесс измеряет время между отправкой и получением каждого пакета (аналогично ping).Я использую rdtsc для получения синхронизации с высоким разрешением и минимальными издержками, что необходимо для моей реализации.

Все измерения выглядят надежно.Тем не менее, меня беспокоит точность rdtsc для разных ядер, так как я читал некоторые тексты, в которых подразумевалось, что tsc не синхронизируется между ядрами.

Я нашел следующую информацию о TSC в википедии

Постоянное поведение TSC гарантирует, что длительность каждого тактового такта является равномерным, и поддерживает использование TSC в качестве настенного таймера, даже если ядро ​​процессора меняет частоту ,Это архитектурное поведение, движущееся вперед для всех процессоров Intel.

Тем не менее меня беспокоит нарастание нагрузки между ядрами, и это мой вопрос

Подробнее

  • Я запускаю процесс на машине Intel Nehalem.
  • Операционная система - Linux.
  • " constant_tsc" "Флаг процессора установлен для всех ядер.

Ответы [ 6 ]

26 голосов
/ 10 ноября 2010

X86_FEATURE_CONSTANT_TSC + X86_FEATURE_NONSTOP_TSC бит в cpuid (edx = x80000007, бит # 8; проверка unsynchronized_tsc функция ядра linux для дополнительных проверок)

Intel's Designer vol3b, раздел 16.11.1 Инвариантный TSC говорит следующее

"16.11.1 Инвариант TSC

Счетчик меток времени в более новых процессорах может поддерживать расширение, называемое инвариантным TSC. Поддержка процессором инвариантного TSC обозначается CPUID.80000007H: EDX [8].

Инвариант TSC будет работать с постоянной скоростью во всех ACPI P-, C-. и Т-состояния. Это архитектурное поведение, движущееся вперед. На процессорах с инвариантной поддержкой TSC ОС может использовать TSC для служб таймера настенных часов (вместо таймеров ACPI или HPET). Чтения TSC намного более эффективны и не требуют дополнительных затрат, связанных с переходом по кольцу или доступом к ресурсу платформы. "

Итак, если TSC можно использовать для настенных часов, они гарантированно синхронизируются.

3 голосов
/ 17 января 2014

На последних процессорах вы можете делать это между отдельными ядрами одного и того же пакета (то есть системой с одним ядром iX-процессора), вы просто не можете делать это в отдельных пакетах (процессорах), потому что они не будут совместно РТК. Вы можете избежать неприятностей с помощью привязки к процессору (привязывая соответствующие потоки к конкретным ядрам), но опять же это будет зависеть от поведения вашего приложения.

В linux вы можете проверить constant_tsc в / proc / cpuinfo, чтобы увидеть, имеет ли процессор единый tsc, действительный для всего пакета. Необработанный регистр находится в CPUID.80000007H: EDX [8]

То, что я прочитал, но еще не подтвердил программно, это то, что процессоры AMD начиная с версии 11h имеют то же значение для этого бита процессора.

2 голосов
/ 20 февраля 2014

На самом деле, кажется, что ядра не разделяют TSC, проверьте этот поток: http://software.intel.com/en-us/forums/topic/388964

Подводя итог, разные ядра не разделяют TSC, иногда TSC может выйти из синхронизации, если ядро ​​изменится наконкретное состояние энергии, но оно зависит от типа процессора, поэтому вам нужно проверить документацию Intel.Кажется, что большинство операционных систем синхронизируют TSC при загрузке.
Я проверил различия между TSC на разных ядрах, используя захватывающий алгоритм реагирования, на машине 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.Это не ваш случай, но он может быть полезен, когда вы хотите измерить время в простом сегменте кода и хотите убедиться, что процесс не был перемещен из ЦП в середине кода.

2 голосов
/ 29 августа 2010

В linux вы можете использовать clock_gettime (3) с CLOCK_MONOTONIC_RAW, что дает вам перенесение на наносекунды и не требует обновления ntp (если это произошло).

0 голосов
/ 17 октября 2010

Вы можете установить соответствие потоков с помощью sched_set_affinity() API, чтобы запускать поток на одном ядре ЦП.

0 голосов
/ 03 августа 2010

Я рекомендую не использовать rdtsc.Он не только не переносим, ​​он не надежен и, как правило, не будет работать - в некоторых системах rdtsc не обновляется равномерно (например, если вы используете speedstep и т. Д.).Если вам нужна точная информация о времени, вы должны установить опцию SO_TIMESTAMP в сокете и использовать recvmsg () для получения сообщения с меткой времени (микросекундное разрешение).

Более того, метка времени, которую вы получаете с SO_TIMESTAMP, фактически является временемядро получило пакет, а не когда ваша задача заметила.

...