Стресс тест процессора в Linux

Прогнал я тест Linpack и задумался: а не пора ли мне поменять термопасту на своём ноутбуке?

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


Стресстест процессора в терминале Linux

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

Начал я с sysbench:

sudo apt install sysbench

sysbench --num-threads=4 --test=cpu --cpu-max-prime=100000 run

где:

  • --num-threads=4 - это количество потоков, у меня двухъядерный четырёхпотоковый Intel® Core™ i7-640M, поэтому 4;
  • --cpu-max-prime=100000 - это максимальное количество выполненных операций, я выставил в 100000, т.к. по умолчанию - 10000, слишком быстро завершают тест.

Потом я перешёл на Linpack. Так как процессор у меня от Intel и я имею некоторую долю лени (лень - двигатель прогресса), то я взял, скачал и распаковал готовый Intel-овский Linpack, предварительно создав в домашнем каталоге директорию linpack:

mkdir ./linpack
cd ./linpack
wget http://registrationcenter-download.intel.com/akdlm/irc_nas/9752/l_mklb_p_2018.3.011.tgz
tar -xvzf ./l_mklb_p_2018.3.011.tgz

Для AMD процессоров такой вариант я бы не стал пробовать, так как компилятор от Intel вставляет закладки, проверяющие процессор и если он не Intel...ну, подумаешь сотню-другую лишних инструкций процессор выполнит и заведомо проиграет в производительности. Для AMD лучше собрать Linpack из исходников, например, из этих. В данной статье сборку из исходников рассматривать не буду - читайте README в source code.

Вернёмся к Intel-овскому Linpack-у. Там много чего лишнего и мне не нужного, а то, что нужно рассмотрю относительно версии 2018.3.011. Сразу же перейду в нужную директорию, чтоб потом не набирать длинные команды:

cd ./l_mklb_p_2018.3.011/benchmarks_2018/linux/mkl/benchmarks/linpack

Так как по умолчанию Intel-овский Linpack заточен под тестирование серверных Xeon-ов, создадим свой файл, который будет использоваться в качестве входных опций - просто уменьшим количество тестов, иначе устанем "пару-тройку дней" ждать завершения теста. У меня Linux Mint LMDE 3, поэтому я использую текстовый редактор xed, да и нравится он мне бОльшим функционалом, особенно, когда из-под root-а его запускать - он цвет на красный меняет. И так, создаём в этой же директории, в которую перешли, файл, например, my_test:

xed ./my_test

И в созданный файл копируем следующее содержимое:

Shared-memory version of Intel(R) Distribution for LINPACK* Benchmark. *Other names and brands may be claimed as the property of others.
Sample data file lininput_xeon64.
5 # number of tests
1000 2000 5000 10000 20000 # problem sizes
1000 2000 5008 10000 20000 # leading dimensions
4 2 2 2 1 # times to run a test
4 4 4 4 4 # alignment values (in KBytes)

Ну, и собственно запуск Linpack с созданным файлом:

./xlinpack_xeon64 -i ./my_test

Или:

./xlinpack_xeon64 ./my_test

Можно ещё заюзать stress-ng или stress, но поставленной мной задачи это всё-равно не решает. Вывода температуры, частот и времени от начала старта эти утилиты мне не показывают.

Температуру может показать sensors - подробнее про установку этой утилиты здесь. И эта утилита понадобится в дальнейшем рассмотрении моего вопроса. Линукс - велик и могуч: одна и та же задача может решаться по-разному. За Си мне лень было браться и я написал недостающую мне часть на BASH, ибо строк получилось не так уж и много. Без установленной sensors мой скрипт работать не будет. Фиксацию троттлинга естесственно не стал писать - его и так будет видно по сбросу частоты и температуре. Вот сам скрипт:

