[Skript] Windows PowerPlan Switcher for Nvidia

S

Stuntmp02

Gast
Hallo zusammen,

ich habe ein Skript geschrieben, dass automatisch den Windows Energiesparplan in Abhängigkeit von der Nvidia-GPU Auslastung und P-State ändert (Nur mit Nvidia Grafikkarten kompatibel). Damit kombiniere ich den "Balanced" Energiesparplan für Non-Gaming mit dem "High Performance" Energiesparplan, während die Grafikkarte belastet ist, ich also am zocken bin.

Sobald die Grafikkarte in den P0 (Performance State) wechselt und mehr als 25% GPU-Auslastung hat: High Performance
Während die Grafikkarte in einem Energiesparmodus ist oder weniger als 25% GPU-Auslastung hat: Balanced
Alle Parameter sind im Block ## To Fill ## frei konfigurierbar

Gerade bei Gaming hat der Prozessor sehr schwankende Last, sodass mit dem Balanced Energiesparplan im GPU-Limit deutliche Latenzen und Lagspikes entstehen können, weil Prozessorkerne bei niedriger Last heruntertakten und dann bei einer Lastspitze erst wieder hochtakten müssen. Je nach Spiel sind die Auswirkungen nicht vorhanden (Quantum Break) bis zu extrem störend (Overwatch oder Nioh).
  • Das Skript verursacht keine nennenswerte Auslastung
  • Beim Browsen wird Strom gespart, beim Zocken sind die Latenzen minimiert
  • Das Umschalten erfolgt automatisch und die Parameter können im Skript konfiguriert werden
PowerShell:
## To Fill
$NvidiaSMIFolderPath = "C:\Program Files\NVIDIA Corporation\NVSMI"
$GamingPState = "P0"
$MinGPUUsage = 25
$CheckEverySeconds = 10
$GamingPowerPlanID = "8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c"
$NoGamingPowerPlanID = "381b4222-f694-41f0-9685-ff5bb260df2e"

## Power Plans IDs (Use Without #)
# 381b4222-f694-41f0-9685-ff5bb260df2e = Balanced
# 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c = High performance
# a1841308-3541-4fab-bc81-f71556f20b4a = Power saver

$SMICommand = "& '" + $NvidiaSMIFolderPath + "\nvidia-smi.exe`' --query-gpu=pstate,utilization.gpu --format=csv,noheader,nounits"

while ($true){
    $GPUData = (Invoke-Expression -command $SMICommand).split(",")

    if ($GPUData[0] -eq $GamingPState -and [int]$GPUData[1] -ge $MinGPUUsage){
        if ((powercfg /GetActiveScheme) -notlike ("*" + $GamingPowerPlanID + "*")){    
            powercfg -s $GamingPowerplanID
        }
    }
    else{
        if ((powercfg /GetActiveScheme) -notlike ("*" + $NoGamingPowerPlanID + "*")){
            powercfg -s $NoGamingPowerPlanID
        }
    }
    Start-Sleep -Seconds $CheckEverySeconds
}

PowerShell:
## To Fill
$NvidiaSMIFolderPath = "C:\Program Files\NVIDIA Corporation\NVSMI"
$MinGPUUsage = 25
$CheckEverySeconds = 10
$GamingPowerPlanID = "8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c"
$NoGamingPowerPlanID = "381b4222-f694-41f0-9685-ff5bb260df2e"

## Power Plans IDs (Use Without #)
# 381b4222-f694-41f0-9685-ff5bb260df2e = Balanced
# 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c = High performance
# a1841308-3541-4fab-bc81-f71556f20b4a = Power saver

$SMICommand = "& '" + $NvidiaSMIFolderPath + "\nvidia-smi.exe`' --query-gpu=utilization.gpu --format=csv,noheader,nounits"

while ($true){
    [int]$GPUData = Invoke-Expression -command $SMICommand

    if ($GPUData -ge $MinGPUUsage){
        if ((powercfg /GetActiveScheme) -notlike ("*" + $GamingPowerPlanID + "*")){    
            powercfg -s $GamingPowerplanID
        }
    }
    else{
        if ((powercfg /GetActiveScheme) -notlike ("*" + $NoGamingPowerPlanID + "*")){
            powercfg -s $NoGamingPowerPlanID
        }
    }
    Start-Sleep -Seconds $CheckEverySeconds
}

Anleitung

