From e9a3ef465ca68dd182b54437f061944a9d106786 Mon Sep 17 00:00:00 2001 From: Peter Surda Date: Thu, 10 Nov 2016 21:43:10 +0100 Subject: [PATCH] OpenCL vendor selector - when you have multiple OpenCL drivers at the same time, e.g. intel and nvidia, they won't mix leading to crashes. This patch makes it possible to select which driver to use by listing the available vendors --- src/bitmessageqt/__init__.py | 22 ++++--- src/bitmessageqt/settings.py | 8 +-- src/bitmessageqt/support.py | 4 +- src/openclpow.py | 109 ++++++++++++++++++++--------------- src/proofofwork.py | 8 +-- 5 files changed, 84 insertions(+), 67 deletions(-) diff --git a/src/bitmessageqt/__init__.py b/src/bitmessageqt/__init__.py index 6ddafb35..ff4bfbcf 100644 --- a/src/bitmessageqt/__init__.py +++ b/src/bitmessageqt/__init__.py @@ -2408,8 +2408,8 @@ class MyForm(settingsmixin.SMainWindow): shared.config.set('bitmessagesettings', 'defaultpayloadlengthextrabytes', str(int(float( self.settingsDialogInstance.ui.lineEditSmallMessageDifficulty.text()) * shared.networkDefaultPayloadLengthExtraBytes))) - if openclpow.has_opencl() and self.settingsDialogInstance.ui.checkBoxOpenCL.isChecked() != shared.safeConfigGetBoolean("bitmessagesettings", "opencl"): - shared.config.set('bitmessagesettings', 'opencl', str(self.settingsDialogInstance.ui.checkBoxOpenCL.isChecked())) + if self.settingsDialogInstance.ui.checkBoxOpenCL.currentText().toUtf8() != shared.safeConfigGet("bitmessagesettings", "opencl"): + shared.config.set('bitmessagesettings', 'opencl', self.settingsDialogInstance.ui.checkBoxOpenCL.currentText().toUtf8()) acceptableDifficultyChanged = False @@ -4082,14 +4082,18 @@ class settingsDialog(QtGui.QDialog): 'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes')) / shared.networkDefaultPayloadLengthExtraBytes))) # OpenCL - if openclpow.has_opencl(): - self.ui.checkBoxOpenCL.setEnabled(True) + if openclpow.openclAvailable(): + self.ui.comboBoxOpenCL.setEnabled(True) else: - self.ui.checkBoxOpenCL.setEnabled(False) - if shared.safeConfigGetBoolean("bitmessagesettings", "opencl"): - self.ui.checkBoxOpenCL.setChecked(True) - else: - self.ui.checkBoxOpenCL.setChecked(False) + self.ui.comboBoxOpenCL.setEnabled(False) + self.ui.comboBoxOpenCL.clear() + self.ui.comboBoxOpenCL.addItem("None") + self.ui.comboBoxOpenCL.addItems(openclpow.vendors) + self.ui.comboBoxOpenCL.setCurrentIndex(0) + for i in range(self.ui.comboBoxOpenCL.count()): + if self.ui.comboBoxOpenCL.itemText(i) == shared.safeConfigGet('bitmessagesettings', 'opencl'): + self.ui.comboBoxOpenCL.setCurrentIndex(i) + break # Namecoin integration tab nmctype = shared.config.get('bitmessagesettings', 'namecoinrpctype') diff --git a/src/bitmessageqt/settings.py b/src/bitmessageqt/settings.py index 9b86ea5a..a67c7f42 100644 --- a/src/bitmessageqt/settings.py +++ b/src/bitmessageqt/settings.py @@ -298,9 +298,9 @@ class Ui_settingsDialog(object): self.labelOpenCL = QtGui.QLabel(self.tabMaxAcceptableDifficulty) self.labelOpenCL.setObjectName(_fromUtf8("labelOpenCL")) self.gridLayout_7.addWidget(self.labelOpenCL, 4, 0, 1, 1) - self.checkBoxOpenCL = QtGui.QCheckBox(self.tabMaxAcceptableDifficulty) - self.checkBoxOpenCL.setObjectName = (_fromUtf8("checkBoxOpenCL")) - self.gridLayout_7.addWidget(self.checkBoxOpenCL, 4, 1, 1, 1) + self.comboBoxOpenCL = QtGui.QComboBox(self.tabMaxAcceptableDifficulty) + self.comboBoxOpenCL.setObjectName = (_fromUtf8("comboBoxOpenCL")) + self.gridLayout_7.addWidget(self.comboBoxOpenCL, 4, 1, 1, 1) self.tabWidgetSettings.addTab(self.tabMaxAcceptableDifficulty, _fromUtf8("")) self.tabNamecoin = QtGui.QWidget() self.tabNamecoin.setObjectName(_fromUtf8("tabNamecoin")) @@ -475,7 +475,7 @@ class Ui_settingsDialog(object): self.label_13.setText(_translate("settingsDialog", "Maximum acceptable total difficulty:", None)) self.label_14.setText(_translate("settingsDialog", "Maximum acceptable small message difficulty:", None)) self.tabWidgetSettings.setTabText(self.tabWidgetSettings.indexOf(self.tabMaxAcceptableDifficulty), _translate("settingsDialog", "Max acceptable difficulty", None)) - self.labelOpenCL.setText(_translate("settingsDialog", "Hardware GPU acceleration (OpenCL)", None)) + self.labelOpenCL.setText(_translate("settingsDialog", "Hardware GPU acceleration (OpenCL):", None)) self.label_16.setText(_translate("settingsDialog", "

Bitmessage can utilize a different Bitcoin-based program called Namecoin to make addresses human-friendly. For example, instead of having to tell your friend your long Bitmessage address, you can simply tell him to send a message to test.

(Getting your own Bitmessage address into Namecoin is still rather difficult).

Bitmessage can use either namecoind directly or a running nmcontrol instance.

", None)) self.label_17.setText(_translate("settingsDialog", "Host:", None)) self.label_18.setText(_translate("settingsDialog", "Port:", None)) diff --git a/src/bitmessageqt/support.py b/src/bitmessageqt/support.py index b68619cd..0f52ec04 100644 --- a/src/bitmessageqt/support.py +++ b/src/bitmessageqt/support.py @@ -9,7 +9,7 @@ from debug import logger from foldertree import AccountMixin from helper_sql import * from l10n import getTranslationLanguage -from openclpow import has_opencl +from openclpow import openclAvailable, openclEnabled from proofofwork import bmpow from pyelliptic.openssl import OpenSSL import shared @@ -107,7 +107,7 @@ def createSupportMessage(myapp): portablemode = "True" if shared.appdata == shared.lookupExeFolder() else "False" cpow = "True" if bmpow else "False" #cpow = QtGui.QApplication.translate("Support", cpow) - openclpow = "True" if shared.safeConfigGetBoolean('bitmessagesettings', 'opencl') and has_opencl() else "False" + openclpow = str(shared.safeConfigGet('bitmessagesettings', 'opencl')) if openclEnabled() else "None" #openclpow = QtGui.QApplication.translate("Support", openclpow) locale = getTranslationLanguage() try: diff --git a/src/openclpow.py b/src/openclpow.py index b643ca57..2f7f0158 100644 --- a/src/openclpow.py +++ b/src/openclpow.py @@ -5,7 +5,7 @@ import hashlib import random import os -from shared import codePath, safeConfigGetBoolean, shutdown +from shared import codePath, safeConfigGetBoolean, safeConfigGet, shutdown from debug import logger libAvailable = True @@ -13,6 +13,8 @@ ctx = False queue = False program = False gpus = [] +enabledGpus = [] +vendors = [] hash_dt = None try: @@ -22,13 +24,20 @@ except: libAvailable = False def initCL(): - global ctx, queue, program, gpus, hash_dt + global ctx, queue, program, gpus, hash_dt, vendors 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) + try: + for platform in cl.get_platforms(): + gpus.extend(platform.get_devices(device_type=cl.device_type.GPU)) + if safeConfigGet("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 (len(enabledGpus) > 0): + ctx = cl.Context(devices=enabledGpus) queue = cl.CommandQueue(ctx) f = open(os.path.join(codePath(), "bitmsghash", 'bitmsghash.cl'), 'r') fstr = ''.join(f.readlines()) @@ -36,60 +45,64 @@ def initCL(): logger.info("Loaded OpenCL kernel") else: logger.info("No OpenCL GPUs found") - ctx = False + enabledGpus = [] except Exception as e: logger.error("OpenCL fail: ", exc_info=True) - ctx = False + enabledGpus = [] -def has_opencl(): - global ctx - return (ctx != False) +def openclAvailable(): + global gpus + return (len(gpus) > 0) + +def openclEnabled(): + global enabledGpus + return (len(enabledGpus) > 0) def do_opencl_pow(hash, target): - global ctx, queue, program, gpus, hash_dt + global ctx, queue, program, enabledGpus, hash_dt - output = numpy.zeros(1, dtype=[('v', numpy.uint64, 1)]) - if (ctx == False): - 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, gpus[0]) + output = numpy.zeros(1, dtype=[('v', numpy.uint64, 1)]) + if (len(enabledGpus) == 0): + return output[0][0] - kernel.set_arg(0, hash_buf) - kernel.set_arg(1, dest_buf) + data = numpy.zeros(1, dtype=hash_dt, order='C') + data[0]['v'] = ("0000000000000000" + hash).decode("hex") + data[0]['target'] = target - start = time.time() - progress = 0 - globamt = worksize*2000 + 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) - while output[0][0] == 0 and shutdown == 0: - kernel.set_arg(2, pack("Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8]) - print "{} - value {} < {}".format(nonce, trialValue, target) + target = 54227212183L + initialHash = "3758f55b5a8d902fd3597e4ce6a2d3f23daff735f65d9698c270987f4e67ad590b93f3ffeba0ef2fd08a8dc2f87b68ae5a0dc819ab57f22ad2c4c9c8618a43b3".decode("hex") + nonce = 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) diff --git a/src/proofofwork.py b/src/proofofwork.py index b4ce69b2..701f34ba 100644 --- a/src/proofofwork.py +++ b/src/proofofwork.py @@ -108,10 +108,10 @@ def _doGPUPoW(target, initialHash): trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8]) #print "{} - value {} < {}".format(nonce, trialValue, target) if trialValue > target: - deviceNames = ", ".join(gpu.name for gpu in openclpow.gpus) + deviceNames = ", ".join(gpu.name for gpu in openclpow.enabledGpus) shared.UISignalQueue.put(('updateStatusBar', tr._translate("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 + openclpow.enabledGpus = [] raise Exception("GPU did not calculate correctly.") if shared.shutdown != 0: raise StopIteration("Interrupted") @@ -144,7 +144,7 @@ def estimate(difficulty, format = False): return ret def getPowType(): - if shared.safeConfigGetBoolean('bitmessagesettings', 'opencl') and openclpow.has_opencl(): + if openclpow.openclEnabled(): return "OpenCL" if bmpow: return "C" @@ -154,7 +154,7 @@ def run(target, initialHash): if shared.shutdown != 0: raise target = int(target) - if shared.safeConfigGetBoolean('bitmessagesettings', 'opencl') and openclpow.has_opencl(): + if openclpow.openclEnabled(): # trialvalue1, nonce1 = _doGPUPoW(target, initialHash) # trialvalue, nonce = _doFastPoW(target, initialHash) # print "GPU: %s, %s" % (trialvalue1, nonce1)