Linux узнает Hyper-threaded core id

Сегодня утром я попытался выяснить, как определить, какой идентификатор процессора является гиперпотоковым ядром, но без везения.

Я хочу узнать эту информацию и использовать set_affinity() для привязки процесса к потоку с гиперпотоком или потоком без гиперпотока, чтобы определить его производительность.

Ответ 1

Я обнаружил простой трюк, чтобы сделать то, что мне нужно.

cat /sys/devices/system/cpu/cpu0/topology/thread_siblings_list

Если первое число равно номеру CPU (0 в этом примере), то это реальное ядро, если оно не является гиперпотоковым ядром.

Реальный основной пример:

# cat /sys/devices/system/cpu/cpu1/topology/thread_siblings_list
1,13

Пример ядра Hyperthreading

# cat /sys/devices/system/cpu/cpu13/topology/thread_siblings_list
1,13

Результат второго примера точно такой же, как и первый. Однако мы проверяем cpu13, а первое число 1, поэтому CPU 13 это гиперпотоковое ядро.

Ответ 2

HT симметричен (в терминах базовых ресурсов системный режим может быть асимметричным).

Итак, если HT включен, большие ресурсы физического ядра будут разделены между двумя потоками. Некоторые дополнительные аппаратные средства включены для сохранения состояния обоих потоков. Оба потока имеют симметричный доступ к физическому ядру.

Существует разница между ядром с HT-отключением и ядром с поддержкой HT; но нет разницы между первой половиной ядра с поддержкой HT и второй половиной ядра с поддержкой HT.

В один момент времени один HT-поток может использовать больше ресурсов, чем другие, но эта балансировка ресурсов динамична. Процессор будет балансировать потоки, насколько это возможно, и по мере того как он хочет, чтобы оба потока хотели использовать один и тот же ресурс. Вы можете делать только rep nop или pause в одном потоке, чтобы позволить ЦП давать больше ресурсов другому потоку.

Я хочу узнать эту информацию и использовать set_affinity() для привязки процесса к потоку с гиперпотоком или потоком без гиперпотока, чтобы профилировать его производительность.

Хорошо, вы действительно можете измерить производительность, не зная факта. Просто выполните профиль, когда единственный поток в системе привязан к CPU0; и повторите его, когда он привязан к CPU1. Я думаю, что результаты будут практически одинаковыми (ОС может генерировать шум, если он связывает некоторые прерывания с CPU0, поэтому постарайтесь уменьшить количество прерываний при тестировании и попытаться использовать CPU2 и CPU3, если они есть).

PS

Агнер (он - Гуру в x86) рекомендует использовать четные ядра в случае, если вы не хотите использовать HT, но он включен в BIOS:

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

PPS О новой реинкарнации HT (не P4, но Nehalem и Sandy) - на основе исследований Agner по микроархитектуре

Новые узкие места, требующие внимания в Sandy Bridge, следующие:... 5. Обмен ресурсами между потоками. Многие из критически важных ресурсов между двумя нитями ядра, когда включена гиперпоточность. Может быть разумно повернуть off overthreading, когда несколько потоков зависят от одних и тех же ресурсов выполнения.

...

Полуостровное решение было введено в NetBurst и снова в Nehalem и Sandy Bridge с так называемым гиперпоточность. Процессор гиперпоточности имеет два логических процессора используя одно и то же ядро ​​выполнения. Преимущество этого ограничено, если два потока конкурировать за одни и те же ресурсы, но гиперпоточность может быть весьма выгодной, если производительность ограничена чем-то другим, таким как доступ к памяти.

...

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

PPPS: В книге оптимизации Intel перечислены ресурсы по обмену ресурсами во втором поколении HT: (страница 93, этот список предназначен для nehalem, но нет изменения этого списка в разделе Sandy)

Более глубокая буферизация и расширенные политики доступа к ресурсам/раздела:

  • - Реплицированный ресурс для работы с HT: состояние регистрации, переименованный стек возврата буфер, крупностраничный ITLB//комментарий от меня: есть два набора этого HW
  • - Разделенные ресурсы для работы HT: буферы загрузки, буферы хранения, повторный порядок буферов, ITLB с малыми страницами статически распределяются между двумя логическими процессоры.//комментарий от меня: есть один набор этого HW; он статически разделен между двумя HT-виртуальными ядрами в две половины
  • - Конкурентоспособный общий ресурс при работе HT: станция резервирования, кэш-иерархию, буферы заполнения, как DTLB0, так и STLB.//comment: Единый набор, но разделенный не пополам. CPU будет динамически перераспределять ресурсы.
  • - чередование во время работы HT: фронт-операции обычно чередуются между двумя логическими процессорами для обеспечения справедливости. //comment: есть один Frontend (декодер команд), поэтому потоки будут декодированы в порядке: 1, 2, 1, 2.
  • - HT неизвестные ресурсы: исполнительные блоки. //comment: есть настоящие hw-устройства, которые будут выполнять вычисления, обращения к памяти. Существует только один набор. Если один из потоков способен использовать множество исполнительных блоков, и если он ожидает небольшое количество памяти, он будет потреблять все блоки exec, а производительность второго потока будет низкой (но HT иногда переключается на второй поток. Как часто?). Если оба потока не оптимизированы по весу и/или ожидают память, исполнительные блоки будут разделены между двумя потоками.

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

