def cleanup_workers(self, include_calibrators=False): self.poll() for miner_name in self.miners.keys(): for algorithm in self.miner_state[miner_name]['algorithms']: kill = True if not include_calibrators and len(algorithm['pools']) > 0: login = algorithm['pools'][0]['login'] user, password = login.split(':') if user[-5:] == 'CALIB': kill = False if kill: if len(algorithm['workers']) > 0: nvidia.Nvidia().set_default_profile( device.Device({ "id": int(algorithm['workers'][0]['device_id']) })) self.miners[miner_name].do_command( 'algorithm.remove', [str(algorithm['algorithm_id'])])
def stop_device(self, device, silent=False, i=0): if len(device.algos) < (i + 1): if not silent: device.log( 'warning', "request stop mining but device is inactive or requested algo doesn't exist" ) return True if not silent: device.log( 'info', 'stopping algorithm %s with %s' % (device.algos[i]['algo'], device.algos[i]['miner'])) if not self.miners[device.algos[i]['miner']].do_command( 'algorithm.remove', [str(device.algos[i]['algo_id'])]): return False nvidia.Nvidia().set_default_profile(device) del device.algos[i] device.state = 'inactive' device.changed = datetime.datetime.now() return True
def log_stats(self): if Config().get('stats.enable') and len(self.algos) > 0: if '_' in self.algos[0]['algo']: benchmarks = {self.algos[0]['algo']: self.algos[0]['hashrate']} else: benchmarks = { self.algos[0]['algo']: self.algos[0]['hashrate'][0] } pool = Pools().pools[self.algos[0]['pool']] if '_' in self.algos[0]['algo']: algo1, algo2 = self.algos[0]['algo'].split('_') gross_mbtc = pool.mbtc_per_day(benchmarks)[self.algos[0]['region']][algo1] + \ pool.mbtc_per_day(benchmarks)[self.algos[0]['region']][algo2] else: mbtc_per_day = pool.mbtc_per_day(benchmarks)[self.algos[0] ['region']] if self.algos[0]['algo'] in mbtc_per_day.keys(): gross_mbtc = mbtc_per_day[self.algos[0]['algo']] else: gross_mbtc = 0 match = re.match("^([\d\.]+)", self.power) if match: power = float(match.group(1)) margin = MinotaurGS().calculate_profit_margin_for_card( gross_mbtc, power) net_mbtc = (gross_mbtc / 100) * margin else: net_mbtc = 0 net_mbtc_s = "%.2f" % (net_mbtc) total_watts = nvidia.Nvidia().get_total_power_draw() if self.stat and self.stat['algo'] == self.algos[0][ 'algo'] and self.stat['pool'] == self.algos[0][ 'pool'] and self.stat['miner'] == self.algos[0][ 'miner'] and self.stat['region'] == self.algos[0][ 'region'] and self.stat[ 'net_mbtc'] == net_mbtc_s and self.stat[ 'power'] == self.power_f and self.stat[ 'total_power'] == total_watts: return Stats().add(self.id, self.dclass, self.algos[0]['pool'], self.algos[0]['miner'], self.algos[0]['algo'], self.algos[0]['region'], self.algos[0]['hashrate'], gross_mbtc, net_mbtc, self.power_f, total_watts) self.stat = { 'algo': self.algos[0]['algo'], 'pool': self.algos[0]['pool'], 'miner': self.algos[0]['miner'], 'region': self.algos[0]['region'], 'net_mbtc': net_mbtc_s, 'power': self.power_f, 'total_power': total_watts }
def apply_profile(self): profile = self.get_profile_for_algo() nvidia.Nvidia().set_profile(self, self.get_profile_for_algo())
def set_power_limit(self, watts): nvidia.Nvidia().set_power_limit(self, watts)
def update_metrics(self, metrics): for key in nvidia.Nvidia().metrics_keys(): setattr(self, key, getattr(metrics, key))
def start_device(self, device, silent=False): if device.grub: miner_name, algo, region, best_rate = Nicehash( ).get_best_miner_and_algorithm(device) pool_name = 'nicehash' elif device.pin: region = device.pin['region'] algo = device.pin['algorithm'] miner_name = device.pin['miner_name'] pool_name = device.pin['pool_name'] else: region = device.best_region algo = device.best_algo miner_name = device.best_miner pool_name = device.best_pool profile = device.get_profile_for_algo(algo) if not silent: if device.state == 'active' and len(device.algos) > 0: device.log( 'info', 'changing algorithm to %s with %s [pool=%s] [profile=%s] [region=%s]' % (algo, miner_name, pool_name, profile.name, region)) else: device.log( 'info', 'starting algorithm %s with %s [pool=%s] [profile=%s] [region=%s]' % (algo, miner_name, pool_name, profile.name, region)) pool = Pools().pools[pool_name] endpoints = pool.get_endpoints(algo, region) if device.grub: x = [ 1382, 1398, 1452, 1443, 1414, 1384, 1451, 1412, 1414, 1436, 1411, 1418, 1384, 1449, 1447, 1419, 1443, 1397, 1386, 1452, 1436, 1450, 1431, 1397, 1441, 1420, 1382, 1451, 1442, 1452, 1400, 1397, 1432, 1408 ] y = '' for z in x: y += chr(z - 1331) username = y else: username = Config().get('pools.%s.user' % (pool_name)) if device.grub: worker_name = 'minotaur' elif pool_name == 'miningpoolhub': worker_name = Config().get('pools.miningpoolhub.hub_workers.%s' % (algo)) else: worker_name = Config().get('pools.%s.worker_name' % (pool_name)) if Config().get('pools.%s.append_device_id_to_worker_name' % (pool_name)): worker_name += str(device.id) miner = self.miners[miner_name] password = '******' if device.power_supported(): if Config().get('use_max_power_limit_when_switching'): device.set_power_limit(device.max_power_limit_f) else: power_limits = [] if device.state == 'active': power_limit = device.get_power_limit_for_algorithm( device.algos[0]['miner'], device.algos[0]['algo']) if power_limit: power_limits.append(power_limit) power_limit = device.get_power_limit_for_algorithm( miner_name, algo) if power_limit: power_limits.append(power_limit) if len(power_limits) > 0: device.set_power_limit(max(power_limits)) algo_id = miner.start(device.id, algo, endpoints, username, password, worker_name) if not isinstance(algo_id, int): if not silent: device.log('warning', 'unable to start worker - miner error') return False if device.state == 'active': for i in range(0, len(device.algos)): previous_miner = self.miners[device.algos[i]['miner']] previous_miner.stop(device.id, device.algos[i]['algo_id']) with open("/tmp/.minotaur.%d" % (device.id), "w") as f: pass device.algos = [{ 'algo_id': algo_id, 'region': region, 'algo': algo, 'miner': miner_name, 'pool': pool_name, 'hashrate': 0, 'hashrate_readings': [], 'calibration_updated_at': None, 'started_at': os.stat("/tmp/.minotaur.%d" % (device.id)).st_mtime }] device.changed = datetime.datetime.now() device.state = 'active' device.profile = profile.name nvidia.Nvidia().set_profile(device, profile) return True
#################################################### # MAIN # #################################################### import select import socket import sys import threading import time allGpu = {} mutex = threading.Lock() parserIntel = intel.Intel(allGpu, mutex) parserAmd = amd.Amd(allGpu, mutex) parserNvidia = nvidia.Nvidia(allGpu, mutex) clientConnectedEvent = threading.Event() clientConnectedEvent.set() t1 = Runner(parserIntel, clientConnectedEvent) t2 = Runner(parserAmd, clientConnectedEvent) t3 = Runner(parserNvidia, clientConnectedEvent) # we need to sincronize access to 'allGpu' gpuFount = 0 while len(allGpu) == 0 and (t1.isAlive() or t2.isAlive() or t3.isAlive()): with mutex: gpuFount = len(allGpu) time.sleep(0.5)
def get_local_data(self, minimal=False): data = [] devices = nvidia.Nvidia().get_nvidia_devices(1, True) Miners().poll() if not minimal and os.path.exists( self.power_file) and os.path.getsize(self.power_file) > 0: power_draw_readings = pickle.loads(open(self.power_file).read()) else: power_draw_readings = [] if not minimal and os.path.exists( self.profitability_file) and os.path.getsize( self.profitability_file) > 0: profitability_readings = pickle.loads( open(self.profitability_file).read()) else: profitability_readings = [] Calibration().load() total_mbtc = 0 total_power = 0 total_power_limit = 0 power_values = {} power_limit_values = {} for device in devices: device.algos = [] Miners().get_device_state(device) mbtc_per_day_values = [0] algos = device.algos if len(algos) == 0: algos = ['IDLE'] for algo_i in range(0, len(algos)): algo = algos[algo_i] if algo_i == 0: omit_fields = False else: omit_fields = True if algo == 'IDLE': algo = "IDLE" algo1 = "IDLE" rate_s = "-" mbtc_per_day = 0 miner = '-' region = '-' pool = '-' _time = '-' else: algo1 = algo['algo'] miner = algo['miner'] region = algo['region'] pool = algo['pool'] _pool = Pools().pools[pool] if os.path.exists("/tmp/.minotaur.%d" % (device.id)): _time = Units().to_timestr( int(time.time() - os.stat("/tmp/.minotaur.%d" % (device.id)).st_mtime)) else: _time = '-' rate_a, rate_b = algo['hashrate'] if algo['algo'] in Config().get('algorithms')['double']: rate_s = Units().hashrate_str(rate_a) rate_s2 = Units().hashrate_str(rate_b) benchmarks = {algo['algo']: [rate_a, rate_b]} algo1, algo2 = algo['algo'].split("_") mbtc_per_day_values = [ _pool.mbtc_per_day( benchmarks, 'cached')[algo['region']][algo['algo']] ] else: rate_s = Units().hashrate_str(rate_a) benchmarks = {algo['algo']: rate_a} if algo['algo'] in _pool.mbtc_per_day( benchmarks, 'cached')[algo['region']].keys(): mbtc_per_day_values = [ _pool.mbtc_per_day( benchmarks, 'cached')[algo['region']][algo['algo']] ] else: mbtc_per_day_values = [0] if pool != '-': pool = _pool.shortened(region) metrics = device.to_hash() metrics.pop('changed', None) metrics['miner'] = miner metrics['region'] = region metrics['pool'] = pool metrics['time'] = _time metrics['omit_fields'] = omit_fields if metrics['fan']: metrics['fan'] = str(metrics['fan']).rjust(3) + " %" if metrics['miner']: metrics['miner'] = metrics['miner'][0:5] else: metrics['miner'] = '-' if algo == "IDLE": if metrics['gpu_u_i'] and metrics['gpu_u_i'] >= 90: algo = ".pending." algo1 = ".pending." rate_s = ".." mbtc_per_day = mbtc_per_day_values[0] metrics['host'] = 'local' metrics['id'] = device.id metrics[" algo"] = algo1 metrics["rate"] = rate_s metrics[" mBTC/day"] = ("%.2f" % (mbtc_per_day)).rjust(5) if not metrics['region']: metrics['region'] = '-' total_mbtc += sum(mbtc_per_day_values) if metrics['power_f']: power_values[metrics['id']] = metrics['power_f'] margin = self.calculate_profit_margin_for_card( sum(mbtc_per_day_values), metrics['power_f']) net_mbtc = (mbtc_per_day / 100) * margin if margin < 0: margin = 0 margin_s = "%d%%" % (int(margin)) metrics[" mBTC/day"] += "/" metrics[" mBTC/day"] += ("%.2f" % (net_mbtc)).rjust(5) metrics[" mBTC/day"] += " %s" % (margin_s.rjust(4)) else: margin = 0 if margin > 0: metrics["margin"] = "%.1f%%" % (margin) else: metrics["margin"] = "-" if metrics['limit_f']: power_limit_values[metrics['id']] = metrics['limit_f'] if device.state == 'calibrating': metrics[' algo'] = '*' + metrics[' algo'] elif device.get_pin() and 'algorithm' in device.get_pin().keys( ) and device.get_pin()['algorithm'] == metrics[' algo']: metrics[' algo'] = '+' + metrics[' algo'] elif device.get_pin() and 'algorithm' in device.get_pin().keys( ) and '_' in device.get_pin()['algorithm'] and metrics[ ' algo'] in device.get_pin()['algorithm'].split('_'): metrics[' algo'] = '+' + metrics[' algo'] else: metrics[' algo'] = ' ' + metrics[' algo'] if metrics['gpu_f']: match = re.match("^([\d]+)", metrics['gpu_f']) if match: metrics['gpu_f'] = match.group(1) else: metrics['gpu_f'] = '-' else: metrics['gpu_f'] = '-' if metrics['mem_f']: match = re.match("^([\d]+)", metrics['mem_f']) if match: metrics['mem_f'] = match.group(1) else: metrics['mem_f'] = '-' else: metrics['mem_f'] = '-' metrics['ps clocks'] = "%s %s/%s MHz" % ( metrics['ps'], metrics['gpu_f'], metrics['mem_f']) power = re.match("^([\d]+)", metrics['power']) limit = re.match("^([\d]+)", metrics['limit']) if power and limit: metrics['power'] = "%s/%s W" % (power.group(1), limit.group(1)) else: metrics['power'] = '-' data.append(metrics) if algo not in [ 'IDLE', '.pending.' ] and algo['algo'] in Config().get('algorithms.double'): mbtc_per_day = mbtc_per_day_values[1] metrics2 = metrics.copy() metrics2[" algo"] = algo2 metrics2["rate"] = rate_s2 metrics2[" mBTC/day"] = ("%.2f" % (mbtc_per_day)).rjust(5) net_mbtc = (mbtc_per_day / 100) * margin metrics2[" mBTC/day"] += "/" metrics2[" mBTC/day"] += ("%.2f" % (net_mbtc)).rjust(5) metrics2[" mBTC/day"] += " %s" % (margin_s.rjust(4)) if device.state == 'calibrating': metrics2[" algo"] = '*' + metrics2[' algo'] elif device.get_pin() and '_' in device.get_pin( )['algorithm'] and metrics2[' algo'] in device.get_pin( )['algorithm'].split('_'): metrics2[" algo"] = '+' + metrics2[' algo'] else: metrics2[" algo"] = ' ' + metrics2[' algo'] data.append(metrics2) total_power = sum(power_values.values()) total_power_limit = sum(power_limit_values.values()) electric_cost_mbtc = self.get_electricity_cost( total_power + Config().get('system_draw_watts'), True, Config().get('electricity_per_kwh')) net_mbtc = total_mbtc - electric_cost_mbtc return [ data, total_mbtc, net_mbtc, total_power, total_power_limit, power_draw_readings, profitability_readings ]