1: Kopiert den Skript Code in eine Textdatei auf eurem Computer und benennt diese von .txt zu .ps1 um (in meinem Beispiel C:\Install\Skripts\Nvidia_PowerPlanSwitcher\Nvidia_PowerPlanSwitcher.ps1)

2: Öffnet die Aufgabenplanung (Task Scheduler in eng) und geht auf "Neue Aufgabe erstellen / Create Task". Folgt nun den Bildern.
1540043768130.png


1540043786720.png



1540043799400.png


Nach diesen Einstellungen könnt ihr die Aufgabe / Task mit OK speichern und müsst nur noch euer Kennwort eingeben.

1540043947850.png


Ab dem nächsten Windows-Start läuft nun mit 1 Minute Verzögerung das Skript und prüft alle 10 Sekunden die GPU-Auslastung, um dann den Windows Energiesparplan entsprechend zu setzen. Im Task Manager läuft das Skript dann als "powershell.exe". Während ich hier also in Edge diese Zeilen verfasse, ist der Balanced Energieplan aktiv, sobald ich aber ein Game starte, wird nach wenigen Sekunden in den High Performance Energiesparplan gewechselt.

Getestet unter Windows 10 mit einer GTX 1080 und einem Standard Nvidia Treiber ohne Geforce Experience.

Troubleshooting
Es ist möglich, dass die ExecutionPolicy auf Unrestricted gestellt werden muss, damit das Ausführen von Skripts erlaubt wird. Beim User @Pizza! konnte damit das Skript erfolgreich genutzt werden.
1: Powershell als Administrator ausführen
2: In die geöffnete PowerShell folgende Zeile eingeben
PowerShell:
Set-ExecutionPolicy Unrestricted

Ihr könnt die Änderung wie folgt wieder rückgängig machen, dann funktioniert aber ggf. der PowerPlan Switcher nicht mehr.
PowerShell:
Set-ExecutionPolicy Restricted
 
Zuletzt bearbeitet: (Update)
  • Gefällt mir
Reaktionen: Seko, Topfn, tzuiop und 5 andere
Vielen Dank für deine Veröffentlichung, Anleitung & sonstige Mühen.
Das teste ich auf jeden Fall aus.
Bisher habe ich wegen den Energieprofilen eine ziemliche Fummelei.
Warum die Developer bei Microsoft nicht darauf kommen, ist mir ein Rätsel.
 
Das kann ich auch absolut nicht nachvollziehen, ich habe selbst zuvor nach Tools oder Apps gesucht, die das können, bin aber absolut nicht fündig geworden. Das einzige, was aufzufinden war, ist ein Tool zum Umschalten zwischen Strom-Betrieb und Akku-Betrieb, aber keines in Abhängigkeit von laufenden Prozessen oder bei Vollbild, DirectX-Belastung oder ähnliches. Finde das auch ziemlich schwach von Microsoft, dass es sowas nicht längst gibt...
 
@doof123
Was ich noch anmerken wollte, man kann das Skript auch einfach ohne den Task scheduler ausführen, um es zu testen - dann startet es halt nicht automatisch bei jedem Windows Boot mit, wie über den Task Planer. Einfach hierfür den Code in eine .txt Datei reinkopieren, die Datei zu .ps1 umbenennen und mit rechtsklick -> run with PowerShell ausführen. Es erscheint dann nur ein blinkender Cursor, aber das Programm läuft und man sieht es am einfachsten, wenn man in die Energiesparverwaltung geht und danach z.B. den GPU-Z rendertest startet - nach wenigen Sekunden ist High Performance ausgewählt, sobald man den rendertest wieder stoppt, ist balanced nach wenigen Sekunden wieder der Standard.
 
  • Gefällt mir
Reaktionen: doof123
[Update]
Ich habe das Skript minimal modifiziert:
Bisher hat das Skript bei jeder Ausführung je nach GPU-Auslastung den gewünschten Energiesparplan aktiviert, auch wenn dieser schon aktiviert war. Ich habe nun eine Abfrage eingebaut, welches den aktuellen Energiesparplan zuerst ausliest und nur wenn der gewünschte Energiesparplan nicht bereits aktiv ist, wird er umgeschaltet.

Bisher: 3D Auslastung erkannt: Aktivieren von GamingPowerPlan
Neu: 3D Auslastung erkannt: Aktivieren von GamingPowerPlan, wenn ein anderer PowerPlan derzeit aktiv ist. Wenn GamingPowerPlan bereits aktiv ist, nichts machen

