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(
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')

View File

@ -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", "<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_18.setText(_translate("settingsDialog", "Port:", None))

View File

@ -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:

View File

@ -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", progress))
cl.enqueue_nd_range_kernel(queue, kernel, (globamt,), (worksize,))
cl.enqueue_read_buffer(queue, dest_buf, output)
queue.finish()
progress += globamt
sofar = time.time() - start
# logger.debug("Working for %.3fs, %.2f Mh/s", sofar, (progress / sofar) / 1000000)
if shutdown != 0:
raise Exception ("Interrupted")
taken = time.time() - start
# logger.debug("Took %d tries.", progress)
return output[0][0]
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)
start = time.time()
progress = 0
globamt = worksize*2000
while output[0][0] == 0 and shutdown == 0:
kernel.set_arg(2, pack("<Q", progress))
cl.enqueue_nd_range_kernel(queue, kernel, (globamt,), (worksize,))
cl.enqueue_read_buffer(queue, dest_buf, output)
queue.finish()
progress += globamt
sofar = time.time() - start
# logger.debug("Working for %.3fs, %.2f Mh/s", sofar, (progress / sofar) / 1000000)
if shutdown != 0:
raise Exception ("Interrupted")
taken = time.time() - start
# logger.debug("Took %d tries.", progress)
return output[0][0]
if libAvailable:
initCL()
if __name__ == "__main__":
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)
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)

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])
#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)