|
| 1 | +#!/bin/bash |
| 2 | + |
| 3 | +# Copyright © 2020 Teal Dulcet |
| 4 | +# wget -qO - https://raw.github.com/tdulcet/Distributed-Computing-Scripts/master/prpll.sh | bash -s -- |
| 5 | +# ./prpll.sh [PrimeNet User ID] [Computer name] [Type of work] [Idle time to run (mins)] |
| 6 | +# ./prpll.sh "$USER" "$HOSTNAME" 150 10 |
| 7 | +# ./prpll.sh ANONYMOUS |
| 8 | + |
| 9 | +set -e |
| 10 | + |
| 11 | +DIR="prpll" |
| 12 | +BRANCH=master |
| 13 | +if [[ $# -gt 4 ]]; then |
| 14 | + echo "Usage: $0 [PrimeNet User ID] [Computer name] [Type of work] [Idle time to run (mins)]" >&2 |
| 15 | + exit 1 |
| 16 | +fi |
| 17 | +USERID=${1:-$USER} |
| 18 | +COMPUTER=${2:-$HOSTNAME} |
| 19 | +TYPE=${3:-150} |
| 20 | +TIME=${4:-10} |
| 21 | +DEVICE=0 |
| 22 | +RE='^1(0[01246]|5[01235])$' |
| 23 | +if ! [[ $TYPE =~ $RE ]]; then |
| 24 | + echo "Usage: [Type of work] must be a number" >&2 |
| 25 | + exit 1 |
| 26 | +fi |
| 27 | +RE='^([0-9]*\.)?[0-9]+$' |
| 28 | +if ! [[ $TIME =~ $RE ]]; then |
| 29 | + echo "Usage: [Idle time to run] must be a number" >&2 |
| 30 | + exit 1 |
| 31 | +fi |
| 32 | +echo -e "PrimeNet User ID:\t$USERID" |
| 33 | +echo -e "Computer name:\t\t$COMPUTER" |
| 34 | +echo -e "Type of work:\t\t$TYPE" |
| 35 | +echo -e "Idle time to run:\t$TIME minutes\n" |
| 36 | +if [[ -e idletime.sh ]]; then |
| 37 | + bash -- idletime.sh |
| 38 | +else |
| 39 | + wget -qO - https://raw.github.com/tdulcet/Distributed-Computing-Scripts/master/idletime.sh | bash -s |
| 40 | +fi |
| 41 | +if [[ -d $DIR ]]; then |
| 42 | + echo "Error: PRPLL is already downloaded" >&2 |
| 43 | + exit 1 |
| 44 | +fi |
| 45 | +GPU=$(lspci | grep -i 'vga\|3d\|2d') |
| 46 | +if ! echo "$GPU" | grep -iq 'amd\|nvidia\|intel'; then |
| 47 | + echo -e "Please enter your password if prompted.\n" |
| 48 | + sudo update-pciids |
| 49 | + GPU=$(lspci | grep -i 'vga\|3d\|2d') |
| 50 | + if ! echo "$GPU" | grep -iq 'amd\|nvidia\|intel'; then |
| 51 | + echo "$GPU" | sed -n 's/^.*: //p' |
| 52 | + echo "Error: This computer does not have an AMD, Nvidia or Intel GPU" >&2 |
| 53 | + exit 1 |
| 54 | + fi |
| 55 | +fi |
| 56 | +if command -v clinfo >/dev/null; then |
| 57 | + if [[ $(clinfo --raw | sed -n 's/^#PLATFORMS *//p') -eq 0 ]]; then |
| 58 | + clinfo |
| 59 | + echo "Error: This computer does not have an OpenCL platform" >&2 |
| 60 | + exit 1 |
| 61 | + fi |
| 62 | +fi |
| 63 | +if ! command -v make >/dev/null || ! command -v g++ >/dev/null; then |
| 64 | + echo -e "Installing Make and the GNU C++ compiler" |
| 65 | + echo -e "Please enter your password if prompted.\n" |
| 66 | + sudo apt-get update -y |
| 67 | + sudo apt-get install -y build-essential |
| 68 | +fi |
| 69 | +if [[ -n $CXX ]] && ! command -v "$CXX" >/dev/null; then |
| 70 | + echo "Error: $CXX is not installed." >&2 |
| 71 | + exit 1 |
| 72 | +fi |
| 73 | +CXX=${CXX:-g++} |
| 74 | +VERSION=$("$CXX" -dumpversion) |
| 75 | +RE='^g\+\+' |
| 76 | +if [[ $CXX =~ $RE && ${VERSION%%.*} -lt 8 ]]; then |
| 77 | + echo "Error: PRPLL requires at least the GNU C++ compiler 8 and you have $VERSION" >&2 |
| 78 | + exit 1 |
| 79 | +fi |
| 80 | +if ! command -v python3 >/dev/null; then |
| 81 | + echo "Error: Python 3 is not installed." >&2 |
| 82 | + exit 1 |
| 83 | +fi |
| 84 | +if ! ldconfig -p | grep -iq 'libOpenCL\.'; then |
| 85 | + echo -e "Installing the OpenCL library" |
| 86 | + echo -e "Please enter your password if prompted.\n" |
| 87 | + sudo apt-get update -y |
| 88 | + # sudo apt-get install -y ocl-icd-* opencl-headers clinfo |
| 89 | + sudo apt-get install -y ocl-icd-opencl-dev clinfo |
| 90 | +fi |
| 91 | +TIME=$(echo "$TIME" | awk '{ printf "%g", $1 * 60 }') |
| 92 | +if command -v git >/dev/null; then |
| 93 | + echo -e "Downloading PRPLL\n" |
| 94 | + git clone https://github.com/gwoltman/gpuowl.git "$DIR" |
| 95 | + cd "$DIR" |
| 96 | + git remote add upstream https://github.com/preda/gpuowl.git |
| 97 | + git fetch upstream |
| 98 | + sed -i 's/--dirty //' Makefile |
| 99 | + sed -i 's/ --match v\/prpll\/\*//' Makefile |
| 100 | +else |
| 101 | + echo -e "Downloading PRPLL\n" |
| 102 | + wget https://github.com/gwoltman/gpuowl/archive/$BRANCH.tar.gz |
| 103 | + echo -e "\nDecompressing the files\n" |
| 104 | + tar -xzvf $BRANCH.tar.gz |
| 105 | + mv -v gpuowl-$BRANCH/ "$DIR"/ |
| 106 | + cd "$DIR" |
| 107 | + if output=$(curl -sf 'https://api.github.com/repos/gwoltman/gpuowl/tags?per_page=1'); then |
| 108 | + if command -v jq >/dev/null; then |
| 109 | + name=$(echo "$output" | jq -r '.[0].name') |
| 110 | + else |
| 111 | + name=$(echo "$output" | python3 -c 'import sys, json; print(json.load(sys.stdin)[0]["name"])') |
| 112 | + fi |
| 113 | + if output=$(curl -sf "https://api.github.com/repos/gwoltman/gpuowl/compare/$BRANCH...$name"); then |
| 114 | + if command -v jq >/dev/null; then |
| 115 | + behind_by=$(echo "$output" | jq '.behind_by') |
| 116 | + sha=$(echo "$output" | jq -r '.base_commit.sha') |
| 117 | + else |
| 118 | + behind_by=$(echo "$output" | python3 -c 'import sys, json; print(json.load(sys.stdin)["behind_by"])') |
| 119 | + sha=$(echo "$output" | python3 -c 'import sys, json; print(json.load(sys.stdin)["base_commit"]["sha"])') |
| 120 | + fi |
| 121 | + fi |
| 122 | + sed -i 's/\\`git describe --tags --long --dirty --always --match v\/prpll\/\*\\`/'"${name}${behind_by:+-${behind_by}${sha:+-g${sha::7}}}"'/' Makefile |
| 123 | + fi |
| 124 | +fi |
| 125 | +DIR=$PWD |
| 126 | +echo -e "\nDownloading AutoPrimeNet\n" |
| 127 | +if [[ -e ../autoprimenet.py ]]; then |
| 128 | + cp -v ../autoprimenet.py . |
| 129 | +else |
| 130 | + wget -nv https://raw.github.com/tdulcet/AutoPrimeNet/main/autoprimenet.py |
| 131 | +fi |
| 132 | +chmod +x autoprimenet.py |
| 133 | +python3 -OO -m py_compile autoprimenet.py |
| 134 | +echo -e "\nInstalling the Requests library\n" |
| 135 | +# python3 -m ensurepip --default-pip || true |
| 136 | +python3 -m pip install --upgrade pip || true |
| 137 | +if ! python3 -m pip install requests; then |
| 138 | + if command -v pip3 >/dev/null; then |
| 139 | + pip3 install requests |
| 140 | + else |
| 141 | + echo -e "\nWarning: Python pip3 is not installed and the Requests library may also not be installed\n" |
| 142 | + fi |
| 143 | +fi |
| 144 | +echo -e "\nSetting up PRPLL\n" |
| 145 | +echo "-user $USERID -cpu ${COMPUTER//[[:space:]]/_}" >config.txt |
| 146 | +sed -i 's/^CXX =/CXX ?=/' Makefile |
| 147 | +# -funsafe-math-optimizations |
| 148 | +sed -i 's/-O2/-Wall -g -O3 -flto -ffinite-math-only/' Makefile |
| 149 | +make -j "$(nproc)" |
| 150 | +# make clean |
| 151 | +pushd build-release >/dev/null |
| 152 | +rm -- *.o |
| 153 | +mv -v prpll .. |
| 154 | +popd >/dev/null |
| 155 | +echo -e "\nRegistering computer with PrimeNet\n" |
| 156 | +ARGS=() |
| 157 | +if command -v clinfo >/dev/null; then |
| 158 | + clinfo=$(clinfo --raw) |
| 159 | + mapfile -t GPU < <(echo "$clinfo" | sed -n 's/.*CL_DEVICE_NAME *//p') |
| 160 | + ARGS+=(--cpu-model="${GPU[DEVICE]//\[*\]/}") |
| 161 | + |
| 162 | + mapfile -t GPU_FREQ < <(echo "$clinfo" | sed -n 's/.*CL_DEVICE_MAX_CLOCK_FREQUENCY *//p') |
| 163 | + ARGS+=(--frequency="${GPU_FREQ[DEVICE]}") |
| 164 | + |
| 165 | + mapfile -t TOTAL_GPU_MEM < <(echo "$clinfo" | sed -n 's/.*CL_DEVICE_GLOBAL_MEM_SIZE *//p') |
| 166 | + maxAlloc=$((TOTAL_GPU_MEM[DEVICE] >> 20)) |
| 167 | + ARGS+=(--memory="$maxAlloc" --max-memory="$(echo "$maxAlloc" | awk '{ printf "%d", $1 * 0.9 }')") |
| 168 | +elif command -v nvidia-smi >/dev/null && nvidia-smi >/dev/null; then |
| 169 | + mapfile -t GPU < <(nvidia-smi --query-gpu=gpu_name --format=csv,noheader) |
| 170 | + ARGS+=(--cpu-model="${GPU[DEVICE]}") |
| 171 | + |
| 172 | + mapfile -t GPU_FREQ < <(nvidia-smi --query-gpu=clocks.max.gr --format=csv,noheader,nounits | grep -iv 'not supported') |
| 173 | + if [[ -n $GPU_FREQ ]]; then |
| 174 | + ARGS+=(--frequency="${GPU_FREQ[DEVICE]}") |
| 175 | + fi |
| 176 | + |
| 177 | + mapfile -t TOTAL_GPU_MEM < <(nvidia-smi --query-gpu=memory.total --format=csv,noheader,nounits | grep -iv 'not supported') |
| 178 | + if [[ -n $TOTAL_GPU_MEM ]]; then |
| 179 | + maxAlloc=${TOTAL_GPU_MEM[DEVICE]} |
| 180 | + ARGS+=(--memory="$maxAlloc" --max-memory="$(echo "$maxAlloc" | awk '{ printf "%d", $1 * 0.9 }')") |
| 181 | + fi |
| 182 | +fi |
| 183 | +python3 -OO autoprimenet.py -t 0 -T "$TYPE" -u "$USERID" --prpll -H "$COMPUTER" "${ARGS[@]}" |
| 184 | +echo -e "\nStarting AutoPrimeNet\n" |
| 185 | +nohup python3 -OO autoprimenet.py >>'autoprimenet.out' & |
| 186 | +sleep 1 |
| 187 | +echo -e "\nTuning PRPLL for your computer and GPU\nThis may take a while…\n" |
| 188 | +time ./prpll -device $DEVICE -tune minexp=0 |
| 189 | +sed -i '/-log/ s/^/# /' config.txt |
| 190 | +echo -e "\nStarting PRPLL\n" |
| 191 | +nohup ./prpll -device $DEVICE >>"prpll.out" & |
| 192 | +sleep 1 |
| 193 | +#crontab -l | { cat; echo "@reboot cd ${DIR@Q} && nohup ./prpll -device $DEVICE >> 'prpll.out' &"; } | crontab - |
| 194 | +#crontab -l | { cat; echo "@reboot cd ${DIR@Q} && nohup python3 -OO autoprimenet.py >> 'autoprimenet.out' &"; } | crontab - |
| 195 | +cat <<EOF >prpll.sh |
| 196 | +#!/bin/bash |
| 197 | +
|
| 198 | +# Copyright © 2020 Teal Dulcet |
| 199 | +# Start PRPLL and AutoPrimeNet if the computer has not been used in the specified idle time and stop it when someone uses the computer |
| 200 | +# ${DIR@Q}/prpll.sh |
| 201 | +
|
| 202 | +NOW=\${EPOCHSECONDS:-\$(date +%s)} |
| 203 | +
|
| 204 | +if who -s | awk '{ print \$2 }' | (cd /dev && xargs -r stat -c '%U %X') | awk '{if ('"\$NOW"'-\$2<$TIME) { print \$1"\t"'"\$NOW"'-\$2; ++count }} END{if (count>0) { exit 1 }}' >/dev/null; then |
| 205 | + pgrep -x prpll >/dev/null || (cd ${DIR@Q} && exec nohup ./prpll -device $DEVICE >>'prpll.out' &) |
| 206 | + pgrep -f '^python3 -OO autoprimenet\.py' >/dev/null || (cd ${DIR@Q} && exec nohup python3 -OO autoprimenet.py >>'autoprimenet.out' &) |
| 207 | +else |
| 208 | + pgrep -x prpll >/dev/null && killall -g -INT prpll |
| 209 | +fi |
| 210 | +EOF |
| 211 | +chmod +x prpll.sh |
| 212 | +echo -e "\nRun this command for it to start if the computer has not been used in the specified idle time and stop it when someone uses the computer:\n" |
| 213 | +echo "crontab -l | { cat; echo \"* * * * * ${DIR@Q}/prpll.sh\"; } | crontab -" |
| 214 | +echo -e "\nTo edit the crontab, run \"crontab -e\"" |
0 commit comments