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
This commit is contained in:
Peter Šurda 2016-11-10 21:43:10 +01:00
parent 756f85c9f0
commit e9a3ef465c
Signed by untrusted user: PeterSurda
GPG Key ID: 0C5F50C0B5F37D87
5 changed files with 84 additions and 67 deletions

View File

@ -2408,8 +2408,8 @@ class MyForm(settingsmixin.SMainWindow):
shared.config.set('bitmessagesettings', 'defaultpayloadlengthextrabytes', str(int(float( shared.config.set('bitmessagesettings', 'defaultpayloadlengthextrabytes', str(int(float(
self.settingsDialogInstance.ui.lineEditSmallMessageDifficulty.text()) * shared.networkDefaultPayloadLengthExtraBytes))) self.settingsDialogInstance.ui.lineEditSmallMessageDifficulty.text()) * shared.networkDefaultPayloadLengthExtraBytes)))
if openclpow.has_opencl() and self.settingsDialogInstance.ui.checkBoxOpenCL.isChecked() != shared.safeConfigGetBoolean("bitmessagesettings", "opencl"): if self.settingsDialogInstance.ui.checkBoxOpenCL.currentText().toUtf8() != shared.safeConfigGet("bitmessagesettings", "opencl"):
shared.config.set('bitmessagesettings', 'opencl', str(self.settingsDialogInstance.ui.checkBoxOpenCL.isChecked())) shared.config.set('bitmessagesettings', 'opencl', self.settingsDialogInstance.ui.checkBoxOpenCL.currentText().toUtf8())
acceptableDifficultyChanged = False acceptableDifficultyChanged = False
@ -4082,14 +4082,18 @@ class settingsDialog(QtGui.QDialog):
'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes')) / shared.networkDefaultPayloadLengthExtraBytes))) 'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes')) / shared.networkDefaultPayloadLengthExtraBytes)))
# OpenCL # OpenCL
if openclpow.has_opencl(): if openclpow.openclAvailable():
self.ui.checkBoxOpenCL.setEnabled(True) self.ui.comboBoxOpenCL.setEnabled(True)
else: else:
self.ui.checkBoxOpenCL.setEnabled(False) self.ui.comboBoxOpenCL.setEnabled(False)
if shared.safeConfigGetBoolean("bitmessagesettings", "opencl"): self.ui.comboBoxOpenCL.clear()
self.ui.checkBoxOpenCL.setChecked(True) self.ui.comboBoxOpenCL.addItem("None")
else: self.ui.comboBoxOpenCL.addItems(openclpow.vendors)
self.ui.checkBoxOpenCL.setChecked(False) 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 # Namecoin integration tab
nmctype = shared.config.get('bitmessagesettings', 'namecoinrpctype') nmctype = shared.config.get('bitmessagesettings', 'namecoinrpctype')

View File

@ -298,9 +298,9 @@ class Ui_settingsDialog(object):
self.labelOpenCL = QtGui.QLabel(self.tabMaxAcceptableDifficulty) self.labelOpenCL = QtGui.QLabel(self.tabMaxAcceptableDifficulty)
self.labelOpenCL.setObjectName(_fromUtf8("labelOpenCL")) self.labelOpenCL.setObjectName(_fromUtf8("labelOpenCL"))
self.gridLayout_7.addWidget(self.labelOpenCL, 4, 0, 1, 1) self.gridLayout_7.addWidget(self.labelOpenCL, 4, 0, 1, 1)
self.checkBoxOpenCL = QtGui.QCheckBox(self.tabMaxAcceptableDifficulty) self.comboBoxOpenCL = QtGui.QComboBox(self.tabMaxAcceptableDifficulty)
self.checkBoxOpenCL.setObjectName = (_fromUtf8("checkBoxOpenCL")) self.comboBoxOpenCL.setObjectName = (_fromUtf8("comboBoxOpenCL"))
self.gridLayout_7.addWidget(self.checkBoxOpenCL, 4, 1, 1, 1) self.gridLayout_7.addWidget(self.comboBoxOpenCL, 4, 1, 1, 1)
self.tabWidgetSettings.addTab(self.tabMaxAcceptableDifficulty, _fromUtf8("")) self.tabWidgetSettings.addTab(self.tabMaxAcceptableDifficulty, _fromUtf8(""))
self.tabNamecoin = QtGui.QWidget() self.tabNamecoin = QtGui.QWidget()
self.tabNamecoin.setObjectName(_fromUtf8("tabNamecoin")) 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_13.setText(_translate("settingsDialog", "Maximum acceptable total difficulty:", None))
self.label_14.setText(_translate("settingsDialog", "Maximum acceptable small message 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.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", "<html><head/><body><p>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 <span style=\" font-style:italic;\">test. </span></p><p>(Getting your own Bitmessage address into Namecoin is still rather difficult).</p><p>Bitmessage can use either namecoind directly or a running nmcontrol instance.</p></body></html>", None)) self.label_16.setText(_translate("settingsDialog", "<html><head/><body><p>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 <span style=\" font-style:italic;\">test. </span></p><p>(Getting your own Bitmessage address into Namecoin is still rather difficult).</p><p>Bitmessage can use either namecoind directly or a running nmcontrol instance.</p></body></html>", None))
self.label_17.setText(_translate("settingsDialog", "Host:", None)) self.label_17.setText(_translate("settingsDialog", "Host:", None))
self.label_18.setText(_translate("settingsDialog", "Port:", None)) self.label_18.setText(_translate("settingsDialog", "Port:", None))

View File

@ -9,7 +9,7 @@ from debug import logger
from foldertree import AccountMixin from foldertree import AccountMixin
from helper_sql import * from helper_sql import *
from l10n import getTranslationLanguage from l10n import getTranslationLanguage
from openclpow import has_opencl from openclpow import openclAvailable, openclEnabled
from proofofwork import bmpow from proofofwork import bmpow
from pyelliptic.openssl import OpenSSL from pyelliptic.openssl import OpenSSL
import shared import shared
@ -107,7 +107,7 @@ def createSupportMessage(myapp):
portablemode = "True" if shared.appdata == shared.lookupExeFolder() else "False" portablemode = "True" if shared.appdata == shared.lookupExeFolder() else "False"
cpow = "True" if bmpow else "False" cpow = "True" if bmpow else "False"
#cpow = QtGui.QApplication.translate("Support", cpow) #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) #openclpow = QtGui.QApplication.translate("Support", openclpow)
locale = getTranslationLanguage() locale = getTranslationLanguage()
try: try:

View File

@ -5,7 +5,7 @@ import hashlib
import random import random
import os import os
from shared import codePath, safeConfigGetBoolean, shutdown from shared import codePath, safeConfigGetBoolean, safeConfigGet, shutdown
from debug import logger from debug import logger
libAvailable = True libAvailable = True
@ -13,6 +13,8 @@ ctx = False
queue = False queue = False
program = False program = False
gpus = [] gpus = []
enabledGpus = []
vendors = []
hash_dt = None hash_dt = None
try: try:
@ -22,13 +24,20 @@ except:
libAvailable = False libAvailable = False
def initCL(): def initCL():
global ctx, queue, program, gpus, hash_dt global ctx, queue, program, gpus, hash_dt, vendors
try: try:
hash_dt = numpy.dtype([('target', numpy.uint64), ('v', numpy.str_, 73)]) hash_dt = numpy.dtype([('target', numpy.uint64), ('v', numpy.str_, 73)])
for platform in cl.get_platforms(): try:
gpus.extend(platform.get_devices(device_type=cl.device_type.GPU)) for platform in cl.get_platforms():
if (len(gpus) > 0): gpus.extend(platform.get_devices(device_type=cl.device_type.GPU))
ctx = cl.Context(devices=gpus) 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) queue = cl.CommandQueue(ctx)
f = open(os.path.join(codePath(), "bitmsghash", 'bitmsghash.cl'), 'r') f = open(os.path.join(codePath(), "bitmsghash", 'bitmsghash.cl'), 'r')
fstr = ''.join(f.readlines()) fstr = ''.join(f.readlines())
@ -36,60 +45,64 @@ def initCL():
logger.info("Loaded OpenCL kernel") logger.info("Loaded OpenCL kernel")
else: else:
logger.info("No OpenCL GPUs found") logger.info("No OpenCL GPUs found")
ctx = False enabledGpus = []
except Exception as e: except Exception as e:
logger.error("OpenCL fail: ", exc_info=True) logger.error("OpenCL fail: ", exc_info=True)
ctx = False enabledGpus = []
def has_opencl(): def openclAvailable():
global ctx global gpus
return (ctx != False) return (len(gpus) > 0)
def openclEnabled():
global enabledGpus
return (len(enabledGpus) > 0)
def do_opencl_pow(hash, target): 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)]) output = numpy.zeros(1, dtype=[('v', numpy.uint64, 1)])
if (ctx == False): if (len(enabledGpus) == 0):
return output[0][0] return output[0][0]
data = numpy.zeros(1, dtype=hash_dt, order='C') data = numpy.zeros(1, dtype=hash_dt, order='C')
data[0]['v'] = ("0000000000000000" + hash).decode("hex") data[0]['v'] = ("0000000000000000" + hash).decode("hex")
data[0]['target'] = target data[0]['target'] = target
hash_buf = cl.Buffer(ctx, cl.mem_flags.READ_ONLY | cl.mem_flags.COPY_HOST_PTR, hostbuf=data) 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) dest_buf = cl.Buffer(ctx, cl.mem_flags.WRITE_ONLY, output.nbytes)
kernel = program.kernel_sha512 kernel = program.kernel_sha512
worksize = kernel.get_work_group_info(cl.kernel_work_group_info.WORK_GROUP_SIZE, gpus[0]) 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(0, hash_buf)
kernel.set_arg(1, dest_buf) kernel.set_arg(1, dest_buf)
start = time.time() start = time.time()
progress = 0 progress = 0
globamt = worksize*2000 globamt = worksize*2000
while output[0][0] == 0 and shutdown == 0: while output[0][0] == 0 and shutdown == 0:
kernel.set_arg(2, pack("<Q", progress)) kernel.set_arg(2, pack("<Q", progress))
cl.enqueue_nd_range_kernel(queue, kernel, (globamt,), (worksize,)) cl.enqueue_nd_range_kernel(queue, kernel, (globamt,), (worksize,))
cl.enqueue_read_buffer(queue, dest_buf, output) cl.enqueue_read_buffer(queue, dest_buf, output)
queue.finish() queue.finish()
progress += globamt progress += globamt
sofar = time.time() - start sofar = time.time() - start
# logger.debug("Working for %.3fs, %.2f Mh/s", sofar, (progress / sofar) / 1000000) # logger.debug("Working for %.3fs, %.2f Mh/s", sofar, (progress / sofar) / 1000000)
if shutdown != 0: if shutdown != 0:
raise Exception ("Interrupted") raise Exception ("Interrupted")
taken = time.time() - start taken = time.time() - start
# logger.debug("Took %d tries.", progress) # logger.debug("Took %d tries.", progress)
return output[0][0] return output[0][0]
if libAvailable: if libAvailable:
initCL() initCL()
if __name__ == "__main__": if __name__ == "__main__":
target = 54227212183L target = 54227212183L
initialHash = "3758f55b5a8d902fd3597e4ce6a2d3f23daff735f65d9698c270987f4e67ad590b93f3ffeba0ef2fd08a8dc2f87b68ae5a0dc819ab57f22ad2c4c9c8618a43b3".decode("hex") initialHash = "3758f55b5a8d902fd3597e4ce6a2d3f23daff735f65d9698c270987f4e67ad590b93f3ffeba0ef2fd08a8dc2f87b68ae5a0dc819ab57f22ad2c4c9c8618a43b3".decode("hex")
nonce = do_opencl_pow(initialHash.encode("hex"), target) nonce = 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)

View File

@ -108,10 +108,10 @@ def _doGPUPoW(target, initialHash):
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)
if 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.'))) 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) 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.") raise Exception("GPU did not calculate correctly.")
if shared.shutdown != 0: if shared.shutdown != 0:
raise StopIteration("Interrupted") raise StopIteration("Interrupted")
@ -144,7 +144,7 @@ def estimate(difficulty, format = False):
return ret return ret
def getPowType(): def getPowType():
if shared.safeConfigGetBoolean('bitmessagesettings', 'opencl') and openclpow.has_opencl(): if openclpow.openclEnabled():
return "OpenCL" return "OpenCL"
if bmpow: if bmpow:
return "C" return "C"
@ -154,7 +154,7 @@ def run(target, initialHash):
if shared.shutdown != 0: if shared.shutdown != 0:
raise raise
target = int(target) target = int(target)
if shared.safeConfigGetBoolean('bitmessagesettings', 'opencl') and openclpow.has_opencl(): if openclpow.openclEnabled():
# 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)