Управление вентилятором Radeon RX-6xx0: различия между версиями
Дым (обсуждение | вклад) |
Дым (обсуждение | вклад) |
||
Строка 23: | Строка 23: | ||
} | } | ||
## User variables | ## User variables ########################################### | ||
card=0 | card=0 # Vega rather has number 1 | ||
rate=5 | rate=5 # check frequency | ||
step=5 # min to max divider | |||
within=2 # temperature borders and pwm diff tolerance | |||
min_tmp=40 # no need cooling lower | |||
## System variables | ## System variables ######################################### | ||
dev_dir=/sys/class/drm/card$card/device | dev_dir=/sys/class/drm/card$card/device | ||
sys_dir=`ls -d $dev_dir/hwmon/*` | sys_dir=`ls -d $dev_dir/hwmon/*` | ||
# | sys_lvl=${dev_dir}/power_dpm_force_performance_level | ||
sys_clk=${dev_dir}/pp_od_clk_voltage | |||
sys_tmp=${sys_dir}/temp2_input # 1:edge, 2:junction, 3:memory | |||
sys_pwm=${sys_dir}/pwm1 | sys_pwm=${sys_dir}/pwm1 | ||
sys_fan=${sys_pwm}_enable | sys_fan=${sys_pwm}_enable | ||
max_tmp=$[`cat $sys_dir/temp*_crit | sort -V | head -1`/1000] | |||
max_pwm=`cat ${sys_pwm}_max` | |||
min_pwm=`cat ${sys_pwm}_min` | min_pwm=`cat ${sys_pwm}_min` | ||
gap_pwm=$[(max_pwm-min_pwm)/step] | |||
gap_tmp=$[(max_tmp-min_tmp)/step] | |||
reset(){ # Sudden | reset(){ # Sudden break. | ||
printf "Exiting and | printf "Exiting and s" | ||
setmode auto | |||
exit 0 | exit 0 | ||
} | } | ||
setmode(){ # Change mode and gpu & mem frequency. | |||
case $1 in | case $1 in | ||
auto) mhz=(2650 1000) # default frequencies | |||
mode=2;; | |||
manual) mhz=(`awk '/^(M|S)/{gsub("Mhz","");print $3}' $sys_clk`) | |||
mode=1;; | |||
*) mode=0 # max | *) mode=0 # max | ||
esac | esac | ||
echo " to '$1'." | echo "etting clock & fan mode to '$1'." | ||
echo $mode >$sys_fan | echo $1 >$sys_lvl | ||
echo $mode >$sys_fan | |||
echo s 1 ${mhz[0]} >$sys_clk | |||
echo m 1 ${mhz[1]} >$sys_clk | |||
} | } | ||
Строка 72: | Строка 69: | ||
cur_tmp=$[`cat $sys_tmp`/1000] | cur_tmp=$[`cat $sys_tmp`/1000] | ||
[[ `cat $sys_fan` -eq 1 ]] || { | [[ `cat $sys_fan` -eq 1 ]] || { | ||
printf " | printf "S" | ||
setmode manual | |||
} | } | ||
if [[ $cur_tmp -gt $max_tmp ]]; then | if [[ $cur_tmp -gt $max_tmp ]]; then | ||
echo "$cur_tmp°C | echo "$cur_tmp°C exceeds critical, setting PWM to $max_pwm for max speed." | ||
new_pwm=$max_pwm | new_pwm=$max_pwm | ||
elif [[ $cur_tmp -le $min_tmp ]]; then | elif [[ $cur_tmp -le $min_tmp ]]; then | ||
new_pwm=$min_pwm | new_pwm=$min_pwm | ||
else | else | ||
for i in $ | for i in `seq 0 $[step-2]`; do | ||
[[ $cur_tmp -ge $[min_tmp+gap_tmp*i] ]] && | [[ $cur_tmp -ge $[min_tmp+gap_tmp*i] ]] && | ||
[[ $cur_tmp -le $[min_tmp+gap_tmp*(i+1)] ]] && { | [[ $cur_tmp -le $[min_tmp+gap_tmp*(i+1)] ]] && { | ||
new_pwm=$[min_pwm+ | new_pwm=$[min_pwm+gap_pwm*(i+1)] | ||
break | break | ||
} | } | ||
Строка 92: | Строка 89: | ||
[[ $cur_pwm -ge $[new_pwm-within] ]] && | [[ $cur_pwm -ge $[new_pwm-within] ]] && | ||
[[ $cur_pwm -le $[new_pwm+within] ]] && | [[ $cur_pwm -le $[new_pwm+within] ]] && | ||
echo "." || { | echo "." || { # Change PWM if differ. | ||
printf ", changing to %3d.\n" $new_pwm | for i in `seq 0 $[step-2]`; do | ||
[[ $cur_tmp -ge $[min_tmp+gap_tmp*i-within] ]] && | |||
[[ $cur_tmp -le $[min_tmp+gap_tmp*i+within] ]] && { | |||
echo "." | |||
break | |||
} | |||
done || { | |||
printf ", changing to %3d.\n" $new_pwm | |||
echo $new_pwm >$sys_pwm | |||
} | |||
} | } | ||
} | } | ||
Строка 112: | Строка 117: | ||
#:*температуру '''min_tmp''', ниже которой мослать вентилятором бессмысленно (с завода вентилятор не алё градусов до полусотни минимум, что видно в логе при перезапуске скрипта — см. в [[Управление_вентилятором_Radeon_RX-6xx0#Перезапуск_скрипта_в_жару|примере]] ниже); | #:*температуру '''min_tmp''', ниже которой мослать вентилятором бессмысленно (с завода вентилятор не алё градусов до полусотни минимум, что видно в логе при перезапуске скрипта — см. в [[Управление_вентилятором_Radeon_RX-6xx0#Перезапуск_скрипта_в_жару|примере]] ниже); | ||
#:*шаг '''gap_tmp''' между диапазонами температур; | #:*шаг '''gap_tmp''' между диапазонами температур; | ||
#:* | #:*шаг '''gap_pwm''' между значениями ШИМа в температурных диапазонах (и это не об/мин, как можно подумать, а нечто вроде процента от максимума — но не из 100, а из 255). | ||
#:*допустимый разброс ('''whithin''') присваиваемого значения ШИМ с текущим, | #:*допустимый разброс ('''whithin''') присваиваемого значения ШИМ с текущим, порою отличающимся от заданного, а ещё перехлёст температурных диапазонов, дабы вентилятор не дёргался по одному градусу, внося сумятицу в ума и сердца; | ||
# | #Скрипт сделал а-ля «резидентным» (цикл '''while''') — запускать по таймеру не стал, дабы между его запусками не оставлять видюху в ручном режиме без управления (см. функцию '''setmode'''). | ||
==Запускающий юнит== | ==Запускающий юнит== |
Версия от 18:21, 26 мая 2022
Введение
Столкнулся с проблемой перегрева видюхи RX-6700XT на игровых нагрузках — и не только её самой, поскольку она ведь и вокруг себя изрядно греет.
- Процессор прямо над нею кипятится — мéста между видюхой, крышкой и стенками отнюдь не завались.
- М2-накопитель посреди видюхи и проца тоже знатно подгорает — хоть и с радиатором, и от проц-кулера на него дует… горячим.
- Дополнительным винчестерам в корзине, вставленной в пространство 5-дюймовых отсеков, жарко и душно.
- Да и тем, что в нижних 3,5-дюймовых, ни разу не уютно.
До некоторой степени спасает вариант поставить (скорей, положить) перед открытой крышкой системника большой комнатный вентилятор — для всего, кроме самой видюхи: она ж к нему краем, и толку ноль. А заводская авторегулировка видюхиного ШИМа как-то не особо способствует её охлаждению даже зимой, о жаре за бортом вовсе молчу.
Реализация
Пошарив по просторам, нарыл массу графических «мониторилок» — но ни одной «крутилки» именно для АМД, хотя для ненаВидии — завались (один лишь «позеленевший от зависти» чего стóит). И это невзирая на то, что всё нужное доступно прям в системе, без нужды ковыряться в проприетарщине… Странное дело.
Однако наваянного по теме для командной строки хватает на разных языках от рубина до питона, но к чему плодить сущности, если всё можно сделать перманентно доступным башем?
Вдохновлённый этой мыслью, проникся решением amdgpu-fancontrol
и выстругал на скорую руку собственный сильно упрощённый вариант, для которого понадобится создать всего пару файлов.
Скрипт запуска
/usr/local/sbin/amdgpufan
:
#!/bin/bash
# Check root privileges at first.
[ $UID -eq 0 ] || {
echo "Writing to /sys requires root privileges."
exit 1
}
## User variables ###########################################
card=0 # Vega rather has number 1
rate=5 # check frequency
step=5 # min to max divider
within=2 # temperature borders and pwm diff tolerance
min_tmp=40 # no need cooling lower
## System variables #########################################
dev_dir=/sys/class/drm/card$card/device
sys_dir=`ls -d $dev_dir/hwmon/*`
sys_lvl=${dev_dir}/power_dpm_force_performance_level
sys_clk=${dev_dir}/pp_od_clk_voltage
sys_tmp=${sys_dir}/temp2_input # 1:edge, 2:junction, 3:memory
sys_pwm=${sys_dir}/pwm1
sys_fan=${sys_pwm}_enable
max_tmp=$[`cat $sys_dir/temp*_crit | sort -V | head -1`/1000]
max_pwm=`cat ${sys_pwm}_max`
min_pwm=`cat ${sys_pwm}_min`
gap_pwm=$[(max_pwm-min_pwm)/step]
gap_tmp=$[(max_tmp-min_tmp)/step]
reset(){ # Sudden break.
printf "Exiting and s"
setmode auto
exit 0
}
setmode(){ # Change mode and gpu & mem frequency.
case $1 in
auto) mhz=(2650 1000) # default frequencies
mode=2;;
manual) mhz=(`awk '/^(M|S)/{gsub("Mhz","");print $3}' $sys_clk`)
mode=1;;
*) mode=0 # max
esac
echo "etting clock & fan mode to '$1'."
echo $1 >$sys_lvl
echo $mode >$sys_fan
echo s 1 ${mhz[0]} >$sys_clk
echo m 1 ${mhz[1]} >$sys_clk
}
main(){ # Whole magic.
cur_pwm=`cat $sys_pwm`
cur_tmp=$[`cat $sys_tmp`/1000]
[[ `cat $sys_fan` -eq 1 ]] || {
printf "S"
setmode manual
}
if [[ $cur_tmp -gt $max_tmp ]]; then
echo "$cur_tmp°C exceeds critical, setting PWM to $max_pwm for max speed."
new_pwm=$max_pwm
elif [[ $cur_tmp -le $min_tmp ]]; then
new_pwm=$min_pwm
else
for i in `seq 0 $[step-2]`; do
[[ $cur_tmp -ge $[min_tmp+gap_tmp*i] ]] &&
[[ $cur_tmp -le $[min_tmp+gap_tmp*(i+1)] ]] && {
new_pwm=$[min_pwm+gap_pwm*(i+1)]
break
}
done
fi
printf "%3d°C @%3d PWM" $cur_tmp $cur_pwm
[[ $cur_pwm -ge $[new_pwm-within] ]] &&
[[ $cur_pwm -le $[new_pwm+within] ]] &&
echo "." || { # Change PWM if differ.
for i in `seq 0 $[step-2]`; do
[[ $cur_tmp -ge $[min_tmp+gap_tmp*i-within] ]] &&
[[ $cur_tmp -le $[min_tmp+gap_tmp*i+within] ]] && {
echo "."
break
}
done || {
printf ", changing to %3d.\n" $new_pwm
echo $new_pwm >$sys_pwm
}
}
}
trap "reset" SIGINT SIGTERM # Handle signals.
while :; do # Go on!
main
sleep ${rate}s
done
Пояснения
- В системных переменных отслеживаю показания датчика температуры перехода, самого горячего элемента из трёх —
junction
(sys_tmp), но в качестве предельной температуры (max_tmp) выбираю минимальную из критических (в моём случае это датчик памяти). - Пользовательскими переменными задаю:
- № видюхи (судя по статьям от спецов, при наличии встройки оная будет пронумерована единичкой);
- частоту опроса температуры rate со сменой значения в ШИМ-контроллере при необходимости (5 секунд хватает и чтоб не дать перегреться, и чтоб не надоело листать портянку журнала);
- температуру min_tmp, ниже которой мослать вентилятором бессмысленно (с завода вентилятор не алё градусов до полусотни минимум, что видно в логе при перезапуске скрипта — см. в примере ниже);
- шаг gap_tmp между диапазонами температур;
- шаг gap_pwm между значениями ШИМа в температурных диапазонах (и это не об/мин, как можно подумать, а нечто вроде процента от максимума — но не из 100, а из 255).
- допустимый разброс (whithin) присваиваемого значения ШИМ с текущим, порою отличающимся от заданного, а ещё перехлёст температурных диапазонов, дабы вентилятор не дёргался по одному градусу, внося сумятицу в ума и сердца;
- Скрипт сделал а-ля «резидентным» (цикл while) — запускать по таймеру не стал, дабы между его запусками не оставлять видюху в ручном режиме без управления (см. функцию setmode).
Запускающий юнит
/lib/systemd/system/amdgpufan.service
:
[Unit]
Description = AMD GPU fan control
[Service]
ExecStart = /usr/local/sbin/amdgpufan
Restart = on-failure
RestartSec = 5
[Install]
WantedBy = default.target
Как включать юниты, все давно знают. :)
Пример работы
(дату-время и имя-пид процесса убрал для удобочитаемости)
Вечер — веб-сёрфинг, редактирование и пр.
Колебания в пределах 50°C при ШИМ 69.
Запуск игры
60°C @ 69 PWM, changing to 90. 59°C @ 89 PWM, changing to 70. 60°C @ 69 PWM, changing to 90. 57°C @ 89 PWM, changing to 70. 54°C @ 69 PWM. 59°C @ 69 PWM. 62°C @ 69 PWM, changing to 90. 77°C @ 89 PWM.
Активная фаза игры
82°C @ 89 PWM, changing to 140. 62°C @138 PWM, changing to 90. 59°C @ 89 PWM, changing to 70. 62°C @ 69 PWM, changing to 90. 60°C @ 89 PWM. … 61°C @ 89 PWM. 62°C @ 89 PWM. 58°C @ 89 PWM, changing to 70. 60°C @ 69 PWM, changing to 90. 75°C @ 89 PWM.
Игра завершена
Плавное падение температуры:
53°C @ 89 PWM, changing to 70. 52°C @ 69 PWM. 40°C @ 69 PWM. 39°C @ 69 PWM, changing to 0. 40°C @ 0 PWM, changing to 70. 39°C @ 69 PWM, changing to 0. 39°C @ 0 PWM.
Ночью колебания 35-38°C с отключёнными вентиляторами видюхи.
Утро — вход в систему
Веб-сёрфинг, редактирование и пр.:
40°C @ 0 PWM, changing to 70. 41°C @ 69 PWM.
Далее — колебания 42-55°C при ШИМ 69.
Перезапуск скрипта в жару
По нулевому значению ШИМ на старте видно, что автонастройка не включает вентиляторы как минимум до 50°C:
мая 25 18:01:19 comp.ill amdgpufan[2544596]: 49°C @ 69 PWM. мая 25 18:01:21 comp.ill systemd[1]: Stopping AMD GPU fan control... мая 25 18:01:21 comp.ill amdgpufan[2544596]: Завершено мая 25 18:01:21 comp.ill amdgpufan[2544596]: Exiting and setting fan mode to 'auto'. мая 25 18:01:21 comp.ill systemd[1]: amdgpufan.service: Deactivated successfully. мая 25 18:01:21 comp.ill systemd[1]: Stopped AMD GPU fan control. мая 25 18:01:21 comp.ill systemd[1]: amdgpufan.service: Consumed 1.034s CPU time. мая 25 18:01:21 comp.ill systemd[1]: Started AMD GPU fan control. мая 25 18:01:21 comp.ill amdgpufan[2558019]: Wrong fan mode, setting to 'manual'. мая 25 18:01:21 comp.ill amdgpufan[2558019]: 49°C @ 0 PWM, changing to 70. мая 25 18:01:26 comp.ill amdgpufan[2558019]: 49°C @ 69 PWM.
Игра по жаре
92°C @ 87 PWM, changing to 140.
Далее колебания на 90+°C при ШИМ 138.
Выводы
На данный момент ночью, по прохладе, большой внешний вентилятор уже точно не нужен: игрушки на ультрах в высоком разрешении прогревают самый горячий компонент видюхи не выше 96 градусов, тогда как прежде и с вентилятором за сотку вылезало. Вечером в пределах +30 на улице тоже обошёлся без вентилятора. Как оно в дневную жару, опробовать пока не довелось, но по результатам отчитаюсь.
Когда не ломанная / не чиненная железяка работает не так, как ожидается, порой на помощь спешат чип и… программные средства. Пусть без рюшечек и фантиков, зато задача решена на системном уровне. Ну, и есть надежда, что дружелюбного софта тоже не придётся долго ждать.
Послесловие
А ведь есть ещё варианты разгона с понижением напруги типа такого. С учётом побеждённого перегрева, отчего б и его не задействовать… :)