Example #1
0
    def add(self, device_id, device_class, pool, miner, algo, region, hashrate,
            gross_mbtc, net_mbtc, device_watts, total_watts):
        if not os.path.exists(self.log_file):
            with open(self.log_file, "w") as f:
                f.write(
                    "timestamp,device_id,device_class,pool,miner,algorithm,region,hashrate,gross_mbtc,net_mbtc,device_watts,total_watts\n"
                )

        with open(self.log_file, "a+") as f:
            if net_mbtc == 0:
                net_s = ""
            else:
                net_s = "%.2f" % (net_mbtc)

            if '_' in algo:
                hashrate_s = Units().hashrate_str(hashrate)
            else:
                hashrate_s = Units().hashrate_str(hashrate[0])

            f.write("%s,%d,%s,%s,%s,%s,%s,%s,%.2f,%s,%.2f,%.2f\n" %
                    (datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                     device_id, device_class, pool, miner, algo, region,
                     hashrate_s, gross_mbtc, net_s, device_watts, total_watts))

        if os.path.getsize(self.log_file) >= (
                Config().get('stats.max_size_mb') * 1024 * 1024):
            self.rotate_logs(self.log_file)
Example #2
0
    def get_power_draw_average_time_periods(self):
        data = {}

        for seconds in Config().get('live_data.power_draw_averages'):
            data[seconds] = Units().seconds_to_string(seconds)

        return data
Example #3
0
  def get_miner_hashrate_for_algorithm_on_device(self, miner_name, algorithm, device_class):
    calibrated = self.get('%s.%s.%s' % (device_class, miner_name, algorithm))

    if calibrated:
      return Units().hashrate_str(calibrated['hashrate'])

    return " "
Example #4
0
 def realnew(klass, h, M, L, K):
   self = object.__new__(klass)
   self.M = M
   self.L = L
   self.K = K
   self.h = h
   self.units = Units(h)
   self.U = self.units
   self.DH = self.units.C / self.units.H0
   self.tH = 1.0 / self.units.H0
   self._cosmology = _cosmology.Cosmology(self.M, self.K, self.L, self.h)
   return self
Example #5
0
    def check_hashrate(self):
        hashrates = Calibration().get_hashrates(self)

        if len(self.algos) == 0:
            return

        miner = self.algos[0]['miner']
        algo = self.algos[0]['algo']

        if not miner in hashrates.keys() or not algo in hashrates[miner].keys(
        ):
            self.log(
                'warning', 'running uncalibrated algorithm %s with miner %s' %
                (algo, miner))
            return

        if self.algos[0]['algo'] in Config().get('algorithms.single'):
            baseline = float(hashrates[miner][algo]['hashrate'])
        else:
            baseline = float(hashrates[miner][algo]['hashrate'][0])

        threshold_pc_value = (
            baseline / 100) * Config().get('hashrate_alert_threshold_percent')

        hr_s = Units().hashrate_str(self.algos[0]['hashrate'][0])
        bl_s = Units().hashrate_str(baseline)

        if self.algos[0]['hashrate'][0] < baseline and (
                baseline - self.algos[0]['hashrate'][0]) >= threshold_pc_value:
            self.log(
                'warning', 'hashrate %d%% below calibrated rate [%s < %s]' %
                (Config().get('hashrate_alert_threshold_percent'), hr_s, bl_s))

        if self.algos[0]['hashrate'][0] > baseline and (
                self.algos[0]['hashrate'][0] - baseline) >= threshold_pc_value:
            self.log(
                'warning', 'hashrate %d%% above calibrated rate [%s > %s]' %
                (Config().get('hashrate_alert_threshold_percent'), hr_s, bl_s))
Example #6
0
    args_cli = pytools.parse_args()
    var = args_cli.var

    #confs = [ "gam3.ini", ]
    confs = [
        args_cli.conf_filename,
    ]

    for conf_filename in confs:
        conf = Configuration(conf_filename, do_print=True)

        # restructure path to point to this dir
        fdir = conf.outdir
        print(fdir)

        units = Units(conf)

        #--------------------------------------------------
        # read data

        flds_Epar = []
        flds_Eperp = []

        flds_Bpar = []
        flds_Bperp = []

        flds_Jpar = []
        flds_Jperp = []
        flds_time = []

        flds_tot = []
