What | Removed | Added |
---|---|---|
Priority | high | low |
Severity | major | minor |
Building on julien tempel's workaround, here's a somewhat more complex script to manage the memory p-state jumps. It switches between low and high memory p-states very reluctantly, so minimizing instances of flickering. I'm not a bash expert so please excuse the clumsy coding, but this works for me. #!/bin/bash # Each memory p-state switch causes a screen flicker. Tweak these variables to match # your personal 'flicker aversion' vs efficiency trade-off. CORE_P_STATE_UP=6 # The gpu core p-state at which we should jump up to memory p-state 2 CORE_P_STATE_DOWN=1 # The gpu core p-state at which we should drop down to low memory p-state UP_DELAY=2 # in seconds. How long to stay in low memory p-state before checking whether we can jump up to 2. DOWN_DELAY=10 # in seconds. How long to stay in memory p-state 2 before checking whether we can drop down to low. SLEEP_INTERVAL=1 # in seconds. How frequently we should poll the core p-state. LOW_MEM_STATE=0 # Choose between 0 & 1 # Sysfs paths here are hardcoded for one amdgpu card at card0; adjust as needed. FILE_PERF_LEVEL=/sys/class/drm/card0/device/power_dpm_force_performance_level FILE_MEM_P_STATE=/sys/class/drm/card0/device/pp_dpm_mclk FILE_CORE_P_STATE=/sys/class/drm/card0/device/pp_dpm_sclk # check for root privileges if [ $UID -ne 0 ] then echo "Writing to sysfs requires root privileges; relaunch as root" exit 1 fi # Set gpu performance level control to manual # echo "Setting performance level control to manual" echo "manual" > "$FILE_PERF_LEVEL" # Read the current core p-state and set a corresponding initial memory p-state CORE_P_STATE="$(grep -F '*' $FILE_CORE_P_STATE)" CORE_P_STATE=${CORE_P_STATE:0:1} if [ "$CORE_P_STATE" -ge "$CORE_P_STATE_UP" ]; then MEM_P_STATE=2 else MEM_P_STATE=$LOW_MEM_STATE fi echo "$MEM_P_STATE" > "$FILE_MEM_P_STATE" PROPOSED_MEM_P_STATE=$MEM_P_STATE function check_core_p_state { CORE_P_STATE="$(grep -F '*' $FILE_CORE_P_STATE)" CORE_P_STATE=${CORE_P_STATE:0:1} # Propose what the corresponding memory p-state should be OLD_PROPOSED_MEM_P_STATE=$PROPOSED_MEM_P_STATE PROPOSED_MEM_P_STATE=$MEM_P_STATE if [ "$CORE_P_STATE" -ge "$CORE_P_STATE_UP" ]; then PROPOSED_MEM_P_STATE=2 elif [ "$CORE_P_STATE" -le "$CORE_P_STATE_DOWN" ]; then PROPOSED_MEM_P_STATE=$LOW_MEM_STATE fi if [ "$PROPOSED_MEM_P_STATE" -ne "$MEM_P_STATE" ]; then # We want to change so determine where we are in the countdown. if [ "$PROPOSED_MEM_P_STATE" -ne "$OLD_PROPOSED_MEM_P_STATE" ]; then if [ "$PROPOSED_MEM_P_STATE" -eq 2 ]; then CHANGE_COUNTDOWN=$UP_DELAY else CHANGE_COUNTDOWN=$DOWN_DELAY fi fi (( CHANGE_COUNTDOWN = $CHANGE_COUNTDOWN - $SLEEP_INTERVAL )) if [ $CHANGE_COUNTDOWN -le 0 ]; then # The countdown has reached 0 so change the memory p-state. MEM_P_STATE=$PROPOSED_MEM_P_STATE echo "$MEM_P_STATE" > "$FILE_MEM_P_STATE" fi # else # we don't want to change. fi # echo "Old Prop Mem Core Countdown" # echo " $OLD_PROPOSED_MEM_P_STATE $PROPOSED_MEM_P_STATE $MEM_P_STATE $CORE_P_STATE $CHANGE_COUNTDOWN" # echo "" } function reset_on_fail { echo "Exiting, setting memory p-state to 2" echo "manual" > "$FILE_PERF_LEVEL" echo "2" > "$FILE_MEM_P_STATE" exit 1 } # always try to fix memory p-state 2 on failure trap "reset_on_fail" SIGINT SIGTERM function run_daemon { while :; do sleep $SLEEP_INTERVAL check_core_p_state done } # start the loop run_daemon