Отключить гиперпоточность из Linux (нет доступа к BIOS)
У меня есть система, на которой запущено приложение для финансовой торговли на удаленном объекте. У меня нет доступа к МОТ /DRAC, но мне нужно отключить гиперпоточность. Система работает на шестиъядерных процессорах Intel Westmere 3,33 ГГц X5680. Я могу перезагрузиться, но хочу убедиться, что система не поддерживает гиперпоточность из-за проблем с производительностью. Есть ли чистый способ сделать это изнутри Linux?
Изменить: noht
Директива, добавленная в командную строку загрузки ядра, не работает. То же самое для RHEL.
Смотрите: https://bugzilla.redhat.com/show_bug.cgi?id=440321
11 ответов
Мне пришлось ждать, пока я не смогу попасть в МОТ / Драк. Параметры загрузки ядра не работают в текущих дистрибутивах Linux.
Более новые ядра обеспечивают управление одновременной многопоточностью (SMT).
Вы можете проверить состояние SMT с помощью;
cat /sys/devices/system/cpu/smt/active
Изменить состояние с помощью
echo off > /sys/devices/system/cpu/smt/control
Варианты есть;
- на
- от
- forceoff
Мы проверили это с Linux Kernel 4.4.0
Вы можете сделать это во время выполнения, если хотите. Я нашел хорошее решение, описанное здесь: http://www.absolutelytech.com/2011/08/01/how-to-disable-cpu-cores-in-linux/
Шаг 1: Определите процессоры Linux, которые вы хотите отключить:
cat /proc/cpuinfo
Ищите процессоры, которые имеют одинаковый "идентификатор ядра", вы хотите отключить одну из каждой пары.
Шаг 2: Отключить процессоры с гиперпоточностью (в моем случае последние четыре из 8 "процессоров", которые видел Linux)
echo 0 > /sys/devices/system/cpu/cpu4/online
echo 0 > /sys/devices/system/cpu/cpu5/online
echo 0 > /sys/devices/system/cpu/cpu6/online
echo 0 > /sys/devices/system/cpu/cpu7/online
Вы можете настроить скрипт, который вы запускаете сразу после запуска системы.
Скрипт для отключения гиперпоточности при запуске машины...
Чтобы отключить гиперпоточность, я включаю скрипт на машине /etc/rc.local. Он не совсем чистый, но простой в установке, независимый от архитектуры процессора и должен работать на любом современном дистрибутиве Linux.
nano /etc/rc.local
# place this near the end before the "exit 0"
for CPU in /sys/devices/system/cpu/cpu[0-9]*; do
CPUID=$(basename $CPU)
echo "CPU: $CPUID";
if test -e $CPU/online; then
echo "1" > $CPU/online;
fi;
COREID="$(cat $CPU/topology/core_id)";
eval "COREENABLE=\"\${core${COREID}enable}\"";
if ${COREENABLE:-true}; then
echo "${CPU} core=${CORE} -> enable"
eval "core${COREID}enable='false'";
else
echo "$CPU core=${CORE} -> disable";
echo "0" > "$CPU/online";
fi;
done;
Как это работает?
Информация о ядре Linux и элементы управления доступны в виде файлов в каталоге / sys в современных дистрибутивах Linux. Например:
/ sys / devices / system / cpu / cpu3 содержит информацию о ядре и элементы управления для логического процессора 3.
cat / sys / devices / system / cpu / cpu3 / topology / core_id покажет номер ядра, которому принадлежит этот логический процессор.
echo "0"> / sys / devices / system / cpu / cpu3 / online позволяет отключить логический процессор 3.
Почему это работает?
Я не знаю точно, почему... но система стала более отзывчивой с отключенной гиперпоточностью (на моем ноутбуке i5 и массивных серверах Xeon с более чем 60 ядрами). Я предполагаю, что это связано с кэшем для каждого процессора, выделением памяти для каждого процессора, выделением планировщика процессора и сложными итерациями приоритетов процесса. Я думаю, что преимущества гиперпоточности перевешивают сложность создания планировщиков ЦП, которые знают, как их использовать.
Для меня проблема с гиперпоточностью такова: если я запущу столько потоков с интенсивным использованием процессора, сколько у меня логических ядер, у меня будут быстрые переключатели контекста для задач с интенсивным использованием процессора, но дорогие для фоновых задач, поскольку гиперпоточность полностью используется интенсивные задачи процессора. С другой стороны, если я запускаю столько потоков с интенсивным использованием процессора, сколько у меня физических ядер, у меня не будет переключений контекста на эти задачи и быстрых переключений контекста для фоновых задач. Вроде бы хорошо, но фоновые задачи найдут свободные логические процессоры и будут работать почти сразу. Как будто они в реальном времени (неплохо -20).
В первом сценарии гиперпоточность - это пустяки, фоновые задачи будут использовать дорогие переключатели контекста, потому что я увеличил гиперпоточность при обычной обработке. Второе недопустимо, поскольку до 50% мощности моего процессора отдается приоритет фоновым задачам.
"Интенсивная загрузка процессора", о которой я говорю, - это интеллектуальный анализ данных и серверы авторизации (моя работа). Блендер рендеринг в дешевых компьютерах и кластерах (для эскиза моего будущего дома).
Кроме того, это догадки.
У меня такое впечатление, что лучше, но может и нет.
Вы можете использовать "thread_siblings_list" для каждого ядра, чтобы отключить второе ядро в паре HT.
Следующий командный конвейер является хакерским, не оптимизированным и сделан таким образом, чтобы облегчить понимание.
cat /sys/devices/system/cpu/cpu*/topology/thread_siblings_list | \
awk -F, '{print $2}' | \
sort -n | \
uniq | \
( while read X ; do echo $X ; echo 0 > /sys/devices/system/cpu/cpu$X/online ; done )
Итак, возьмите все списки дочерних элементов потока, извлеките второй ЦП для каждой пары, получите уникальный список и затем отключите их.
Имеет ли это смысл?
если я выполнил команду "cat /proc/cpuinfo" после запуска выше, число ядер уменьшается вдвое.
Для действительно старых ядер (Linux 2.6.9 или около того) добавьте параметр noht к ядру при загрузке.
Эта опция командной строки ядра была удалена, по крайней мере, с Linux 2.6.18.
С http://www.faqs.org/docs/Linux-HOWTO/BootPrompt-HOWTO.html:
The `noht' Argument
This will disable hyper-threading on intel processors that have this feature.
Если вы используете lilo, отредактируйте ваш файл /etc/lilo.conf (и запустите lilo впоследствии) или, если вы используете grub, отредактируйте ваш файл /boot/grub/menu.lst.
Отключить SMT / HT во время загрузки с помощью параметра командной строки ядра nosmt
:
nosmt [KNL,S390] Disable symmetric multithreading (SMT).
Equivalent to smt=1.
[KNL,x86] Disable symmetric multithreading (SMT).
nosmt=force: Force disable SMT, cannot be undone
via the sysfs control file.
Отключить SMT / HT во время выполнения с помощью управления SMT:
/sys/devices/system/cpu/smt/control:
This file allows to read out the SMT control state and provides the
ability to disable or (re)enable SMT. The possible states are:
============== ===================================================
on SMT is supported by the CPU and enabled. All
logical CPUs can be onlined and offlined without
restrictions.
off SMT is supported by the CPU and disabled. Only
the so called primary SMT threads can be onlined
and offlined without restrictions. An attempt to
online a non-primary sibling is rejected
forceoff Same as 'off' but the state cannot be controlled.
Attempts to write to the control file are rejected.
notsupported The processor does not support SMT. It's therefore
not affected by the SMT implications of L1TF.
Attempts to write to the control file are rejected.
============== ===================================================
The possible states which can be written into this file to control SMT
state are:
- on
- off
- forceoff
Ответ Лукаса хорош, но на самом деле не работает для отключения HT, потому что идентификатор ядра не может служить для идентификации братьев и сестер HT. Этот скрипт работает вместо:
#!/bin/bash
for CPU in /sys/devices/system/cpu/cpu[0-9]*; do
CPUID=`basename $CPU | cut -b4-`
echo -en "CPU: $CPUID\t"
[ -e $CPU/online ] && echo "1" > $CPU/online
THREAD1=`cat $CPU/topology/thread_siblings_list | cut -f1 -d,`
if [ $CPUID = $THREAD1 ]; then
echo "-> enable"
[ -e $CPU/online ] && echo "1" > $CPU/online
else
echo "-> disable"
echo "0" > $CPU/online
fi
done
Отключить HT:
echo 0 |sudo tee /sys/devices/system/cpu/cpu{4..7}/online
Включить HT:
echo 1 |sudo tee /sys/devices/system/cpu/cpu{4..7}/online
Примечание. Это на самом деле не отключает HyperThreading, но отключает "поддельные" ядра, получая почти тот же результат.
В пакете libsmbios-bin (Debian, Ubuntu и т. Д.) У вас есть исполняемые файлы isCmosTokenActive и activCmosToken. Вместе со списком токенов вы можете попробовать что-то вроде этого:
# isCmosTokenActive 0x00d1 # CPU_Hyperthreading_Enable
[...] Type 0x00d1 Location 0x46 AND(fe) OR(0) BITFIELD: 1
# isCmosTokenActive 0x00d2 # CPU_Hyperthreading_Disable
[....] Type 0x00d2 Location 0x46 AND(fe) OR(1) BITFIELD: 0
Затем активируйте токен CPU_Hyperthreading_Disable:
# activateCmosToken 0x00d2 # CPU_Hyperthreading_Disable
[...] Type 0x00d2 Location 0x46 AND(fe) OR(1) BITFIELD: 1
Убедитесь, что:
# isCmosTokenActive 0x00d1 # CPU_Hyperthreading_Enable
[...] Type 0x00d1 Location 0x46 AND(fe) OR(0) BITFIELD: 0
# isCmosTokenActive 0x00d2 # CPU_Hyperthreading_Disable
[...] Type 0x00d2 Location 0x46 AND(fe) OR(1) BITFIELD: 1
Теперь большой вопрос заключается в том, нужна ли вам просто перезагрузка, чтобы это вступило в силу, или требуется полный цикл питания. Попробуйте и посмотрите, как это происходит!
Основываясь на информации, предоставленной Полом М здесь, я бы "написал" это так:
fgrep , /sys/devices/system/cpu/cpu*/topology/thread_siblings_list |
cut -d, -f2 | sort -u |
sudo xargs -rI, sh -c 'echo 0 > /sys/devices/system/cpu/cpu,/online'
Конечно, он не отключает гиперпоточность в том же смысле, что и работа с BIOS, в основном он говорит только планировщику задач ядра не использовать некоторые ядра, потому что мы знаем, что они фальшивые.
Программное обеспечение, которое сделало предположение на основе предыдущего состояния /proc
или же /sys
Подсистема все еще может работать неоптимально или даже не работать из-за этого изменения времени выполнения, поэтому может потребоваться ее перезапуск. Например, я заметил irqbalance
был склонен к провалу в этих обстоятельствах.
Старая тема, но была причина попробовать этот эксперимент. Во-первых, я вовсе не уверен, что отключение (слегка фальшивых) процессоров во время выполнения действительно эквивалентно отключению Hyperthreading при загрузке. Тем не менее, я увидел небольшое повышение производительности в нашем приложении. (Но недостаточно, чтобы сохранить.)
Использовал значение thread_siblings (общее для многопоточных процессоров) в качестве ключа для включения / выключения:
for i in /sys/devices/system/cpu/cpu[0-9]*
do echo "$(cat $i/topology/thread_siblings) $i"
done |
awk '{v = (a[$1] ? 0 : 1); a[$1] = 1; print "echo " v " > " $2 "/online"}' |
sudo sh
Попробуйте команду без окончательного sudo sh, чтобы проверить правильность.