Example #7
0
    def hashrate_str(self):
        if self.algos[0]['algo'] in Config().get('algorithms.single'):
            return Units().hashrate_str(self.algos[0]['hashrate'][0])

        return Units().hashrate_str(self.algos[0]['hashrate'])
Example #8
0
  def handle_device_update(self, device):
    if (datetime.datetime.now() - device.changed).seconds < (Config().get('calibration.update_calibration_data_after_mins') * 60):
      return

    for algo in device.algos:
      # Max update once a minute
      if algo['calibration_updated_at'] and \
        (time.time() - algo['calibration_updated_at']) < 60:
        continue

      if len(algo['hashrate_readings']) >0:
        readings_a = []
        readings_b = []

        for reading in algo['hashrate_readings']:
          readings_a.append(reading[0])
          readings_b.append(reading[1])

        if '_' in algo['algo']:
          variance, n = self.get_variance(readings_a, readings_b)
        else:
          variance, n = self.get_variance(readings_a)

        if self.is_stable(variance, n):
          calibrated_data = self.get('%s.%s.%s' % (device.dclass, algo['miner'], algo['algo']))

          if '_' in algo['algo']:
            nominal = [self.get_nominal_hashrate_from_range(readings_a), self.get_nominal_hashrate_from_range(readings_b)]
          else:
            nominal = self.get_nominal_hashrate_from_range(readings_a)

          if self.within_update_threshold(nominal, calibrated_data['hashrate']) and \
            self.hashrate_is_visibly_different(nominal, calibrated_data['hashrate']):
              device.log('info', '%s[%s]: new calibrated rate: %s' % (algo['algo'], algo['miner'], Units().hashrate_str(nominal)))

              calibrated_data['hashrate'] = nominal

              self.update_calibration_data(device.dclass, algo['miner'], algo['algo'], nominal, calibrated_data['power_limit'])

              self.set("%s.%s.%s" % (device.dclass, algo['miner'], algo['algo']), calibrated_data)
              algo['calibration_updated_at'] = time.time()