#!/bin/bash
out=0 # переменная контроля за тестовым процессом
pid_test='tty' # PID тестового процесса (сделан существующей директорией, чтоб запускать без аргументов)
cpus_num=$(cat /proc/cpuinfo | grep -ci 'processor') # количество процессоров/ядер/потоков
echo -en "\033[?25l" 1>&2 # скрыть курсор
echo -en "\033[1m" 1>&2 # жирный шрифт
cat /proc/cpuinfo | sed '/model name/!d;s/^[^:][^:]*: //g' | sort -u # вывод модели процессора
echo -en "\033[0m" 1>&2 # сброс параметров цвета
trap out=1 SIGINT # инициализация выхода по ctrl+c
trap out=2 SIGABRT # инициализация выхода по незапуску теста
for ((i=0; i<$cpus_num; i++)) # предварительная инициализация массива переменных
do
cpu_crit_temp[$i]=$(sensors | sed '/Core '"$i"'/!d;s/.*crit = +\(.*\)[.][0-9]°C).*/\1/')
if [ -n "${cpu_crit_temp[i]}" ]
then
let cpu_red_temp[i]=cpu_crit_temp[i]-10
let cpu_yel_temp[i]=cpu_crit_temp[i]-30
cpu_min_temp[$i]=1000
cpu_max_temp[$i]=0
fi
done
start_time=$(cat /proc/uptime | sed 's/[.][0-9][0-9] .*$//') # время запуска
if [ -n "$1" ]
then
script_pid="$$"
(if ! $@ > "$0_out" 2>&1 # запуск тестового файла
then
kill -s SIGABRT $script_pid # послать сигнал основному скрипту об отказе запуска
fi 2>/dev/null)&
pid_test="$!" # PID тестового процесса
fi
while (true) # контроль температуры
do
for ((i=0; i<$cpus_num; i++))
do
cpu_freq[$i]=$(cat /sys/devices/system/cpu/cpu${i}/cpufreq/scaling_cur_freq | sed 's/...$//')
cpu_temp[$i]=$(sensors | sed '/Core '"$i"'/!d;s/.*+\(.*\)[.][0-9]°C[ \t]*(.*/\1/')
if [ -n "${cpu_temp[i]}" ]
then
(( ${cpu_temp[i]} < ${cpu_min_temp[i]} )) && cpu_min_temp[$i]=${cpu_temp[i]}
if (( ${cpu_temp[i]} > ${cpu_max_temp[i]} ))
then
cpu_max_temp[$i]=${cpu_temp[i]}
time_max[$i]=$(cat /proc/uptime | sed 's/[.][0-9][0-9] .*$//')
let time_max[i]=time_max[i]-start_time
fi
if (( ${cpu_temp[i]} > ${cpu_red_temp[i]} ))
then
echo -en "cpu${i}:\t"
echo -en "\033[1m" 1>&2 # жирный шрифт
echo -n "${cpu_freq[i]} "
echo -en "\033[0m" 1>&2 # сброс параметров цвета
echo -en "MHz \t"
echo -en "\033[31;1m" 1>&2 # жирный красный шрифт
echo -n "${cpu_temp[i]}"
echo -en "\033[0m" 1>&2 # сброс параметров цвета
echo -en "°C \t(min: ${cpu_min_temp[i]}°C; max: "
echo -en "\033[31;1m" 1>&2 # жирный красный шрифт
echo -n "${cpu_max_temp[i]}"
echo -en "\033[0m" 1>&2 # сброс параметров цвета
echo "°C/${time_max[i]}sec) "
elif (( ${cpu_temp[i]} > ${cpu_yel_temp[i]} ))
then
echo -en "cpu${i}:\t"
echo -en "\033[1m" 1>&2 # жирный шрифт
echo -n "${cpu_freq[i]} "
echo -en "\033[0m" 1>&2 # сброс параметров цвета
echo -en "MHz \t"
echo -en "\033[33;1m" 1>&2 # жирный жёлтый шрифт
echo -n "${cpu_temp[i]}"
echo -en "\033[0m" 1>&2 # сброс параметров цвета
echo -en "°C \t(min: ${cpu_min_temp[i]}°C; max: "
echo -en "\033[31;1m" 1>&2 # жирный красный шрифт
echo -n "${cpu_max_temp[i]}"
echo -en "\033[0m" 1>&2 # сброс параметров цвета
echo "°C/${time_max[i]}sec) "
else
echo -en "cpu${i}:\t"
echo -en "\033[1m" 1>&2 # жирный шрифт
echo -n "${cpu_freq[i]} "
echo -en "\033[0m" 1>&2 # сброс параметров цвета
echo -en "MHz \t"
echo -en "\033[32;1m" 1>&2 # жирный зелёный шрифт
echo -n "${cpu_temp[i]}"
echo -en "\033[0m" 1>&2 # сброс параметров цвета
echo -en "°C \t(min: ${cpu_min_temp[i]}°C; max: "
echo -en "\033[31;1m" 1>&2 # жирный красный шрифт
echo -n "${cpu_max_temp[i]}"
echo -en "\033[0m" 1>&2 # сброс параметров цвета
echo "°C/${time_max[i]}sec) "
fi
else
echo -en "cpu${i}:\t"
echo -en "\033[1m" 1>&2 # жирный шрифт
echo -n "${cpu_freq[i]} "
echo -en "\033[0m" 1>&2 # сброс параметров цвета
echo -e "MHz \t "
fi
done
time=$(cat /proc/uptime | sed 's/[.][0-9][0-9] .*$//')
let time=time-start_time
echo -en "Time:\t$time sec. "
[ ! -d "/proc/${pid_test}" ] && break # выход по окончании теста (лучший способ контроля по comm и cmdline, но...лень)
[ "$out" != '0' ] && break # выход при ошибке теста
echo -en "\033[${i}A\r" 1>&2 # перенос курсора вверх на $i строк и на начало строки
sleep 0.1 # пауза, чтоб вывод частот сильно не скакал
done
echo ''
echo -en "\033[?25h" 1>&2 # включение курсора
if [[ "$out" == '0' && -n "$1" ]]
then
cat "$0_out" | sed '/^$/d;/Sample data/d;/CPU frequency/d;/Parameters are set/,/Data alignment value/d'
rm -fR "$0_out"
exit 0
elif [[ "$out" == '1' && -n "$1" ]]
then
kill -9 "$pid_test" 1>/dev/null 2>/dev/null
cat "$0_out" | sed '/^$/d;/Sample data/d;/CPU frequency/d;/Parameters are set/,/Data alignment value/d'
rm -fR "$0_out"
exit 1
elif [ "$out" == '1' ]
then exit 1
elif [ "$out" == '2' ]
then
echo -en "\033[31;1m" 1>&2
echo 'Error arg!'
echo -en "\033[0m" 1>&2
exit 2
fi
exit 0

