Скрипт контроля частот и вентиляторов видеокарт AMD Radeon

Материал из Linux Wiki
Перейти к навигацииПерейти к поиску

Данный скрипт предназначен для управления частотами и вентиляторами в ригах на базе видеокарт AMD Radeon. Помимо управления, скрипт выводит текущее состояние карт. Если доступно API sgminer (или подобного майнера с такой же структурой вывода данных), то используются его данные и управление отдается ему, а скрипт просто выводит статистику.

ToDo: Дописать
ToDo: В setfreqs $i лишняя. Убрать и/или переделать на возможность указания определенной карты

#!/bin/bash

tt1='65'
tt2='70'
toh='80'
tco='85'
hyst='1'

fmin='15'
tfan='60'
fmax='100'

sleep='5'

corelow='800'
memlow='1000'

conf='/home/rain/config/cards.conf'

[ ! -z "${NOAPI}" ] && cmd="false :"

showdate() {
    echo -ne "\e[0;36m[\e[0;35m"$(date +%Y-%m-%d" "%H:%M:%S)"\e[0;36m]\e[0;0m "
}

do_halt() {
        /home/rain/bin/gpuoff 1>/dev/null 2>/dev/null
        /home/rain/bin/ethminerctl suspend
        pkill -9 Hashcat
}

sayto() {
    (cat - ; echo -n " on $(hostname)") | sendxmpp -t rain@jabberworld.info
}

getcoreconf(){
        awk '/gpu-engine/{
                        gsub(/[0-9]+\-|\"/, "", $3)
                        split($3, core, ",")
                        c='$1'+1
                        print core[c]
                }' "${conf}"
}

getmemconf(){
        awk '/gpu-memclock/{
                        gsub(/[0-9]+\-|\"/, "", $3)
                        split($3, mem, ",")
                        c='$1'+1
                        print mem[c]
                }' "${conf}"
}

setfreqs() {
for i in $(seq 0 $(($(aticonfig --lsa | grep -c '[0-9]\.')-1)))
        do
                aticonfig --od-enable 1>/dev/null

                core="$(getcoreconf "${i}")"
                [ -z "${core}" ] && core="$(getcoreconf 0)"

                mem="$(getmemconf "${i}")"
                [ -z "${mem}" ] && core="$(getmemconf 0)"

                [[ ! -z "${core}" && ! -z "${mem}" ]] && {
                        aticonfig --od-setclocks=$core,$mem --adapter=$i 1>/dev/null
                        freqs[$1]='1'
                }
        done
}

