#!/bin/bash # script for tuned AMDGPU clock control # configures GPU power/clock characteristics # clocks/power in 3D are dynamic based on need/usage # # for 'amdgpu-default' tuned profiles, this will reset the characteristics to default # for others this will apply overclocking settings -- leaving clock choices to the associated power profile (eg: VR) # # rendered by Ansible with environment-appropriate values: # card #, eg: card0 # path to discovered sysfs device files (power/clock/voltage control) # # AMDGPU driver/sysfs references: # https://01.org/linuxgraphics/gfx-docs/drm/gpu/amdgpu.html # https://docs.kernel.org/gpu/amdgpu/thermal.html {# done this way to avoid issues with the card number possibly shifting after playbook run #} # dynamically determine the connected GPU using the DRM subsystem CARD=$(/usr/bin/grep -ls ^connected /sys/class/drm/*/status | /usr/bin/grep -o 'card[0-9]' | /usr/bin/sort | /usr/bin/uniq | /usr/bin/sort -h | /usr/bin/tail -1) {# begin the templated script for 'default' profiles to reset state #} {% if 'default' in profile_name %} # set power state transition heuristics to default echo '{{ item.0.value.pwrmode }}' | tee /sys/class/drm/"${CARD}"/device/pp_power_profile_mode # set control mode back to auto # attempts to dynamically set optimal power profile for (load) conditions echo 'auto' | tee /sys/class/drm/"${CARD}"/device/power_dpm_force_performance_level # reset any existing profile clock changes echo 'r' | tee /sys/class/drm/"${CARD}"/device/pp_od_clk_voltage # give '{{ profile_name }}' profile ~{{ profile_percentage }}% (rounded) of the max power capability # {{ profile_watts }} Watts of {{ board_watts }} total echo '{{ profile_microwatts | int }}' | tee '{{ powercap_set.files.0.path }}' {% else %} {# begin the templated script for non-default AMD GPU profiles, eg: 'VR' or '3D_FULL_SCREEN' #} # set manual control mode # allows control via 'pp_dpm_mclk', 'pp_dpm_sclk', 'pp_dpm_pcie', 'pp_dpm_fclk', and 'pp_power_profile_mode' files # only interested in 'pp_power_profile_mode' for power and 'pp_dpm_mclk' for memory clock (flickering). # GPU clocks are dynamic based on (load) condition echo 'manual' | tee /sys/class/drm/"${CARD}"/device/power_dpm_force_performance_level # set power state transition heuristics to '{{ profile_name }}' profile echo '{{ item.0.value.pwrmode }}' | tee /sys/class/drm/"${CARD}"/device/pp_power_profile_mode # give '{{ profile_name }}' profile ~{{ profile_percentage }}% (rounded) of the max power capability # {{ profile_watts }} Watts of {{ board_watts }} total echo '{{ profile_microwatts | int }}' | tee '{{ powercap_set.files.0.path }}' # set the minimum GPU clock echo 's 0 {{ gpu_clock_min }}' | tee /sys/class/drm/"${CARD}"/device/pp_od_clk_voltage # set the maximum GPU clock echo 's 1 {{ gpu_clock_max }}' | tee /sys/class/drm/"${CARD}"/device/pp_od_clk_voltage # set the maximum GPU *memory* clock echo 'm 1 {{ gpumem_clock_static }}' | tee /sys/class/drm/"${CARD}"/device/pp_od_clk_voltage {% if gpu_mv_offset is defined %} # offset GPU voltage {{ gpu_mv_offset }}mV echo 'vo {{ gpu_mv_offset }}' | tee /sys/class/drm/"${CARD}"/device/pp_od_clk_voltage {% endif %} # commit the changes echo 'c' | tee /sys/class/drm/"${CARD}"/device/pp_od_clk_voltage # force GPU memory into highest clock (fix flickering) # pp_dpm_*clk settings are unintuitive, giving profiles that may be used # opt not to set the others (eg: sclk/fclk) - those should remain for benefits from the curve echo '3' | tee /sys/class/drm/"${CARD}"/device/pp_dpm_mclk {% endif %}