Потенциал производительности благодаря технологии HT обусловлен:

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

Хотя инструкции, созданные из двух программ или двух потоков, выполняются одновременно и не обязательно в программном порядке в ядре выполнения и иерархии памяти, передний и задний концы содержат несколько точек выбора для выбора между инструкции от двух логических процессоров. Все точки выбора чередуются между два логических процессора, если только один логический процессор не может использовать конвейер сцена. В этом случае другой логический процессор полностью использует каждый цикл конвейера сцена. Причины, по которым логический процессор не может использовать этап конвейера, включают кеш-промахи, неверные предсказания ветвей и зависимости команд.

Ответ 3

Я удивлен, что никто не упомянул lscpu. Здесь приведен пример однопроцессорной системы с четырьмя физическими ядрами и гиперпотокой:

$ lscpu -p
# The following is the parsable format, which can be fed to other
# programs. Each different item in every column has an unique ID
# starting from zero.
# CPU,Core,Socket,Node,,L1d,L1i,L2,L3
0,0,0,0,,0,0,0,0
1,1,0,0,,1,1,1,0
2,2,0,0,,2,2,2,0
3,3,0,0,,3,3,3,0
4,0,0,0,,0,0,0,0
5,1,0,0,,1,1,1,0
6,2,0,0,,2,2,2,0
7,3,0,0,,3,3,3,0

Результат объясняет, как интерпретировать таблицу идентификаторов; логические идентификаторы CPU с одинаковым идентификатором ядра - это братья и сестры.

Ответ 4

Существует универсальный (Linux/Windows) и переносимый детектор топологии HW (ядра, HT, какафы, южные мосты и локальная сеть) - hwloc по проекту OpenMPI. Вы можете использовать его, потому что linux может использовать разные правила нумерации основных ячеек, и мы не можем знать, будет ли это правило четным/нечетным или y и y + 8 nubering.

Домашняя страница hwloc: http://www.open-mpi.org/projects/hwloc/

Страница загрузки: http://www.open-mpi.org/software/hwloc/v1.10/

Описание:

Программный пакет Portable Hardware Locality (hwloc) обеспечивает переносимую абстракцию (по всей ОС, версии, архитектуры и...) иерархической топологии современных архитектур, включая узлы памяти NUMA, сокеты, общие кэши, ядра и одновременную многопоточность, Он также собирает различные системные атрибуты, такие как информация о кеш-памяти и памяти, а также локальность устройств ввода-вывода, таких как сетевые интерфейсы, HCI InfiniBand или графические процессоры. Он в первую очередь направлен на то, чтобы помочь приложениям собирать информацию о современных вычислительных аппаратах, чтобы использовать их соответственно и эффективно.

Он имеет команду lstopo для получения hw-топологии в графической форме, например

 ubuntu$ sudo apt-get hwloc
 ubuntu$ lstopo

lstopo from hwloc (OpenMPI) - output example

или в текстовой форме:

 ubuntu$ sudo apt-get hwloc-nox
 ubuntu$ lstopo --of console

Мы можем видеть физические ядра как Core L#x, каждый из которых имеет два логических ядра PU L#y и PU L#y+8.

Machine (16GB)
  Socket L#0 + L3 L#0 (4096KB)
    L2 L#0 (1024KB) + L1 L#0 (16KB) + Core L#0
      PU L#0 (P#0)
      PU L#1 (P#8)
    L2 L#1 (1024KB) + L1 L#1 (16KB) + Core L#1
      PU L#2 (P#4)
      PU L#3 (P#12)
  Socket L#1 + L3 L#1 (4096KB)
    L2 L#2 (1024KB) + L1 L#2 (16KB) + Core L#2
      PU L#4 (P#1)
      PU L#5 (P#9)
    L2 L#3 (1024KB) + L1 L#3 (16KB) + Core L#3
      PU L#6 (P#5)
      PU L#7 (P#13)
  Socket L#2 + L3 L#2 (4096KB)
    L2 L#4 (1024KB) + L1 L#4 (16KB) + Core L#4
      PU L#8 (P#2)
      PU L#9 (P#10)
    L2 L#5 (1024KB) + L1 L#5 (16KB) + Core L#5
      PU L#10 (P#6)
      PU L#11 (P#14)
  Socket L#3 + L3 L#3 (4096KB)
    L2 L#6 (1024KB) + L1 L#6 (16KB) + Core L#6
      PU L#12 (P#3)
      PU L#13 (P#11)
    L2 L#7 (1024KB) + L1 L#7 (16KB) + Core L#7
      PU L#14 (P#7)
      PU L#15 (P#15)

Ответ 5

Я попытался проверить информацию, сравнив температуру ядра и нагрузку на ядро ​​HT.

enter image description here

Ответ 6

Простой способ получить гиперпоточность братьев и сестер процессорных ядер в bash:

cat $(find /sys/devices/system/cpu -regex ".*cpu[0-9]+/topology/thread_siblings_list") | sort -n | uniq