""" Module for Proof of Work using OpenCL """ import logging import os from struct import pack import paths from bmconfigparser import BMConfigParser from state import shutdown try: import numpy import pyopencl as cl libAvailable = True except ImportError: libAvailable = False logger = logging.getLogger('default') ctx = False queue = False program = False gpus = [] enabledGpus = [] vendors = [] hash_dt = None def initCL(): """Initlialise OpenCL engine""" global ctx, queue, program, hash_dt # pylint: disable=global-statement if libAvailable is False: return del enabledGpus[:] del vendors[:] del gpus[:] ctx = False try: hash_dt = numpy.dtype([('target', numpy.uint64), ('v', numpy.str_, 73)]) try: for platform in cl.get_platforms(): gpus.extend(platform.get_devices(device_type=cl.device_type.GPU)) if BMConfigParser().safeGet("bitmessagesettings", "opencl") == platform.vendor: enabledGpus.extend(platform.get_devices( device_type=cl.device_type.GPU)) if platform.vendor not in vendors: vendors.append(platform.vendor) except: pass if enabledGpus: ctx = cl.Context(devices=enabledGpus) queue = cl.CommandQueue(ctx) f = open(os.path.join(paths.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") del enabledGpus[:] except Exception: logger.error("OpenCL fail: ", exc_info=True) del enabledGpus[:] def openclAvailable(): """Are there any OpenCL GPUs available?""" return bool(gpus) def openclEnabled(): """Is OpenCL enabled (and available)?""" return bool(enabledGpus) def do_opencl_pow(hash_, target): """Perform PoW using OpenCL""" output = numpy.zeros(1, dtype=[('v', numpy.uint64, 1)]) if not enabledGpus: return output[0][0] data = numpy.zeros(1, dtype=hash_dt, order='C') data[0]['v'] = ("0000000000000000" + hash_).decode("hex") data[0]['target'] = target hash_buf = cl.Buffer(ctx, cl.mem_flags.READ_ONLY | cl.mem_flags.COPY_HOST_PTR, hostbuf=data) dest_buf = cl.Buffer(ctx, cl.mem_flags.WRITE_ONLY, output.nbytes) kernel = program.kernel_sha512 worksize = kernel.get_work_group_info(cl.kernel_work_group_info.WORK_GROUP_SIZE, enabledGpus[0]) kernel.set_arg(0, hash_buf) kernel.set_arg(1, dest_buf) progress = 0 globamt = worksize * 2000 while output[0][0] == 0 and shutdown == 0: kernel.set_arg(2, pack("