Obendrein habe ich eine "Lite Variante" ohne den Filter für den PState erstellt, wenn jemand diesen Filter nicht braucht und lieber ein paar Kiloherz an Rechenzeit spart.

Performance Verbrauch des Skripts
Ich habe einen Performance Test für die Variante ohne P-State durchgeführt und dafür die Schleife alle 100ms ausführen lassen, also 10x pro Sekunde, anstatt einmal alle x Sekunden (10-60 würde ich empfehlen). Das ganze über den Zeitraum von einer Minute mit ständigem ab- und anschalten von GPU-Z Rendertest, um eine GPU-Last zu erzeugen und einen Energiesparplan-Wechsel zu erzeugen.

Der Start des Skripts hat genau 484ms Rechenzeit von einem Core benötigt (Powershell läd relativ viel Module beim Start automatisch) und danach für etwa 600 Checks (10 pro Sekunde über 1 Minute) ist die Rechenzeit von 484ms (Start) auf 578ms (Start + 600 Checks) angestiegen, die 600 Checks haben also zusammen in etwa 94ms Rechenzeit benötigt.

Das entspricht einer CPU-Auslastung pro Check von 0,16ms von einem Thread. Bei einem 4Ghz Prozessor verbraucht also ein Check 0,64Mhz von einem einzelnen Thread. Die Lite Variante braucht 0,12ms, was 0,48Mhz entsprechen würde. Man braucht sich also wirklich keine Sorgen wegen der Auslastung machen, die das Skript selbst erzeugt :daumen:

Das Code Update ist in Post 1 zu finden

@doof123 Vielleicht ist für dich die neue Version interessant
 
Zuletzt bearbeitet:
@Stunrise Hi ich versuche es, aber Windows startet es nicht. Ergebnis letzte Ausführung (0x1)
Manuell Rechtsklick mit powershell ausführen klappt.

Es ist kurz im Taskmanager aufgetaucht und wieder verschwunden.
 
Zuletzt bearbeitet:
@Pizza!
Mach mal Screenshots von deinem Task Scheduler, insb. vom Reiter General und Actions

Hast du ein Kennwort auf deinem Windows Benutzer, oder ist der Windows Benutzer ohne Kennwort?
 
Also bei mir ist es mit dem Microsoft Konto Verknüpft, mein Nutzername sind die Anfangsbuchstaben der email.
Die Anmeldung hab ich manuell eingestellt dass es ohne Passwort eingeben geht.
aktionen.jpg
aufgabenplan.jpg
 
@Pizza!
Meines Erachtens stimmt dein Benutzer nicht, mit dem das ganze gestartet werden soll. Heißt dein Benutzer denn "dwaal", so wie es in der Aufgabenplanung eingestellt ist? Das mit dem verknüpften Microsoft Account könnte die Ursache dafür sein. Stell die Aufgabe mal auf "System", vielleicht klappts ja damit (bei mir läufts mit System prima)

1546686700979.png
 
Ja seit der Verknüpfung mit dem account heißt alles bzw. mein ordner dwaal
Total blöd mit dem ganzen, früher hats auch mit Benutzernamen funktioniert. Man kann glaub nicht alles umbenennen oder?

Funktioniert mit System auch nicht, selber Fehler.

Edit: hab mein PC Name und Benutzername angepasst, Ordner bleibt beim alten. Ich nehme mal die ähnlichen Einstellungen wie eine andere Aufgabe

Edit: so @Stunrise ich hab Benutzername, PC Name und Ordner geändert. Auch statt bei Systemstart, mal bei Anmeldung eines Benutzers probiert. Nix geändert, selber Fehler, powershellfenster ploppt ganz kurz auf und verschwindet und stellt nix um

Nun noch den Pfad einfacher gemacht. habe es pps.ps1 genannt und direkt auf C: gelegt
aufgabe simpel.jpg


Funktioniert alles nicht, auch nicht wenn ich es auf D: lege. Irgendwas verhindert dass es weiter ausgeführt wird. Da es ja für ein Augenblinzeln manchmal auftaucht.

Kann ich es irgendwie minimiert in autostart legen und das powershell es ausführt? ich weiß nicht weiter :heul:

Edit: Stunrise bester Mann, hat geholfen, es waren die restricted policy, haben die Ausführung des Skripts verhindert. Er updated sein 1. Post
 
Zuletzt bearbeitet:
Zurück
Oben