Archiv verlassen und diese Seite im Standarddesign anzeigen : Scripting-Experte gesucht: amdgpu Lüftersteuerung
aufkrawall
2018-01-16, 20:21:17
Hallo,
es ist möglich, den Grafikkartenlüfter via sysfs zu steuern und auch darüber die GPU-Temperatur auszulesen.
Lüftersteuerung auf manuell setzen (nur einmalig nötig):
echo "1" > /sys/class/drm/card0/device/hwmon/hwmon0/pwm1_enable
Lüftergeschwindigkeit einstellen (PWM von 0 - 255)
echo "0" > /sys/class/drm/card0/device/hwmon/hwmon0/pwm1
Temperatur auslesen:
cat /sys/class/drm/card0/device/hwmon/hwmon0/temp1_input Enthält nur die Temperatur in °C + drei Nullen (also etwa "42000" für 42°C).
Jetzt wär ich sehr dankbar, wenn mir jemand dafür ein Lüfterkurven-Script bastelt. Am besten in Bash und mit simpler Hysterese. Etwa Python wäre aber auch kein Problem, wenn das für die Performance/Overhead egal wäre.
Steuerung definiert sich wie folgt:
bis 65°C PWM-Interval von 0
von 65°C bis 80°C ein mit der Temperatur linear skalierender Drehzahlanstieg von PWM-Interval 0 bis bis 153 (entspricht 60%)
Hysterese von 6°C (Temperatur muss um diesen Wert fallen, bevor sich die Lüfterdrehzahl verringern darf; gilt natürlich nicht für Temperaturanstiege und Drehzahlerhöhungen)
Temperatur-Auslesen und Drehzahl-Setzen alle 1s
Aktualisierungsgeschwindigkeit und Hysterese am besten an Anfang oder Ende des Scripts isoliert platziert einstellbar
Wenn sich schon jemand die Mühe macht, könnte man natürlich auch mehr Steuerungspunkte einbauen, sodass sich mehr Leute die Kurve für ihre Zwecke anpassen können. Das könnte man dann auch ins Arch-Wiki oder auf Github packen. Außerdem könnte man es auch einfach für andere Lüfter nutzen, die via sysfs einstellbar sind.
Erdbeermayonnaise
2018-01-16, 22:33:06
Habe das mal ganz schnell runtergeschrieben. Nicht getestet, daher Benutzung auf eigene Gefahr.
HYSTERESIS=6000
SLEEP_INTERVAL=1
function set_pwm {
NEW_PWM=$1
OLD_PWM=$(cat /sys/class/drm/card0/device/hwmon/hwmon0/pwm1)
if [ $NEW_PWM -gt $OLD_PWM ] || [ -z $TEMP_AT_LAST_PWM_CHANGE ] || [ $(($(cat /sys/class/drm/card0/device/hwmon/hwmon0/temp1_input) + $HYSTERESIS)) -le $TEMP_AT_LAST_PWM_CHANGE ]; then
echo $NEW_PWM > /sys/class/drm/card0/device/hwmon/hwmon0/pwm1
TEMP_AT_LAST_PWM_CHANGE=$(cat /sys/class/drm/card0/device/hwmon/hwmon0/temp1_input)
fi
}
while :; do
CURRENT_TEMP=$(cat /sys/class/drm/card0/device/hwmon/hwmon0/temp1_input)
if [ $CURRENT_TEMP -le 65000 ]; then
set_pwm 0
elif [ $CURRENT_TEMP -le 80000 ]; then
set_pwm $((($CURRENT_TEMP - 65000) / 98))
else
set pwm 153
fi
sleep $SLEEP_INTERVAL
done
Nagelbrett
2018-01-16, 22:40:22
Mein Versuch: #!/bin/bash
INTERVAL=1
HYSTERESE=6
while true ; do
TEMP=$(( $(cat /sys/class/drm/card0/device/hwmon/hwmon0/temp1_input) / 1000 ))
DIFF=$(( $OLDTEMP - $TEMP ))
if [ $DIFF -lt 0 ] || [ $DIFF -ge $HYSTERESE ] ; then
if [ $TEMP -le 65 ] ; then
PWM="0"
elif [ $TEMP -le 80 ] ; then
PWM=$(( ( ($TEMP - 65.0) / 15.0 ) * 153.0 ))
else
PWM="153"
fi
echo ${PWM%.*} > /sys/class/drm/card0/device/hwmon/hwmon0/pwm1
OLDTEMP=$TEMP
fi
sleep $INTERVAL
done
Auch nicht wirklich getestet..
aufkrawall
2018-01-16, 23:28:40
Ihr seid klasse! =)
Nagelbrett, dein Script startet dadurch nicht:
./nagel.sh: Zeile 13: ( (70 - 65.0) / 15.0 ) * 153.0 : Syntaxfehler: Ungültiger arithmetischer Operator. (Fehlerverursachendes Zeichen ist \".0) / 15.0 ) * 153.0 \").
Kannst du die Ursache diagnostizieren? :)
Erdbeermayonnaise, es scheint auf den ersten Blick so zu funktionieren wie es soll. :cool:
Möchte das noch jemand anderes testen? Meine RX 560 ist schwer ins Schwitzen zu bringen. Einfach das Script als root starten.
Wenn man danach die Auto-Steuerung wieder will, am besten System neu starten. Eigentlich könnte man dafür auch echo "2" > /sys/class/drm/card0/device/hwmon/hwmon0/pwm1_enable setzen, allerdings funktioniert das bei mir nicht richtig (Treiber-Bug?). Daher der Hinweis mit dem Neustart.
Undervolting wie mit Wattman kommt btw. auch recht bald:
https://www.phoronix.com/scan.php?page=news_item&px=AMDGPU-Voltage-Sysfs
Edit: Erdbeermayonnaises Script funktioniert offenbar wirklich einwandfrei, auch die Hysterese (mit 1-2°C Abfall getestet). =) =)
Milchkanne
2018-01-17, 00:37:12
Nagelbrett, dein Script startet dadurch nicht:
Kannst du die Ursache diagnostizieren? :)
Das Problem ist, dass Bash keine Kommazahlen beherrscht. Einfach die Operatoren vertauschen, damit keine Rundungsfehler entstehen und die Kommastelle weglassen:
PWM=$(( ( ($TEMP - 65) * 153)/ 15 ))
Nagelbrett
2018-01-17, 17:26:28
Das Problem ist, dass Bash keine Kommazahlen beherrscht. Einfach die Operatoren vertauschen, damit keine Rundungsfehler entstehen und die Kommastelle weglassen:
PWM=$(( ( ($TEMP - 65) * 153)/ 15 ))
Oh stimmt, ich bin zsh gewöhnt, da geht das ;)
aufkrawall
2018-01-19, 23:41:52
Dein Script funktioniert damit offenbar genau so gut wie das von Erdbeermayonnaise. :)
nett, packt das doch auf GitHub und ins AUR ;)
aufkrawall
2018-01-24, 12:06:24
Wär noch schön, wenn wir das Ganze etwas abstrahieren könnten. Für die Punkte wäre eine Art Tabelle ganz schön, die einfach zu erkennen und ggf. zu erweitern ist.
Ich meine erkennen zu können, wie im Script von Erdbeermayonnaise pwm1 gesetzt wird. Allerdings könnte das erstmal verwirrend wirken, und da das ja im Vergleich zur eigentlichen Lüfterkurve ein Sonderfall im Script ist, könnte man das vielleicht ebenfalls noch etwas prominenter herausstellen, damit sich es jemand für andere Lüfter leichter anpassen kann?
kann ich mir ja mal anschauen, wenn ich wieder zuhause bin. Wie stellst du dir das mit der Tabelle vor?
aufkrawall
2018-01-29, 13:03:08
(Bin gerade nur via mobile on.)
Die anpassbaren Parameter sollten möglichst leicht zu erkennen sein, also isoliert stehen. Lässt sich via Bash womöglich nicht zu 100% realisieren, sollte nur leichter zu erkennen sein als bisher.
In der Tabelle sollte eine Zeile pro Lüfterdrehzahl bis Temperatur x sein. Schön wärs, wenn man beliebig weitere Zeilen hinzufügen könnte und das Script das dann ohne weitere Anpassungen entsprechend verarbeitet.
aufkrawall
2018-02-11, 15:46:07
Will noch wer? Sonst versuch ich es so, es ins Wiki zu bringen.
DevilX
2018-02-11, 21:04:10
Ich shaue mal morgen oder so zu testen.
aufkrawall
2018-02-11, 21:24:08
Ich dachte eher ans Script "abstrahieren". ;)
Ich hab das Script von Erdbeermayonnaise jetzt drei Wochen in Benutzung, ich gehe da eigentlich nicht mehr von Problemen aus.
DevilX
2018-02-12, 06:27:34
Dafür reicht mein Können nicht aus ;-).
Das Problem ist, dass Bash keine Kommazahlen beherrscht. Einfach die Operatoren vertauschen, damit keine Rundungsfehler entstehen und die Kommastelle weglassen:
PWM=$(( ( ($TEMP - 65) * 153)/ 15 ))
Oder mit bc rechnen. :wink:
#!/bin/bash
HYSTERESIS=6000 # in mK
SLEEP_INTERVAL=1 # in s
# set temps (in degrees C * 1000) and corresponding pwm values in ascending order and with the same amount of values
TEMPS=( 65000 80000 90000 )
PWMS=( 0 153 255 )
# hwmon paths, hardcoded for one amdgpu card at hwmon0, adjust as needed
FILE_PWM=/sys/class/drm/card0/device/hwmon/hwmon0/pwm1
FILE_FANMODE=/sys/class/drm/card0/device/hwmon/hwmon0/pwm1_enable
FILE_TEMP=/sys/class/drm/card0/device/hwmon/hwmon0/temp1_input
# might want to use this later
#FILE_TEMP_CRIT=/sys/class/hwmon/hwmon0/temp1_crit_hyst
# checking for privileges
if [ $UID -ne 0 ]
then
echo "Writing to sysfs requires privileges, relaunch as root"
exit 1
fi
# set fan mode to max(0), manual(1) or auto(2)
function set_fanmode {
echo "setting fan mode to $1"
echo $1 > $FILE_FANMODE
}
function set_pwm {
NEW_PWM=$1
OLD_PWM=$(cat $FILE_PWM)
echo "current pwm: $OLD_PWM, requested to set pwm to $NEW_PWM"
if [ $NEW_PWM -gt $OLD_PWM ] || [ -z $TEMP_AT_LAST_PWM_CHANGE ] || [ $(($(cat $FILE_TEMP) + $HYSTERESIS)) -le $TEMP_AT_LAST_PWM_CHANGE ]; then
echo "temp at last change was $TEMP_AT_LAST_PWM_CHANGE"
echo "changing pwm to $NEW_PWM"
echo $NEW_PWM > $FILE_PWM
TEMP_AT_LAST_PWM_CHANGE=$(cat $FILE_TEMP)
else
echo "not changing pwm, we just did at $TEMP_AT_LAST_PWM_CHANGE, next change when below $(($TEMP_AT_LAST_PWM_CHANGE - $HYSTERESIS))"
fi
}
function interpolate_pwm {
i=0
TEMP=$(cat $FILE_TEMP)
echo "current temp: $TEMP"
if [[ $TEMP -le ${TEMPS} ]]; then
# below first point in list, set to min speed
set_pwm ${PWMS[i]}
return
fi
for i in "${!TEMPS[@]}"; do
if [[ $i -eq $((${#TEMPS[@]}-1)) ]]; then
# hit last point in list, set to max speed
set_pwm ${PWMS[i]}
return
elif [[ $TEMP -gt ${TEMPS[$i]} ]]; then
continue
fi
# interpolate linearly
LOWERTEMP=${TEMPS[i-1]}
HIGHERTEMP=${TEMPS[i]}
LOWERPWM=${PWMS[i-1]}
HIGHERPWM=${PWMS[i]}
PWM=$(echo "( ( $TEMP - $LOWERTEMP ) * ( $HIGHERPWM - $LOWERPWM ) / ( $HIGHERTEMP - $LOWERTEMP ) ) + $LOWERPWM" | bc)
echo "interpolated pwm value for temperature $TEMP is: $PWM"
set_pwm ${PWM}
return
done
}
function reset_on_fail {
echo "exiting, resetting fan to auto control..."
set_fanmode 2
exit 1
}
# always try to reset fans on exit
trap "reset_on_fail" SIGINT SIGTERM
function run_daemon {
while :; do
interpolate_pwm
echo
sleep $SLEEP_INTERVAL
done
}
# set fan control to manual
set_fanmode 1
# finally start the loop
run_daemon
Das ist etwas "verbose" geworden, obwohl es auch noch keine Fehlerkorrektur oder sowas hat, aber ich denke die Funktionalitaet sollte so jetzt relativ klar werden. Also Vorsicht und natuerlich wie immer auf eigene Gefahr, das Testen ueberlasse ich auch dir da bei mir die Temperatur unter Wasser eh nicht so schwankt ;p
Wie autostartest du das eigentlich? Eine Systemd unit ist auch schnell und einfach erstellt.
Hast du eigentlich schon mal lm_sensors angeschaut? Die haben auch ein pwm tool mit daemon. Es gibt auch irgend eine (community) Radeon GUI mit daemon wo man sowas einbauen koenne. rocm-smi (https://github.com/RadeonOpenCompute/ROC-smi) koennte auch ganz nuetzlich sein, wenn man nur mal was austesten will (dafuer brauchst auch keinen vollen ROC Stack, das schreibt und liest auch nur aus sysfs).
Demnaechst soll ja irgendwann auch noch so eine art Wattman-Funktionalitaet ins sysfs kommen, mit einzelnen Taktraten und Spannungen fuer die DPM States. Wuerde sich vielleicht dann doch noch irgendwie lohnen einen sauberen daemon zu haben. Habe auch demletzt gesehen, dass Wattman Profile via XML exportieren kann, von daher koennte man das sich schon mal anschauen...
aufkrawall
2018-02-15, 13:35:05
Klasse Arbeit, sehr übersichtlich und leicht anzupassen! :up: Auch die Verbosity ist echt super, alles gleich im Blick. =)
Bei einem kurzen Test klappte auch soweit alles einwandfrei (auch die Hysterese), so lange die Temperatur anstieg oder gleich blieb. Bei einem Temperaturabfall passierte dann allerdings das:
current temp: 68000
interpolated pwm value for temperature 68000 is: 30
current pwm: 51, requested to set pwm to 30
not changing pwm, we just did at 70000, next change when below 64000
current temp: 63000
current pwm: 51, requested to set pwm to 153
temp at last change was 70000
changing pwm to 153
current temp: 59000
current pwm: 153, requested to set pwm to 153
not changing pwm, we just did at 63000, next change when below 57000
Sieht so aus, als hätte er nicht interpoliert, sondern stattdessen die Ziel-Drehzahl für die 80°C genommen. Wurd dann natürlich etwas lauter und blieb es auch, kannst du da nochmal nach schauen? :)
Dass er bei Beendung den Lüfter wieder auf auto stellt, ist auch sehr cool und aus Sicherheitsgründne natürlich absolut logisch. Allerdings gibts offenbar einen Bug in amdgpu, dass die Lüftersteuerung nach einmaligem Umstellen auf manual nicht mehr richtig im auto-Mode funktioniert. Das hat zur Folge, dass dann etwa beim Herunterfahren einmal der Lüfter hochdreht, was natürlich unschön ist.
Deswegen stell ich persönlich den fanmode auch bei Beenden auf 1, allerdings können wir ja im Wiki (und Script?) auf den Bug hinweisen.
Mit dem gleichen Problem haben auch die auf lm_sensors basierenden Daemons zu kämpfen, da war die Drehzahl sogar noch extremer. Das war auch eigentlich der Hauptgrund, warum ich eine Bash-Lösung mit sysfs wollte, um einfach volle Kontrolle darüber zu haben. Außerdem ist es halt die "dünnstmöglichste" Lösung und kommt komplett ohne zusätzlichen Programmcode aus, was doch auch sehr cool ist. Kein Programmcode bedeutet natürlich auch hohen Schutz vor Crashes, was mit dem auto fanmode Bug natürlich auch wertvoll ist.
Ich starte das Script einfach über die DE bei Login via sudo, mit der Methode ist das automatisch root und geht ohne PW:
https://askubuntu.com/questions/167847/how-to-run-bash-script-as-root-with-no-password
Ist die Frage, ob die Verbosity einem dann den Speicher minimal, aber dennoch unnötig füllt?
Auf den "Wattman" freue ich mich auch schon ziemlich. Ich nehme an, dass dann einfach die Default-States schon im sysfs liegen und man die nur anpassen braucht, also einfach Wattman in Form einer Textdatei.
Sieht so aus, als hätte er nicht interpoliert, sondern stattdessen die Ziel-Drehzahl für die 80°C genommen. Wurd dann natürlich etwas lauter und blieb es auch, kannst du da nochmal nach schauen? :)
Danke, habe obigen Beitrag aktualisiert (Zeile 48; "i=0"). pwm wurde auf i gesetzt, in der Annahme i sei 0, ohne i aber vorher (nach der Schleife) zurueckzusetzen :redface:
Allerdings gibts offenbar einen Bug in amdgpu, dass die Lüftersteuerung nach einmaligem Umstellen auf manual nicht mehr richtig im auto-Mode funktioniert. Das hat zur Folge, dass dann etwa beim Herunterfahren einmal der Lüfter hochdreht, was natürlich unschön ist.
Deswegen stell ich persönlich den fanmode auch bei Beenden auf 1, allerdings können wir ja im Wiki (und Script?) auf den Bug hinweisen.
OK, ist mir nicht aufgefallen, da ja bei mir eh kein Luefter laeuft. :redface: Klar, kannst du gerne so machen
Mit dem gleichen Problem haben auch die auf lm_sensors basierenden Daemons zu kämpfen, da war die Drehzahl sogar noch extremer. Das war auch eigentlich der Hauptgrund, warum ich eine Bash-Lösung mit sysfs wollte, um einfach volle Kontrolle darüber zu haben. Außerdem ist es halt die "dünnstmöglichste" Lösung und kommt komplett ohne zusätzlichen Programmcode aus, was doch auch sehr cool ist. Kein Programmcode bedeutet natürlich auch hohen Schutz vor Crashes, was mit dem auto fanmode Bug natürlich auch wertvoll ist.
Wie gesagt, error handling macht das Skript hier jetzt auch nicht. Auch wenn die Funktionalitaet jetzt in C gemacht waere, wuerde ich ja trotzdem auch nur strings in sysfs schreiben und da koennte man auch zurueck auf auto (oder max) gehen, bevor man den Prozess abschmieren laesst. Aber mir ist das im Grunde egal
Auch noch denkbar waeren udev rules, sodass das Skript entsprechend ueberhaupt gar nicht erst als root laufen muesste. Dann definiert man halt die paar Eintraege als modifizierbar fuer Gruppe oder User.
Ich starte das Script einfach über die DE bei Login via sudo, mit der Methode ist das automatisch root und geht ohne PW:
https://askubuntu.com/questions/167847/how-to-run-bash-script-as-root-with-no-password
Ist die Frage, ob die Verbosity einem dann den Speicher minimal, aber dennoch unnötig füllt?
Das kommt darauf an, wie die DE das handhabt. Normalerweise haengt stdout von einem entkoppelten Prozess auf /dev/null und wird dementsprechend nirgends gespeichert. Aber ja, systemd wuerde es sich z.B. merken, ist dann ja ueber journalctl abrufbar
Auf den "Wattman" freue ich mich auch schon ziemlich. Ich nehme an, dass dann einfach die Default-States schon im sysfs liegen und man die nur anpassen braucht, also einfach Wattman in Form einer Textdatei.
Naja, wohl nicht ganz so, aber fast ;) Ein Tool waere dann aber entsprechend auch relativ simpel gemacht. Und man braeuchte halt soi oder so trotzdem immer noch einen daemon, damit es nach dem Booten direkt gesetzt wird, als Alternative zum BIOS Mod.
when cat pp_od_clk_voltage it show
OD_SCLK:
0: 300Mhz 800 mV
1: 466Mhz 818 mV
2: 751Mhz 824 mV
3: 1019Mhz 987 mV
4: 1074Mhz 1037 mV
5: 1126Mhz 1087 mV
6: 1169Mhz 1137 mV
7: 1206Mhz 1150 mV
OD_MCLK:
0: 300Mhz 800 mV
1: 1650Mhz 1000 mV
echo "s/m level clock voltage" to change
sclk/mclk's clock and voltage
echo "r" to restore default value.
https://lists.freedesktop.org/archives/amd-gfx/2018-January/017763.html
aufkrawall
2018-02-15, 16:04:04
Danke, habe obigen Beitrag aktualisiert (Zeile 48; "i=0"). pwm wurde auf i gesetzt, in der Annahme i sei 0, ohne i aber vorher (nach der Schleife) zurueckzusetzen :redface:
Scheint jetzt einwandfrei zu funktionieren. :)
Auch noch denkbar waeren udev rules, sodass das Skript entsprechend ueberhaupt gar nicht erst als root laufen muesste. Dann definiert man halt die paar Eintraege als modifizierbar fuer Gruppe oder User.
Imho ist es unbedenklich, wenn das Script als root läuft. Von daher nicht unser Bier, steht im Wiki ja sicher schon genug zu dem Thema. :)
Hätte natürlich nichts dagegen, wenn du so einen Zusatz erwähnt haben möchtest.
Das kommt darauf an, wie die DE das handhabt. Normalerweise haengt stdout von einem entkoppelten Prozess auf /dev/null und wird dementsprechend nirgends gespeichert. Aber ja, systemd wuerde es sich z.B. merken, ist dann ja ueber journalctl abrufbar
Der RAM-Verbrauch scheint unter KDE Plasma einfach via sudo ohne Konsolenfenster zum Glück nicht weiter zu steigen.
Naja, wohl nicht ganz so, aber fast ;) Ein Tool waere dann aber entsprechend auch relativ simpel gemacht. Und man braeuchte halt soi oder so trotzdem immer noch einen daemon, damit es nach dem Booten direkt gesetzt wird, als Alternative zum BIOS Mod.
https://lists.freedesktop.org/archives/amd-gfx/2018-January/017763.html
Ich werd aus Faulheit einfach den kompletten Inhalt mit echo@login überschreiben. :freak:
Supi, vielen Dank nochmal. Ich werd nochmal etwas testen und dann können du oder ich das sicherlich im Arch Wiki unterbringen. :smile:
aufkrawall
2018-03-04, 16:32:43
Per systemd:
/etc/systemd/system/iuno.service
[Unit]
Description=amdgpu custom fancontrol
[Service]
ExecStart=/home/USER/bashscripts/iuno.sh
Restart=on-failure
[Install]
WantedBy=multi-user.target
Lässt sich einwandfrei via status abfragen und startet nach dem Killen wie gewollt neu.
Edit: Vergessen, Script ausführbar zu machen. Alles gut nun.
aufkrawall
2018-03-17, 13:37:26
Weiß jemand, wie die Config aussehen müsste, damit das Script nach dem Aufwachen aus dem Suspend/Hibernate neu gestartet wird? Es wird sonst die Drehzahl nicht mehr angepasst.
raumfahrer
2018-03-17, 16:09:41
https://unix.stackexchange.com/questions/124212/writing-a-systemd-service-to-be-executed-at-resume/227293#227293
Schon dies ausprobiert?
Du könntest dich auch mit "BindsTo=" oder so an irgendeinen Service hängen, der
garantiert im normalen Betrieb lauft.
aufkrawall
2018-03-17, 17:00:36
Der Service läuft ja noch, aber er braucht halt einen Neustart. Deswegen klappt das mit dem suspend.target offenbar nicht und ich schätze, das würde auch auf BindsTo= zutreffen.
raumfahrer
2018-03-17, 18:01:09
Läuft der Prozess denn auch noch, oder meint der Service das nur?
aufkrawall
2018-03-17, 18:48:36
Jap, der läuft tatsächlich noch und iunos Script gibt via status auch zurück, dass es noch Drehzahlen festlegen würde (was aber nicht der Fall ist).
raumfahrer
2018-03-18, 12:48:39
Steht pwm1_enable denn noch auf manuell nach dem resume?
aufkrawall
2018-03-18, 13:09:20
Stimmt, das steht wieder auf 2. Allerdings ändert sich trotz des laufenden Scripts die Drehzahl nicht, wenn ich dann manuell wieder 1 setze.
aufkrawall
2018-03-20, 19:31:39
Läuft. =)
https://wiki.archlinux.org/index.php/Power_management#Sleep_hooks
/etc/systemd/system/root-resume.service
[Unit]
Description=Local system resume actions
After=suspend.target
[Service]
Type=simple
ExecStart=/usr/bin/systemctl restart iuno.service
[Install]
WantedBy=suspend.target
aufkrawall
2018-03-20, 20:07:18
@iuno:
Ich hatte jetzt mal
TEMPS=( 65000 100000 )
PWMS=( 0 204 )
gesetzt. Damit fing er bei 66°C direkt an, die 204 PWM-Intervalle zu setzen. Kannst du da nochmal nach schauen? :redface:
Edit: Warte mal, ich hab da ohne zu überlegen die Punkte von Afterburner übernommen...
Edit 2: Müsste aber doch trotzdem gehen?
raumfahrer
2018-03-20, 22:07:12
Das Skript funktioniert nur ab drei Punkten so wie du es dir vorstellst
(ungefähr -- sobald die Temperatur größer als der vorletzte Eintrag in TEMPS
ist wird der letzte Wert aus PWMS gesetzt). Shell-Skripte sind IMO ziemlich
"unclean" hinsichtlich der Syntax (sobald es ein bisschen komplexer wird).
for i in "${!TEMPS[@]}"; do
if [[ $i -eq $((${#TEMPS[@]}-1)) ]]; then
# hit last point in list, set to max speed
set_pwm ${PWMS[i]}
return
elif [[ $TEMP -gt ${TEMPS[$i]} ]]; then
continue
fi
Hoffe der Pseudocode macht das Problem offensichtlicher:
for i in range 0 to last_idx(TEMPS)
if i == last_idx(TEMPS)
set_pwm TEMPS[i]
stop loop
elseif TEMP > TEMPS[i]
next i
else
interpolate
Wenn i==0 und die Temperatur größer ist als der erste Eintrag in TEMPS springt
es zu i==1, das ist dann gleich dem letzten Index von TEMPS und somit wird
direkt die entsprechende PWM gesetzt.
Du willst eher sowas:
if [[ $i -eq $((${#TEMPS[@]}-1)) ]] && [[ $TEMP -ge ${TEMPS[$i]} ]]; then
Wenn am Ende _und_ aktuelle Temperatur >= letzter Eintrag, dann usw.
Ich bin übrigens skeptisch, wieso der Service-Restart notwendig sein sollte.
aufkrawall
2018-03-21, 13:52:30
Thx für die Erläuterung, dann erwähnen wir das mit den mind. drei Punkten lieber mal.
Ich teste aber noch >3. Muss nur zuverlässig funktionieren und keinen Syntax-Preis gewinnen. :)
Ich bin übrigens skeptisch, wieso der Service-Restart notwendig sein sollte.
Ich vermute, durch das Neustarten des Treibers, ausgelöst durch Suspend, wird der Status von sysfs nicht richtig beachtet oder übernommen. Ich glaube nicht, dass das Script da etwas falsch macht. Der Workaround funktioniert zum Glück ohne Nebenwirkung, anders als z.B. das Script automatisch alle X Sekunden neu starten zu lassen, was dann die Hysterese kaputt machen würde.
raumfahrer
2018-03-22, 00:05:14
Thx für die Erläuterung, dann erwähnen wir das mit den mind. drei Punkten lieber mal.
Wurde evtl. nicht deutlich, aber du solltest durch anhängen von
&& [[ $TEMP -ge ${TEMPS[$i]} ]]
an die erste if-Bedingung in der Schleife das gewünschte Resultat erzielen
können. Alternativ kannst du die Interpolationsfunktion auch ein wenig
abändern.
function interpolate_pwm {
TEMP=$(cat $FILE_TEMP)
echo "current temp: $TEMP"
if [[ $TEMP -le ${TEMPS[0]} ]]; then
# below first point in list, set to min speed
set_pwm ${PWMS[0]}
return
fi
if [[ $TEMP -ge ${TEMPS[-1]} ]]; then
# above last point in list, set to max speed
set_pwm ${PWMS[-1]}
return
fi
for i in "${!TEMPS[@]}"; do
if [[ $TEMP -gt ${TEMPS[$i]} ]]; then
continue
fi
# interpolate linearly
LOWERTEMP=${TEMPS[i-1]}
HIGHERTEMP=${TEMPS[i]}
LOWERPWM=${PWMS[i-1]}
HIGHERPWM=${PWMS[i]}
PWM=$(echo "( ( $TEMP - $LOWERTEMP ) * ( $HIGHERPWM - $LOWERPWM ) / ( $HIGHERTEMP - $LOWERTEMP ) ) + $LOWERPWM" | bc)
echo "interpolated pwm value for temperature $TEMP is: $PWM"
set_pwm ${PWM}
return
done
}
Zu Arrays in bash: ${ARRAY} ist identisch mit ${ARRAY[0]}.
aufkrawall
2018-04-22, 14:30:17
Wurde evtl. nicht deutlich, aber du solltest durch anhängen von
&& [[ $TEMP -ge ${TEMPS[$i]} ]]
an die erste if-Bedingung in der Schleife das gewünschte Resultat erzielen
können.
Damit funktioniert es leider nicht mehr richtig.
Passt aber schon, mind drei Werte als Einschränkung ist ja völlig akzeptabel.
Ich habs gerade auch mit sechs Werten getestet, scheint auch damit einwandfrei zu funktionieren.
Nochmal dickes Thx @ iuno!
vBulletin®, Copyright ©2000-2025, Jelsoft Enterprises Ltd.