initial commit

This commit is contained in:
2017-07-26 18:44:22 -07:00
commit e28a331c04
4 changed files with 333 additions and 0 deletions

19
LICENSE Normal file
View File

@@ -0,0 +1,19 @@
Copyright © 2017 Scott Alfter
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

123
README.md Normal file
View File

@@ -0,0 +1,123 @@
nvOC MiningPoolHub Switcher
===========================
nvOC makes it easy to squeeze more hashrate out of your GPUs. MiningPoolHub
makes it easy to mine altcoins and get paid in Bitcoin. However, nvOC is a
customized Ubuntu Linux and the management software MiningPoolHub recommends
for profit switching only runs under Windows. Their approach to
coin-switching with nVidia GPUs under Linux is to loop through a bunch of
different miners, erroring out on all but the currently-profitable coin. I
lost nearly four hours this morning when a miner didn't exit properly during
a switch.
This set of scripts bridges the gap. With them, you can use the miners
included in nvOC (and others that you might add) to mine whatever's most
profitable at MiningPoolHub. For each supported algorithm, you can
customize power, clockspeed, and fan speed settings as you consider
appropriate.
Setup
-----
1. ssh into your mining rig's m1 account.
2. Clone these files into the same directory as nvOC's oneBash script.
3. Disable oneBash by commenting out all lines in ~/2unix. oneBash should
be invoked manually if you add/remove GPUs so it can reconfigure
/etc/X11/xorg.conf, but it otherwise isn't used. To keep gnome-terminal
from sucking down CPU cycles by constantly restarting the 2unix script, you
might want to include something like "sleep 86400" at the end.
4. Edit mph_conf.json. You'll set your user and miner names here. You can
also customize your overclocking settings for each algorithm here.
5. If your network is IPv6-enabled, note that nvOC (as of v17) has a problem
connecting to IPv6 hosts. MiningPoolHub makes its API available over both IPv6
and IPv4, so to force it to use IPv4 in the meantime, edit /etc/hosts as
follows:
`104.27.168.52 miningpoolhub.com`
6. Set mph_switch.py to launch with a cronjob:
`0,10,20,30,40,50 * * * * (cd /media/m1/1263-A96E && python2.7 mph_switch.py mph_conf.json)`
Every 10 minutes, the script will run and determine which miner needs to
start up. If it's already running, it will leave it alone. If it needs to
switch, it kills one miner and starts the other. If nothing's running
(because the rig just rebooted or the miner crashed), it will start the
miner.
current-profit is a text file that will be updated on every run of switch.py
to show which is currently the most profitable. Profitability is determined
by the MiningPoolHub API and is a unitless number; higher is better.
algo-log is a list of coins and algorithms the switcher has selected when
run. If you start seeing repeats of the same algo every 10 minutes, that's
a sign that something has gone wrong with your GPUs and you might want to
consider a reboot.
Miners are started in Screen sessions (http://www.gnu.org/software/screen)
that can be viewed over an ssh login session:
`screen -dr miner`
When the rig switches algorithms, the Screen session will be closed and a
new one opened. Repeat the above to monitor it, or you could use something
like this on a monitoring workstation:
`while true; do screen -dr miner; done`
Adding Algorithms
-----------------
Some algorithms supported by MiningPoolHub can't be mined with the miners
included in nvOC. If you add the appropriate software, though, you can mine
these as well. Instructions to add these capabilities will follow.
Sia
---
To add the miner:
`sudo apt install golang-go
mkdir /home/m1/gocode
GOPATH=/home/m1/gocode go get github.com/robvanmieghem/gominer`
To enable mining, create a new object named "sia" within the "miners"
list in mph_conf.json. Here's what I use:
```
"miners":
{
[existing entries deleted for brevity]
"Sia":
{
"bin": "/home/m1/SPccminer/ccminer -a sia -o stratum+tcp://{HOST}:{PORT} -u {NAME}.{MINER} -p x",
"power_limit": [115,115,95], "gpu_oc": [-100,-100,0], "mem_oc": 0, "fan": [70,75,70]
}
}
```
CryptoNight
-----------
To add the miner:
`cd /home/m1
git clone https://github.com/KlausT/ccminer-cryptonight KTccminer-cryptonight
cd KTccminer-cryptonight
./autoreconf.sh
./configure --with-cuda-/usr/local/cuda-8.0
make`
To enable mining, create a new object named "cryptonight" within the "miners"
list in mph_conf.json. Here's what I use:
```
"miners":
{
[existing entries deleted for brevity]
"Cryptonight":
{
"bin": "/home/m1/KTccminer-cryptonight/ccminer -a cryptonight -o stratum+tcp://{HOST}:{PORT} -u {NAME}.{MINER} -p x",
"power_limit": [115,115,95], "gpu_oc": -200, "mem_oc": 1000, "fan": [70,75,70]
}
}
```

68
mph_conf.json Normal file
View File

@@ -0,0 +1,68 @@
{
"user_name": "salfter",
"miner_name": "miner10",
"card_type": "nvidia",
"miners":
{
"Blake-Vanilla":
{
"bin": "/home/m1/SPccminer/ccminer -a vanilla -o stratum+tcp://{HOST}:{PORT} -u {NAME}.{MINER} -p x",
"power_limit": [115,115,95], "gpu_oc": [-100,-100,0], "mem_oc": 0, "fan": [70,75,70]
},
"Equihash":
{
"bin": "/home/m1/zec/v3_4/miner --eexit 3 --fee 0 --pec --server {HOST} --user {NAME}.{MINER} --pass z --port {PORT}",
"power_limit": [115,115,95], "gpu_oc": [-100,-100,0], "mem_oc": 0, "fan": [70,75,70]
},
"Ethash":
{
"bin": "/home/m1/eth/Genoil-U/ethminer -S {HOST}:{PORT} -O {NAME}.{MINER}:x -U",
"power_limit": [115,115,95], "gpu_oc": -200, "mem_oc": 1000, "fan": [70,75,70]
},
"Groestl":
{
"bin": "/home/m1/SPccminer/ccminer -a groestl -o stratum+tcp://{HOST}:{PORT} -u {NAME}.{MINER} -p x",
"power_limit": [115,115,95], "gpu_oc": [-100,-100,0], "mem_oc": 0, "fan": [70,75,70]
},
"Keccak":
{
"bin": "/home/m1/SPccminer/ccminer -a keccak -o stratum+tcp://{HOST}:{PORT} -u {NAME}.{MINER} -p x",
"power_limit": [115,115,95], "gpu_oc": [-100,-100,0], "mem_oc": 0, "fan": [70,75,70]
},
"Lyra2RE2":
{
"bin": "/home/m1/SPccminer/ccminer -a lyra2v2 -o stratum+tcp://{HOST}:{PORT} -u {NAME}.{MINER} -p x",
"power_limit": [115,115,95], "gpu_oc": [-100,-100,0], "mem_oc": 0, "fan": [70,75,70]
},
"Myriad-Groestl":
{
"bin": "/home/m1/SPccminer/ccminer -a myr-gr -o stratum+tcp://{HOST}:{PORT} -u {NAME}.{MINER} -p x",
"power_limit": [115,115,95], "gpu_oc": [-100,-100,0], "mem_oc": 0, "fan": [70,75,70]
},
"NeoScrypt":
{
"bin": "/home/m1/SPccminer/ccminer -a neoscrypt -o stratum+tcp://{HOST}:{PORT} -u {NAME}.{MINER} -p x",
"power_limit": [115,115,95], "gpu_oc": [-100,-100,0], "mem_oc": 0, "fan": [70,75,70]
},
"Qubit":
{
"bin": "/home/m1/SPccminer/ccminer -a qubit -o stratum+tcp://{HOST}:{PORT} -u {NAME}.{MINER} -p x",
"power_limit": [115,115,95], "gpu_oc": [-100,-100,0], "mem_oc": 0, "fan": [70,75,70]
},
"Scrypt":
{
"bin": "/home/m1/SPccminer/ccminer -a scrypt -o stratum+tcp://{HOST}:{PORT} -u {NAME}.{MINER} -p x",
"power_limit": [115,115,95], "gpu_oc": [-100,-100,0], "mem_oc": 0, "fan": [70,75,70]
},
"Skein":
{
"bin": "/home/m1/SPccminer/ccminer -a skein -o stratum+tcp://{HOST}:{PORT} -u {NAME}.{MINER} -p x",
"power_limit": [115,115,95], "gpu_oc": [-100,-100,0], "mem_oc": 0, "fan": [70,75,70]
},
"X11":
{
"bin": "/home/m1/SPccminer/ccminer -a x11 -o stratum+tcp://{HOST}:{PORT} -u {NAME}.{MINER} -p x",
"power_limit": [115,115,95], "gpu_oc": [-100,-100,0], "mem_oc": 0, "fan": [70,75,70]
}
}
}

123
mph_switch.py Normal file
View File

@@ -0,0 +1,123 @@
#!/usr/bin/env python2.7
import pprint
import json
import urllib2
import sys
import datetime
import time
import subprocess
import os
# load config
cfg=json.loads(open(sys.argv[1]).read())
card_type=cfg["card_type"]
miners=cfg["miners"]
user_name=cfg["user_name"]
miner_name=cfg["miner_name"]
os.environ["DISPLAY"]=":0"
# grab something from a website
def fetch(url):
r=urllib2.Request(url)
r.add_header("User-Agent", "Lynx/2.8.8dev.3 libwww-FM/2.14 SSL-MM/1.4.1")
r.add_header("Pragma", "no-cache")
return urllib2.build_opener().open(r).read()
# main
data=json.loads(fetch("http://miningpoolhub.com/?page=api&action=getminingandprofitsstatistics"))["return"]
coins={}
for i in reversed(data): # weed out unconfigured algos, do string substitutions
try:
miner=miners[i["algo"]]
coins[i["coin_name"]]=miner["bin"].format(HOST=i["host"], PORT=str(i["port"]), NAME=user_name, MINER=miner_name)
except:
data.remove(i)
sort={}
for i in data:
sort[i["coin_name"]+" ("+i["algo"]+")"]=i["normalized_profit_"+card_type]
sort=sorted(sort.items(), key=lambda x:x[1], reverse=True)
log=open("current-profit", "w")
for i in sort:
log.write(i[0]+": "+str(i[1])+"\n")
log.close()
max_profit_val=0 # find the most profitable coin
for i in data:
if i["normalized_profit_"+card_type]>max_profit_val:
max_profit=i
max_profit_val=i["normalized_profit_"+card_type]
miner=miners[max_profit["algo"]]
coin=coins[max_profit["coin_name"]]
# see if miner's already running
try:
subprocess.check_output(["pgrep", "-f", "^"+coin.replace("+", "\\+")])
current=1
except:
current=0
if (current==0):
other=0
for algo in coins:
try:
subprocess.check_output(["pgrep", "-f", "^"+coins[algo].replace("+", "\\+")])
other=1
except:
pass
if (current==0):
# log a change
algo_log=open("algo-log", "a")
algo_log.write(str(datetime.datetime.now())+": "+max_profit["coin_name"]+" ("+max_profit["algo"]+")\n")
algo_log.close()
if (other==1):
# kill existing miners
for algo in coins:
subprocess.call(["pkill", "-f", "^"+coins[algo].replace("+", "\\+")])
time.sleep(3)
if card_type=="nvidia": # update card settings
cards=int(subprocess.check_output("nvidia-smi --query-gpu=count --format=csv,noheader,nounits".split(" ")).split("\n")[-2])
for i in range(0, cards):
# power limit
if type(miner["power_limit"]) is int:
subprocess.call(("sudo nvidia-smi -i "+str(i)+" -pl "+str(miner["power_limit"])).split(" "))
else:
subprocess.call(("sudo nvidia-smi -i "+str(i)+" -pl "+str(miner["power_limit"][i])).split(" "))
# core overclock
if type(miner["gpu_oc"]) is int:
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUGraphicsClockOffset[2]="+str(miner["gpu_oc"])).split(" "))
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUGraphicsClockOffset[3]="+str(miner["gpu_oc"])).split(" "))
else:
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUGraphicsClockOffset[2]="+str(miner["gpu_oc"][i])).split(" "))
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUGraphicsClockOffset[3]="+str(miner["gpu_oc"][i])).split(" "))
# memory overclock
if type(miner["mem_oc"]) is int:
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUMemoryTransferRateOffset[2]="+str(miner["mem_oc"])).split(" "))
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUMemoryTransferRateOffset[3]="+str(miner["mem_oc"])).split(" "))
else:
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUMemoryTransferRateOffset[2]="+str(miner["mem_oc"][i])).split(" "))
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUMemoryTransferRateOffset[3]="+str(miner["mem_oc"][i])).split(" "))
# fan speed
if type(miner["fan"]) is int:
if (miner["fan"]==0):
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUFanControlState=0").split(" "))
else:
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUFanControlState=1").split(" "))
subprocess.call(("nvidia-settings -a [fan:"+str(i)+"]/GPUTargetFanSpeed="+str(miner["fan"])).split(" "))
else:
if (miner["fan"][i]==0):
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUFanControlState=0").split(" "))
else:
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUFanControlState=1").split(" "))
subprocess.call(("nvidia-settings -a [fan:"+str(i)+"]/GPUTargetFanSpeed="+str(miner["fan"][i])).split(" "))
# launch new miner
subprocess.call(("screen -dmS miner "+coin).split(" "))