PoW support code cleanup
Is now nicer and reports if OpenCL fails
This commit is contained in:
parent
9335f74c61
commit
399100e6d8
|
@ -21,6 +21,12 @@ import l10n
|
|||
# This thread, of which there is only one, does the heavy lifting:
|
||||
# calculating POWs.
|
||||
|
||||
def sizeof_fmt(num, suffix='h/s'):
|
||||
for unit in ['','k','M','G','T','P','E','Z']:
|
||||
if abs(num) < 1000.0:
|
||||
return "%3.1f%s%s" % (num, unit, suffix)
|
||||
num /= 1024.0
|
||||
return "%.1f%s%s" % (num, 'Yi', suffix)
|
||||
|
||||
class singleWorker(threading.Thread, StoppableThread):
|
||||
|
||||
|
@ -787,7 +793,7 @@ class singleWorker(threading.Thread, StoppableThread):
|
|||
trialValue, nonce = proofofwork.run(target, initialHash)
|
||||
logger.info('(For msg message) Found proof of work ' + str(trialValue) + ' Nonce: ' + str(nonce))
|
||||
try:
|
||||
logger.info('POW took ' + str(int(time.time() - powStartTime)) + ' seconds. ' + str(nonce / (time.time() - powStartTime)) + ' nonce trials per second.')
|
||||
logger.info('PoW took %.1f seconds, speed %s.', time.time() - powStartTime, sizeof_fmt(nonce / (time.time() - powStartTime)))
|
||||
except:
|
||||
pass
|
||||
|
||||
|
@ -966,7 +972,7 @@ class singleWorker(threading.Thread, StoppableThread):
|
|||
trialValue, nonce = proofofwork.run(target, initialHash)
|
||||
logger.info('(For ack message) Found proof of work ' + str(trialValue) + ' Nonce: ' + str(nonce))
|
||||
try:
|
||||
logger.info('POW took ' + str(time.time() - powStartTime) + ' seconds. ' + str(nonce / (time.time() - powStartTime)) + ' nonce trials per second.')
|
||||
logger.info('PoW took %.1f seconds, speed %s.', time.time() - powStartTime, sizeof_fmt(nonce / (time.time() - powStartTime)))
|
||||
except:
|
||||
pass
|
||||
|
||||
|
|
|
@ -5,35 +5,49 @@ import hashlib
|
|||
import random
|
||||
import os
|
||||
|
||||
from shared import codePath, safeConfigGetBoolean
|
||||
from debug import logger
|
||||
|
||||
libAvailable = True
|
||||
ctx = False
|
||||
queue = False
|
||||
program = False
|
||||
gpus = []
|
||||
hash_dt = None
|
||||
|
||||
try:
|
||||
import numpy
|
||||
import pyopencl as cl
|
||||
hash_dt = numpy.dtype([('target', numpy.uint64), ('v', numpy.str_, 73)])
|
||||
gpus = []
|
||||
for platform in cl.get_platforms():
|
||||
gpus.extend(platform.get_devices(device_type=cl.device_type.GPU))
|
||||
if (len(gpus) > 0):
|
||||
ctx = cl.Context(devices=gpus)
|
||||
queue = cl.CommandQueue(ctx)
|
||||
full_path = os.path.dirname(os.path.realpath(__file__))
|
||||
f = open(os.path.join(full_path, "bitmsghash", 'bitmsghash.cl'), 'r')
|
||||
fstr = ''.join(f.readlines())
|
||||
program = cl.Program(ctx, fstr).build(options="")
|
||||
else:
|
||||
print "No OpenCL GPUs found"
|
||||
except:
|
||||
libAvailable = False
|
||||
|
||||
def initCL():
|
||||
global ctx, queue, program, gpus, hash_dt
|
||||
try:
|
||||
hash_dt = numpy.dtype([('target', numpy.uint64), ('v', numpy.str_, 73)])
|
||||
for platform in cl.get_platforms():
|
||||
gpus.extend(platform.get_devices(device_type=cl.device_type.GPU))
|
||||
if (len(gpus) > 0):
|
||||
ctx = cl.Context(devices=gpus)
|
||||
queue = cl.CommandQueue(ctx)
|
||||
f = open(os.path.join(codePath(), "bitmsghash", 'bitmsghash.cl'), 'r')
|
||||
fstr = ''.join(f.readlines())
|
||||
program = cl.Program(ctx, fstr).build(options="")
|
||||
logger.info("Loaded OpenCL kernel")
|
||||
else:
|
||||
logger.info("No OpenCL GPUs found")
|
||||
ctx = False
|
||||
except Exception as e:
|
||||
logger.error("OpenCL fail: ", exc_info=True)
|
||||
ctx = False
|
||||
except Exception as e:
|
||||
print "opencl fail: " + str(e)
|
||||
ctx = False
|
||||
|
||||
def has_opencl():
|
||||
global ctx
|
||||
return (ctx != False)
|
||||
|
||||
def do_opencl_pow(hash, target):
|
||||
global ctx, queue, program, gpus, hash_dt
|
||||
|
||||
output = numpy.zeros(1, dtype=[('v', numpy.uint64, 1)])
|
||||
if (ctx == False):
|
||||
return output[0][0]
|
||||
|
@ -62,11 +76,14 @@ def do_opencl_pow(hash, target):
|
|||
queue.finish()
|
||||
progress += globamt
|
||||
sofar = time.time() - start
|
||||
print sofar, progress / sofar, "hashes/sec"
|
||||
# logger.debug("Working for %.3fs, %.2f Mh/s", sofar, (progress / sofar) / 1000000)
|
||||
taken = time.time() - start
|
||||
print progress, taken
|
||||
# logger.debug("Took %d tries.", progress)
|
||||
return output[0][0]
|
||||
|
||||
if libAvailable:
|
||||
initCL()
|
||||
|
||||
if __name__ == "__main__":
|
||||
target = 54227212183L
|
||||
initialHash = "3758f55b5a8d902fd3597e4ce6a2d3f23daff735f65d9698c270987f4e67ad590b93f3ffeba0ef2fd08a8dc2f87b68ae5a0dc819ab57f22ad2c4c9c8618a43b3".decode("hex")
|
||||
|
|
|
@ -4,9 +4,10 @@
|
|||
import hashlib
|
||||
from struct import unpack, pack
|
||||
import sys
|
||||
from shared import config, frozen, codePath
|
||||
import shared
|
||||
from debug import logger
|
||||
from shared import config, frozen, codePath, shutdown, safeConfigGetBoolean, UISignalQueue
|
||||
import openclpow
|
||||
import tr
|
||||
import os
|
||||
import ctypes
|
||||
|
||||
|
@ -17,12 +18,20 @@ if "win32" == sys.platform:
|
|||
else:
|
||||
bitmsglib = 'bitmsghash64.dll'
|
||||
try:
|
||||
# MSVS
|
||||
bso = ctypes.WinDLL(os.path.join(codePath(), "bitmsghash", bitmsglib))
|
||||
logger.info("Loaded C PoW DLL (stdcall) %s", bitmsglib)
|
||||
except:
|
||||
bso = None
|
||||
try:
|
||||
# MinGW
|
||||
bso = ctypes.CDLL(os.path.join(codePath(), "bitmsghash", bitmsglib))
|
||||
logger.info("Loaded C PoW DLL (cdecl) %s", bitmsglib)
|
||||
except:
|
||||
bso = None
|
||||
else:
|
||||
try:
|
||||
bso = ctypes.CDLL(os.path.join(codePath(), "bitmsghash", bitmsglib))
|
||||
logger.info("Loaded C PoW DLL %s", bitmsglib)
|
||||
except:
|
||||
bso = None
|
||||
if bso:
|
||||
|
@ -58,16 +67,17 @@ def _pool_worker(nonce, initialHash, target, pool_size):
|
|||
return [trialValue, nonce]
|
||||
|
||||
def _doSafePoW(target, initialHash):
|
||||
print "Safe POW\n"
|
||||
logger.debug("Safe PoW start")
|
||||
nonce = 0
|
||||
trialValue = float('inf')
|
||||
while trialValue > target:
|
||||
nonce += 1
|
||||
trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8])
|
||||
logger.debug("Safe PoW done")
|
||||
return [trialValue, nonce]
|
||||
|
||||
def _doFastPoW(target, initialHash):
|
||||
print "Fast POW\n"
|
||||
logger.debug("Fast PoW start")
|
||||
import time
|
||||
from multiprocessing import Pool, cpu_count
|
||||
try:
|
||||
|
@ -85,7 +95,7 @@ def _doFastPoW(target, initialHash):
|
|||
for i in range(pool_size):
|
||||
result.append(pool.apply_async(_pool_worker, args = (i, initialHash, target, pool_size)))
|
||||
while True:
|
||||
if shared.shutdown >= 1:
|
||||
if shutdown >= 1:
|
||||
pool.terminate()
|
||||
while True:
|
||||
time.sleep(10) # Don't let this thread return here; it will return nothing and cause an exception in bitmessagemain.py
|
||||
|
@ -95,30 +105,38 @@ def _doFastPoW(target, initialHash):
|
|||
result = result[i].get()
|
||||
pool.terminate()
|
||||
pool.join() #Wait for the workers to exit...
|
||||
logger.debug("Fast PoW done")
|
||||
return result[0], result[1]
|
||||
time.sleep(0.2)
|
||||
|
||||
def _doCPoW(target, initialHash):
|
||||
h = initialHash
|
||||
m = target
|
||||
out_h = ctypes.pointer(ctypes.create_string_buffer(h, 64))
|
||||
out_m = ctypes.c_ulonglong(m)
|
||||
print "C PoW start"
|
||||
logger.debug("C PoW start")
|
||||
nonce = bmpow(out_h, out_m)
|
||||
trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8])
|
||||
print "C PoW done"
|
||||
logger.debug("C PoW done")
|
||||
return [trialValue, nonce]
|
||||
|
||||
def _doGPUPoW(target, initialHash):
|
||||
print "GPU PoW start"
|
||||
logger.debug("GPU PoW start")
|
||||
nonce = openclpow.do_opencl_pow(initialHash.encode("hex"), target)
|
||||
trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8])
|
||||
#print "{} - value {} < {}".format(nonce, trialValue, target)
|
||||
print "GPU PoW done"
|
||||
if trialValue > target:
|
||||
deviceNames = ", ".join(gpu.name for gpu in openclpow.gpus)
|
||||
UISignalQueue.put(('updateStatusBar', tr.translateText("MainWindow",'Your GPU(s) did not calculate correctly, disabling OpenCL. Please report to the developers.')))
|
||||
logger.error("Your GPUs (%s) did not calculate correctly, disabling OpenCL. Please report to the developers.", deviceNames)
|
||||
openclpow.ctx = False
|
||||
raise Exception("GPU did not calculate correctly.")
|
||||
logger.debug("GPU PoW done")
|
||||
return [trialValue, nonce]
|
||||
|
||||
def run(target, initialHash):
|
||||
target = int(target)
|
||||
if shared.safeConfigGetBoolean('bitmessagesettings', 'opencl') and openclpow.has_opencl():
|
||||
if safeConfigGetBoolean('bitmessagesettings', 'opencl') and openclpow.has_opencl():
|
||||
# trialvalue1, nonce1 = _doGPUPoW(target, initialHash)
|
||||
# trialvalue, nonce = _doFastPoW(target, initialHash)
|
||||
# print "GPU: %s, %s" % (trialvalue1, nonce1)
|
||||
|
@ -133,12 +151,8 @@ def run(target, initialHash):
|
|||
return _doCPoW(target, initialHash)
|
||||
except:
|
||||
pass # fallback
|
||||
if frozen == "macosx_app" or not frozen:
|
||||
# on my (Peter Surda) Windows 10, Windows Defender
|
||||
# does not like this and fights with PyBitmessage
|
||||
# over CPU, resulting in very slow PoW
|
||||
try:
|
||||
return _doFastPoW(target, initialHash)
|
||||
except:
|
||||
pass #fallback
|
||||
try:
|
||||
return _doFastPoW(target, initialHash)
|
||||
except:
|
||||
pass #fallback
|
||||
return _doSafePoW(target, initialHash)
|
||||
|
|
Reference in New Issue
Block a user