Example #9
0
    def start(self,
              device,
              pool_name,
              miner,
              algorithm,
              region,
              quick=False,
              force=False):
        self.miner = miner
        self.device = device
        self.default_profile = Config().get('device_profiles.default')

        Miners().reload_config()

        device.pin = {
            'pool_name': pool_name,
            'miner_name': miner.name,
            'algorithm': algorithm,
            'region': region
        }

        if not Config().get('calibration'):
            Log().add('fatal', "calibration config missing from config file")

        for key in [
                "hashrate_stabilisation_timeout_mins",
                "hashrate_stabilisation_tolerance",
                "hashrate_stabilisation_consecutive_readings_required",
                "algorithm_start_timeout"
        ]:
            if Config().get('calibration.%s' % (key)) == None:
                Log().add('fatal',
                          "missing config option: calibration.%s" % (key))

        if Config().get('calibration.power_tuning.enable'):
            for key in ["decrement_watts", "acceptable_loss_percent"]:
                if not Config().get('calibration.power_tuning.%s' % (key)):
                    Log().add(
                        'fatal',
                        "missing config option: calibration.power_tuning.%s" %
                        (key))

        Config().set('pools.%s.append_device_id_to_worker_name' % (pool_name),
                     False)

        if pool_name == 'miningpoolhub':
            if Config().get('pools.miningpoolhub.hub_workers.%s' %
                            (algorithm))[-5:] != 'CALIB':
                Config().set(
                    'pools.miningpoolhub.hub_workers.%s' % (algorithm),
                    Config().get('pools.miningpoolhub.hub_workers.%s' %
                                 (algorithm)) + 'CALIB')
        else:
            if Config().get('pools.%s.worker_name' %
                            (pool_name))[-5:] != 'CALIB':
                Config().set(
                    'pools.%s.worker_name' % (pool_name),
                    Config().get('pools.%s.worker_name' % (pool_name)) +
                    "CALIB")

        if quick:
            Config().set('calibration.power_tuning.enable', False)

        profile = Profiles().get_for_device_algo(device, algorithm)

        Log().add('info', '     device id: %d' % (device.id))
        Log().add('info', '          pool: %s' % (pool_name))
        Log().add('info', '  device class: %s' % (device.dclass))
        Log().add('info', 'device profile: %s' % (profile.name))
        Log().add('info', '         miner: %s' % (miner.name))
        Log().add('info', '     algorithm: %s' % (algorithm))
        Log().add('info', '        region: %s' % (region))

        Miners().poll()
        Miners().get_device_state(device)

        if device.state != 'inactive':
            if device.state == 'calibrating':
                device.log(
                    'fatal',
                    'this device is already being used for calibration')

            if force:
                device.log('info', 'terminating existing worker')
                if not device.stop(True):
                    device.log('fatal', 'failed to stop existing worker')
            else:
                device.log(
                    'fatal',
                    'unable to start calibration - device is in use (use --force to override)'
                )

        self.set_pin(device.id)

        default_power_limit = device.default_power_limit_f
        min_power_limit = device.min_power_limit_f
        max_power_limit = device.max_power_limit_f

        if max_power_limit == 0:
            device.log('info', 'device does not support power monitoring')
        else:
            device.log('info', 'max power limit: %d W' % (max_power_limit))

        device.log(
            'info', 'stabilisation tolerance: %.2f%%' %
            (Config().get('calibration.hashrate_stabilisation_tolerance')))

        if Config().get('debug'):
            device.log('debug', 'loading default profile')

        Nvidia().set_default_profile(device)

        if Config().get('debug'):
            device.log('debug', 'initialising pools')

        Pools()

        sample_timeout = Config().get(
            'calibration.hashrate_stabilisation_timeout_mins')

        if default_power_limit != None and Config().get(
                'calibration.power_tuning.enable'):
            device.log(
                'info',
                'starting initial run at max power limit [timeout=%dmins]' %
                (sample_timeout))
        else:
            device.log(
                'info',
                'starting single run [timeout=%dmins]' % (sample_timeout))

        Miners().poll()
        Miners().get_device_state(device)

        if device.state != 'calibrating':
            if not device.start(True):
                device.log('fatal', 'worker failed to start')

        if Config().get('calibration.power_tuning.enable'):
            if not device.power_supported():
                device.log('info', 'device does not support power monitoring')
            else:
                device.set_power_limit(max_power_limit)

        initial_hashrate, initial_max_power_draw = self.get_max_hashrate_and_power_draw(
            miner, device, sample_timeout * 60)

        if initial_hashrate == None:
            device.log(
                'info',
                'skipping algorithm as we failed to get a stable reading')
            print ""
            return

        if initial_max_power_draw != None and initial_max_power_draw > max_power_limit:
            initial_max_power_draw = max_power_limit

        device.log(
            'info', 'benchmark hashrate: %s' %
            (Units().hashrate_str(initial_hashrate)))

        if initial_max_power_draw != None:
            device.log('info',
                       'max power draw: %.2f' % (initial_max_power_draw))
            initial_power_limit = int(math.ceil(initial_max_power_draw))

        hashrate = initial_hashrate

        if initial_max_power_draw == None:
            power_limit = None
        elif Config().get('calibration.power_tuning.enable'):
            if max_power_limit == 0 or min_power_limit == 0 or default_power_limit == 0:
                device.log(
                    'error',
                    'device did not give us sane values for its min/max/default power limits'
                )
                device.log(
                    'error',
                    'unable to proceed with power calibration - device may not support changing the power limit'
                )

                power_limit = default_power_limit
            else:
                power_limit = initial_power_limit

                device.log('info', 'tuning power limit for optimum efficiency')
                hashrate, power_limit = self.do_power_calibration(
                    device, power_limit, miner, hashrate, min_power_limit)
        else:
            power_limit = default_power_limit

        Nvidia().set_default_profile(device)

        self.unset_pin(device.id)

        device.log('info', 'storing calibration data')

        Calibration().update_calibration_data(device.dclass, miner.name,
                                              algorithm, hashrate, power_limit)

        if not device.stop(True):
            device.log('fatal', "failed to stop the miner process")

        print ""

        device.log(
            'info',
            '   calibrated hashrate: %s' % (Units().hashrate_str(hashrate)))

        if power_limit != None:
            device.log('info',
                       'calibrated power limit: %.2f W' % (power_limit))

        print ""
Example #10
0
    def do_power_calibration(self, device, power_limit, miner,
                             initial_hashrate, min_power_limit):
        sample_timeout = Config().get(
            'calibration.hashrate_stabilisation_timeout_mins')
        acceptable_loss_pc = Config().get(
            'calibration.power_tuning.acceptable_loss_percent')

        dial_back = False
        dialed_back = False
        hashrate = initial_hashrate

        if "_" in device.algos[0]['algo']:
            initial_value = initial_hashrate[0]
        else:
            initial_value = initial_hashrate

        while True:
            if dial_back:
                power_limit += Config().get(
                    'calibration.power_tuning.decrement_watts') / 2
                dialed_back = True
            else:
                power_limit -= Config().get(
                    'calibration.power_tuning.decrement_watts')

            if power_limit < min_power_limit:
                power_limit = min_power_limit

            device.log('info', 'setting power limit: %d W' % (power_limit))

            device.set_power_limit(power_limit)

            new_hashrate, max_power_draw = self.get_max_hashrate_and_power_draw(
                miner, device, sample_timeout * 60)

            if new_hashrate == None:
                device.log(
                    'info',
                    'skipping algorithm as we failed to get a stable reading')
                print ""
                return

            if "_" in device.algos[0]['algo']:
                new_value = new_hashrate[0]
            else:
                new_value = new_hashrate

            device.log(
                'info',
                'nominal hashrate: %s' % (Units().hashrate_str(new_hashrate)))

            if new_value > initial_value:
                device.log('info', 'hashrate is higher than before, w00t!')
                hashrate = new_hashrate
                initial_value = new_value
            elif new_value >= (initial_value -
                               (initial_value / 100) * acceptable_loss_pc):
                hashrate = new_hashrate
                if power_limit == min_power_limit or dial_back:
                    device.log(
                        'info', 'hashrate loss is within acceptable %.2f%%' %
                        (acceptable_loss_pc))
                else:
                    device.log(
                        'info',
                        'hashrate loss is within acceptable %.2f%%, continuing'
                        % (acceptable_loss_pc))
            else:
                if dial_back or Config().get(
                        'calibration.power_tuning.decrement_watts') == 1:
                    device.log(
                        'info',
                        'hashrate still below our acceptable loss level of %.2f%%, stopping'
                        % (acceptable_loss_pc))

                    if Config().get(
                            'calibration.power_tuning.decrement_watts') == 1:
                        power_limit += 1
                    else:
                        power_limit += Config().get(
                            'calibration.power_tuning.decrement_watts') / 2
                    break
                else:
                    device.log(
                        'info',
                        'hashrate fell below our acceptable loss level of %.2f%%, dialling back %d W'
                        % (acceptable_loss_pc, Config().get(
                            'calibration.power_tuning.decrement_watts') / 2))
                    dial_back = True

            if dialed_back:
                break

            if power_limit == min_power_limit and not dial_back:
                device.log('info', 'minimum power limit reached, stopping')
                break

        return [hashrate, power_limit]
Example #11
0
 def __init__(self, units_config):
     self.units_config = units_config
     self.units = Units(units_config["units"])
     self.allies = Allies(units_config["allies"])
     self.battalions = Battalions(units_config["battalions"])
     self.all = [self.units, self.allies, self.battalions]
Example #12
0
    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
        ]