case "${1}" in
        freqs)
                                setfreqs $i
        ;;
        *)

        while :
                do
        $cmd nc -w 1 -z localhost 4028 && {
        api='1'
        ffci='0'
        devdata="$(/home/rain/bin/api-example.py devs | sed -r 's/, |\{|\}/\n/g;s/(\n)u|'\''/\1/g')"
        } || {
        api='0'

        [ "${ffci}" != '1' ] && {
#       init fan array
        for j in $(seq 0 $(($(aticonfig --lsa | grep -c '[0-9]\.')-1)))
                do
                fan[$j]="$(DISPLAY=:0.$j aticonfig --pplib-cmd "get fanspeed 0" | awk '/Result/{gsub(/%/, "", $4); print $4}')"
        done

        setfreqs

        ffci='1'
        }

                        atidata="$(aticonfig --odgt --odgc --adapter=all 2>/dev/null)"

# fans
                        for cdat in $(echo "${atidata}" | sed -nr '/Adapter/N;s/Adapter ([0-9]+).*\n.*Sensor.* - ([0-9]+)\.[0-9]+ C/\1:\2/gp')
                                do
                                        cn="${cdat%:*}"
                                        ct="${cdat#*:}"

                                        [ "${ct}" -ge "${tco}" ] && {
                                                # halt mining
                                                DISPLAY=:0.$cn aticonfig --pplib-cmd "set fanspeed 0 ${fmax}" 1>/dev/null
#                                               showdate  >> /tmp/ffc.log
                                                echo -n "ALERT! Critical temperature ($ct) on $cn" | sayto
                                                do_halt
                                        }

                                        [[ "${ct}" -ge "${toh}" && "${ct}" -lt "${tco}" ]] && {
                                                # reduce freqs
                                                [ "${freqs[$cn]}" == '1' ] && {
#                                                       showdate >> /tmp/ffc.log
#                                                       echo "GPU $cn overheat, reducing clocks" >> /tmp/ffc.log

                                                        echo -n "GPU $cn overheat, reducing clocks" | sayto
                                                        freqs[$cn]='2'
                                                        aticonfig --od-setclocks=$corelow,$memlow --adapter=$cn 1>/dev/null
                                                        DISPLAY=:0.$cn aticonfig --pplib-cmd "set fanspeed 0 ${fmax}" 1>/dev/null
                                                }
                                        }

                                        [[ "${ct}" -gt "$((${tt2}+${hyst}))" && "${ct}" -lt "$((${toh}-${hyst}))" ]] && {
                                                # allow fans to 100%
                                                [ "${freqs[$cn]}" == '2' ] && {
                                                        setfreqs "${cn}"
                                                }

                                                [ "${fan[$cn]}" -lt "${fmax}" ] && {
#                                                       old="${fan[$cn]}"
                                                        let fan[$cn]+=5
                                                        [ "${fan[$cn]}" -gt "${fmax}" ] && fan[$cn]="${fmax}"
#                                                       showdate  >> /tmp/ffc.log
#                                                       echo "GPU ${cn} $ct: setting fan $old -> ${fan[$cn]}"  >> /tmp/ffc.log
                                                        DISPLAY=:0.$cn aticonfig --pplib-cmd "set fanspeed 0 ${fan[$cn]}" 1>/dev/null
                                                }
                                        }

                                        [[ "${ct}" -gt "$((${tt1}+${hyst}))" && "${ct}" -lt "$((${tt2}-${hyst}))" ]] && {
                                                # allow fans to $tfan
                                                [ "${freqs[$cn]}" == '2' ] && {
                                                        setfreqs "${cn}"
                                                }

                                                [ "${fan[$cn]}" -lt "${tfan}" ] && {
#                                                       old="${fan[$cn]}"
                                                        let fan[$cn]+=2
                                                        [ "${fan[$cn]}" -gt "${tfan}" ] && fan[$cn]="${tfan}"
#                                                       showdate  >> /tmp/ffc.log
#                                                       echo "GPU ${cn} $ct: setting fan $old -> ${fan[$cn]}"  >> /tmp/ffc.log
                                                        DISPLAY=:0.$cn aticonfig --pplib-cmd "set fanspeed 0 ${fan[$cn]}" 1>/dev/null
                                                }
                                        }


                                        [ "${ct}" -lt "$((${tt1}-${hyst}))" ] && {
                                                # decrease fan speed
#                                               old="${fan[$cn]}"
                                                let fan[$cn]-=1
                                                [ "${fan[$cn]}" -lt "${fmin}" ] && fan[$cn]="${fmin}"
#                                               showdate  >> /tmp/ffc.log
#                                               echo "GPU ${cn} $ct: setting fan $old -> ${fan[$cn]}"  >> /tmp/ffc.log
                                                DISPLAY=:0.$cn aticonfig --pplib-cmd "set fanspeed 0 ${fan[$cn]}" 1>>/dev/null
                                        }


                        done

                        devdata="$((

                        for f in ${!fan[@]}
                                do
                                        echo "Fan Speed $f ${fan[$f]}"
                        done

                        echo "${atidata}"

                        ) | awk '

                                /^Adapter/{
                                        a=$2
                                        name=$0
                                        gsub(/^Adapter.* - /, "", name)
                                }

                                /Temp/{
                                        OFMT="%.f"
                                        temp[a]=$5+0
                                }

                                /Speed/{
                                        speed[$3]=$4
                                }

                                /Clocks/{
                                        core[a]=$4
                                        mem[a]=$5
                                }

                                /load/{
                                        load[a]=$4
                                        gsub(/%/, "", load[a])

                                        print "GPU: "a
                                        print "Devname: "name
                                        print "Temperature: " temp[a]
                                        print "Fan Percent: " speed[a]
                                        print "GPU Clock: " core[a]
                                        print "Memory Clock: " mem[a]
                                        print "GPU Activity: " load[a]
                                        print "Status: uAlive"
                                        print "Enabled: U"
                                        print "Utility"
                                        }
                        ')"
        }

                        data="$(echo -n "${devdata}" | gawk '

                                        function pbar(prog, min, max)
                                        {
                                                p=""
                                                if (min=="") min=10
                                                if (max=="") max=100
                                                inc=((max-min)/10)+0.1
                                                for (i=min; i<=max; i+=inc) {
                                                        if (i>prog) p=p" "
                                                                else p=p"|"
                                                }
                                                return p
                                        }

                                        /Temperature/{
                                                OFMT="%.f"
                                                temp=$2+0
                                                if (temp>79) ctemp="\\e[5;31m"
                                                        else
                                                                if (temp>69) ctemp="\\e[0;33m"
                                                                        else
                                                                                ctemp="\\e[0;32m"
                                        }

                                        /Fan Percent/{
                                                OFMT="%.f"
                                                fan=$3+0
                                                if (fan>75) cfan="\\e[31m"
                                                        else
                                                                if (fan>45) cfan="\\e[33m"
                                                                        else
                                                                                cfan="\\e[32m"
                                        }

                                        /GPU Activity/{
                                                act=$3
                                                if (act<80) cact="\\e[0;31m"
                                                        else
                                                                if (act<90) cact="\\e[0;33m"
                                                                        else
                                                                                cact="\\e[0;32m"
                                        }

                                        /GPU Clock/{
                                                core=$3
                                        }

                                        /Devname/{
                                                name=$0
                                                gsub(/Devname: /, " | ", name)
                                        }

                                        /Status/{
                                                stat=$2
                                                if (stat=="uAlive") stat="\\e[36m"
                                                        else stat="\\e[5;31m"
                                        }

                                        /Memory Clock/{
                                                mem=$3
                                        }

                                        /Enabled/{
                                                en=$2
                                                if (en=="uN") en="X"
                                                        else
                                                if (en=="U") en="U"
                                                        else en="Y"
                                        }

                                        /^GPU:/{
                                                gnum=$2
                                        }

                                        /Utility/{
                                                printf "%-67s %-47s %-12s %-61s %s\n",
                                                        stat en " GPU "gnum": \\e[0;32m["ctemp pbar(temp, 30, 85) "\\e[0m] " ctemp temp"C\\e[0m",
                                                        "| FAN: ["cfan pbar(fan)"\\e[0m] " cfan fan"% \\e[0m",
                                                        "| "core"/"mem,
                                                        "| Load: \\e[0;32m["cact pbar(act, 50, 99) "\\e[0m] " cact act"%\\e[0;0m",
                                                        name
                                        }'
                                        )"

                [ "${api}" == '1' ] &&\
                        data="\t\t\t=========== sgminer stat ===========\n${data}" ||\
                        data="\t\t\t=========== aticonfig stat ===========\n${data}"

                [ "${1}" == 'single' ] && {
                        echo -e "${data}"
                        break
                        } || {
                        clear
                        echo -e "${data}"
                        }

                sleep "${sleep}"
        done

        ;;
esac