Сильно не ругайте за скидывание управляющих символов в stderr (1>&2), но это дело привычки, если вдруг потом вывод скрипта в файл отправлять, а там все эти ESC-апе последовательности точно не нужны, вот так и будет терминал цветным, а файл чистым. Что-то я отвлёкся.

Я создал файл chk в директории с linpack-ом и записал скрипт в него, Вы можете сделать тоже самое, за исключением xed, если у Вас его нет:

xed ./chk

И собственно то, ради чего всё затевалось - тест Linpack cо скриптом:

./chk ./xlinpack_xeon64 -i ./my_test

Да, я вижу, одно ядро нагрелось до критического TDP в 105°C за 86 секунд, но это мне ни о чём не говорит, а вот то, что с 50°C до 80°C процессор нагревается за 2 секунды - это уже показатель: термопасту точно пора менять - два года не менял, а вот с системой охлаждения останется вопрос, который проявят тесты после замены термопасты и термопроводящих прокладок на моём ноутбуке.

Почему именно 80°C я взял за отправную точку? Да просто потому, что именно эта температура заложена в BIOS, как температуры начала скидывания частот, да ещё и начало включения кулера выставлена в 55°C в угоду энергосбережению, но BIOS - InsydeH20, да ещё и с проверкой своей хэш-суммы и белым списком девайсов - та ещё головная боль...будет программатор - займусь им вплотную.

Скрипт писал на скорую руку и с ориентиром на Linpack, но он так же свободно работает и с другими консольными утилитами. Вот запуск с вышеизложенным sysbench:

./chk sysbench --num-threads=4 --test=cpu --cpu-max-prime=100000 run

Как видно из скриншота sysbench не даёт полную нагрузку на процессор, в отличии от Linpack-а...

Вот запуск с утилитой stress (подробнее про stress - здесь):

./chk stress --cpu 16

Естественно выход/окончание теста с утилитой stress осуществляется вручную по CTRL+C, отсюда и Error: 1 выведенная моей переменной PS1 из-за подобной реализации выхода из скрипта через exit 1.

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

./chk

В любом случае выход из скрипта осуществляется автоматически, по окончании теста или можно выйти, нажав CTRL + C:

В общем: поставленную для себя задачу я решил и даже лучше - появилась целая надстройка над тестовыми утилитами. Осталось ноутбук разобрать и поменять таки термопасту с прокладками: как вспомню - аж страшно становится...

2 комментария

  1. Стас Январь 9, 2019 Ответить
    • Cepera Январь 14, 2019 Ответить

Ответить

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: