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:
|
# This thread, of which there is only one, does the heavy lifting:
|
||||||
# calculating POWs.
|
# 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):
|
class singleWorker(threading.Thread, StoppableThread):
|
||||||
|
|
||||||
|
@ -787,7 +793,7 @@ class singleWorker(threading.Thread, StoppableThread):
|
||||||
trialValue, nonce = proofofwork.run(target, initialHash)
|
trialValue, nonce = proofofwork.run(target, initialHash)
|
||||||
logger.info('(For msg message) Found proof of work ' + str(trialValue) + ' Nonce: ' + str(nonce))
|
logger.info('(For msg message) Found proof of work ' + str(trialValue) + ' Nonce: ' + str(nonce))
|
||||||
try:
|
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:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -966,7 +972,7 @@ class singleWorker(threading.Thread, StoppableThread):
|
||||||
trialValue, nonce = proofofwork.run(target, initialHash)
|
trialValue, nonce = proofofwork.run(target, initialHash)
|
||||||
logger.info('(For ack message) Found proof of work ' + str(trialValue) + ' Nonce: ' + str(nonce))
|
logger.info('(For ack message) Found proof of work ' + str(trialValue) + ' Nonce: ' + str(nonce))
|
||||||
try:
|
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:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -5,35 +5,49 @@ import hashlib
|
||||||
import random
|
import random
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from shared import codePath, safeConfigGetBoolean
|
||||||
|
from debug import logger
|
||||||
|
|
||||||
|
libAvailable = True
|
||||||
ctx = False
|
ctx = False
|
||||||
queue = False
|
queue = False
|
||||||
program = False
|
program = False
|
||||||
|
gpus = []
|
||||||
|
hash_dt = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import numpy
|
import numpy
|
||||||
import pyopencl as cl
|
import pyopencl as cl
|
||||||
|
except:
|
||||||
|
libAvailable = False
|
||||||
|
|
||||||
|
def initCL():
|
||||||
|
global ctx, queue, program, gpus, hash_dt
|
||||||
|
try:
|
||||||
hash_dt = numpy.dtype([('target', numpy.uint64), ('v', numpy.str_, 73)])
|
hash_dt = numpy.dtype([('target', numpy.uint64), ('v', numpy.str_, 73)])
|
||||||
gpus = []
|
|
||||||
for platform in cl.get_platforms():
|
for platform in cl.get_platforms():
|
||||||
gpus.extend(platform.get_devices(device_type=cl.device_type.GPU))
|
gpus.extend(platform.get_devices(device_type=cl.device_type.GPU))
|
||||||
if (len(gpus) > 0):
|
if (len(gpus) > 0):
|
||||||
ctx = cl.Context(devices=gpus)
|
ctx = cl.Context(devices=gpus)
|
||||||
queue = cl.CommandQueue(ctx)
|
queue = cl.CommandQueue(ctx)
|
||||||
full_path = os.path.dirname(os.path.realpath(__file__))
|
f = open(os.path.join(codePath(), "bitmsghash", 'bitmsghash.cl'), 'r')
|
||||||
f = open(os.path.join(full_path, "bitmsghash", 'bitmsghash.cl'), 'r')
|
|
||||||
fstr = ''.join(f.readlines())
|
fstr = ''.join(f.readlines())
|
||||||
program = cl.Program(ctx, fstr).build(options="")
|
program = cl.Program(ctx, fstr).build(options="")
|
||||||
|
logger.info("Loaded OpenCL kernel")
|
||||||
else:
|
else:
|
||||||
print "No OpenCL GPUs found"
|
logger.info("No OpenCL GPUs found")
|
||||||
ctx = False
|
ctx = False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print "opencl fail: " + str(e)
|
logger.error("OpenCL fail: ", exc_info=True)
|
||||||
ctx = False
|
ctx = False
|
||||||
|
|
||||||
def has_opencl():
|
def has_opencl():
|
||||||
|
global ctx
|
||||||
return (ctx != False)
|
return (ctx != False)
|
||||||
|
|
||||||
def do_opencl_pow(hash, target):
|
def do_opencl_pow(hash, target):
|
||||||
|
global ctx, queue, program, gpus, hash_dt
|
||||||
|
|
||||||
output = numpy.zeros(1, dtype=[('v', numpy.uint64, 1)])
|
output = numpy.zeros(1, dtype=[('v', numpy.uint64, 1)])
|
||||||
if (ctx == False):
|
if (ctx == False):
|
||||||
return output[0][0]
|
return output[0][0]
|
||||||
|
@ -62,11 +76,14 @@ def do_opencl_pow(hash, target):
|
||||||
queue.finish()
|
queue.finish()
|
||||||
progress += globamt
|
progress += globamt
|
||||||
sofar = time.time() - start
|
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
|
taken = time.time() - start
|
||||||
print progress, taken
|
# logger.debug("Took %d tries.", progress)
|
||||||
return output[0][0]
|
return output[0][0]
|
||||||
|
|
||||||
|
if libAvailable:
|
||||||
|
initCL()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
target = 54227212183L
|
target = 54227212183L
|
||||||
initialHash = "3758f55b5a8d902fd3597e4ce6a2d3f23daff735f65d9698c270987f4e67ad590b93f3ffeba0ef2fd08a8dc2f87b68ae5a0dc819ab57f22ad2c4c9c8618a43b3".decode("hex")
|
initialHash = "3758f55b5a8d902fd3597e4ce6a2d3f23daff735f65d9698c270987f4e67ad590b93f3ffeba0ef2fd08a8dc2f87b68ae5a0dc819ab57f22ad2c4c9c8618a43b3".decode("hex")
|
||||||
|
|
|
@ -4,9 +4,10 @@
|
||||||
import hashlib
|
import hashlib
|
||||||
from struct import unpack, pack
|
from struct import unpack, pack
|
||||||
import sys
|
import sys
|
||||||
from shared import config, frozen, codePath
|
from debug import logger
|
||||||
import shared
|
from shared import config, frozen, codePath, shutdown, safeConfigGetBoolean, UISignalQueue
|
||||||
import openclpow
|
import openclpow
|
||||||
|
import tr
|
||||||
import os
|
import os
|
||||||
import ctypes
|
import ctypes
|
||||||
|
|
||||||
|
@ -17,12 +18,20 @@ if "win32" == sys.platform:
|
||||||
else:
|
else:
|
||||||
bitmsglib = 'bitmsghash64.dll'
|
bitmsglib = 'bitmsghash64.dll'
|
||||||
try:
|
try:
|
||||||
|
# MSVS
|
||||||
bso = ctypes.WinDLL(os.path.join(codePath(), "bitmsghash", bitmsglib))
|
bso = ctypes.WinDLL(os.path.join(codePath(), "bitmsghash", bitmsglib))
|
||||||
|
logger.info("Loaded C PoW DLL (stdcall) %s", bitmsglib)
|
||||||
|
except:
|
||||||
|
try:
|
||||||
|
# MinGW
|
||||||
|
bso = ctypes.CDLL(os.path.join(codePath(), "bitmsghash", bitmsglib))
|
||||||
|
logger.info("Loaded C PoW DLL (cdecl) %s", bitmsglib)
|
||||||
except:
|
except:
|
||||||
bso = None
|
bso = None
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
bso = ctypes.CDLL(os.path.join(codePath(), "bitmsghash", bitmsglib))
|
bso = ctypes.CDLL(os.path.join(codePath(), "bitmsghash", bitmsglib))
|
||||||
|
logger.info("Loaded C PoW DLL %s", bitmsglib)
|
||||||
except:
|
except:
|
||||||
bso = None
|
bso = None
|
||||||
if bso:
|
if bso:
|
||||||
|
@ -58,16 +67,17 @@ def _pool_worker(nonce, initialHash, target, pool_size):
|
||||||
return [trialValue, nonce]
|
return [trialValue, nonce]
|
||||||
|
|
||||||
def _doSafePoW(target, initialHash):
|
def _doSafePoW(target, initialHash):
|
||||||
print "Safe POW\n"
|
logger.debug("Safe PoW start")
|
||||||
nonce = 0
|
nonce = 0
|
||||||
trialValue = float('inf')
|
trialValue = float('inf')
|
||||||
while trialValue > target:
|
while trialValue > target:
|
||||||
nonce += 1
|
nonce += 1
|
||||||
trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8])
|
trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8])
|
||||||
|
logger.debug("Safe PoW done")
|
||||||
return [trialValue, nonce]
|
return [trialValue, nonce]
|
||||||
|
|
||||||
def _doFastPoW(target, initialHash):
|
def _doFastPoW(target, initialHash):
|
||||||
print "Fast POW\n"
|
logger.debug("Fast PoW start")
|
||||||
import time
|
import time
|
||||||
from multiprocessing import Pool, cpu_count
|
from multiprocessing import Pool, cpu_count
|
||||||
try:
|
try:
|
||||||
|
@ -85,7 +95,7 @@ def _doFastPoW(target, initialHash):
|
||||||
for i in range(pool_size):
|
for i in range(pool_size):
|
||||||
result.append(pool.apply_async(_pool_worker, args = (i, initialHash, target, pool_size)))
|
result.append(pool.apply_async(_pool_worker, args = (i, initialHash, target, pool_size)))
|
||||||
while True:
|
while True:
|
||||||
if shared.shutdown >= 1:
|
if shutdown >= 1:
|
||||||
pool.terminate()
|
pool.terminate()
|
||||||
while True:
|
while True:
|
||||||
time.sleep(10) # Don't let this thread return here; it will return nothing and cause an exception in bitmessagemain.py
|
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()
|
result = result[i].get()
|
||||||
pool.terminate()
|
pool.terminate()
|
||||||
pool.join() #Wait for the workers to exit...
|
pool.join() #Wait for the workers to exit...
|
||||||
|
logger.debug("Fast PoW done")
|
||||||
return result[0], result[1]
|
return result[0], result[1]
|
||||||
time.sleep(0.2)
|
time.sleep(0.2)
|
||||||
|
|
||||||
def _doCPoW(target, initialHash):
|
def _doCPoW(target, initialHash):
|
||||||
h = initialHash
|
h = initialHash
|
||||||
m = target
|
m = target
|
||||||
out_h = ctypes.pointer(ctypes.create_string_buffer(h, 64))
|
out_h = ctypes.pointer(ctypes.create_string_buffer(h, 64))
|
||||||
out_m = ctypes.c_ulonglong(m)
|
out_m = ctypes.c_ulonglong(m)
|
||||||
print "C PoW start"
|
logger.debug("C PoW start")
|
||||||
nonce = bmpow(out_h, out_m)
|
nonce = bmpow(out_h, out_m)
|
||||||
trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8])
|
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]
|
return [trialValue, nonce]
|
||||||
|
|
||||||
def _doGPUPoW(target, initialHash):
|
def _doGPUPoW(target, initialHash):
|
||||||
print "GPU PoW start"
|
logger.debug("GPU PoW start")
|
||||||
nonce = openclpow.do_opencl_pow(initialHash.encode("hex"), target)
|
nonce = openclpow.do_opencl_pow(initialHash.encode("hex"), target)
|
||||||
trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8])
|
trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8])
|
||||||
#print "{} - value {} < {}".format(nonce, trialValue, target)
|
#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]
|
return [trialValue, nonce]
|
||||||
|
|
||||||
def run(target, initialHash):
|
def run(target, initialHash):
|
||||||
target = int(target)
|
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)
|
# trialvalue1, nonce1 = _doGPUPoW(target, initialHash)
|
||||||
# trialvalue, nonce = _doFastPoW(target, initialHash)
|
# trialvalue, nonce = _doFastPoW(target, initialHash)
|
||||||
# print "GPU: %s, %s" % (trialvalue1, nonce1)
|
# print "GPU: %s, %s" % (trialvalue1, nonce1)
|
||||||
|
@ -133,10 +151,6 @@ def run(target, initialHash):
|
||||||
return _doCPoW(target, initialHash)
|
return _doCPoW(target, initialHash)
|
||||||
except:
|
except:
|
||||||
pass # fallback
|
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:
|
try:
|
||||||
return _doFastPoW(target, initialHash)
|
return _doFastPoW(target, initialHash)
|
||||||
except:
|
except:
|
||||||
|
|
Reference in New Issue
Block a user