Added POW settings to settings window
This commit is contained in:
parent
2c7d677ccf
commit
373157db45
|
@ -55,6 +55,7 @@ import sound
|
||||||
import re
|
import re
|
||||||
import bitmessage_icons_rc # Loads icon resources
|
import bitmessage_icons_rc # Loads icon resources
|
||||||
import workprover.utils
|
import workprover.utils
|
||||||
|
import singleworker
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -2616,9 +2617,34 @@ class MyForm(settingsmixin.SMainWindow):
|
||||||
BMConfigParser().set('bitmessagesettings', 'defaultpayloadlengthextrabytes', str(int(float(
|
BMConfigParser().set('bitmessagesettings', 'defaultpayloadlengthextrabytes', str(int(float(
|
||||||
self.settingsDialogInstance.ui.lineEditSmallMessageDifficulty.text()) * defaults.networkDefaultPayloadLengthExtraBytes)))
|
self.settingsDialogInstance.ui.lineEditSmallMessageDifficulty.text()) * defaults.networkDefaultPayloadLengthExtraBytes)))
|
||||||
|
|
||||||
if self.settingsDialogInstance.ui.comboBoxOpenCL.currentText().toUtf8() != BMConfigParser().safeGet("bitmessagesettings", "opencl"):
|
if self.settingsDialogInstance.ui.radioButtonDumbSolver.isChecked():
|
||||||
BMConfigParser().set('bitmessagesettings', 'opencl', str(self.settingsDialogInstance.ui.comboBoxOpenCL.currentText()))
|
BMConfigParser().set("bitmessagesettings", "powsolver", "dumb")
|
||||||
queues.workerQueue.put(('resetPoW', ''))
|
elif self.settingsDialogInstance.ui.radioButtonForkingSolver.isChecked():
|
||||||
|
BMConfigParser().set("bitmessagesettings", "powsolver", "forking")
|
||||||
|
|
||||||
|
BMConfigParser().set(
|
||||||
|
"bitmessagesettings",
|
||||||
|
"processes",
|
||||||
|
str(self.settingsDialogInstance.ui.spinBoxForkingSolverParallelism.value())
|
||||||
|
)
|
||||||
|
elif self.settingsDialogInstance.ui.radioButtonFastSolver.isChecked():
|
||||||
|
BMConfigParser().set("bitmessagesettings", "powsolver", "fast")
|
||||||
|
|
||||||
|
BMConfigParser().set(
|
||||||
|
"bitmessagesettings",
|
||||||
|
"threads",
|
||||||
|
str(self.settingsDialogInstance.ui.spinBoxFastSolverParallelism.value())
|
||||||
|
)
|
||||||
|
elif self.settingsDialogInstance.ui.radioButtonGPUSolver.isChecked():
|
||||||
|
BMConfigParser().set("bitmessagesettings", "powsolver", "gpu")
|
||||||
|
|
||||||
|
BMConfigParser().set(
|
||||||
|
"bitmessagesettings",
|
||||||
|
"opencl",
|
||||||
|
str(self.settingsDialogInstance.ui.comboBoxGPUVendor.currentText().toUtf8())
|
||||||
|
)
|
||||||
|
|
||||||
|
singleworker.setBestSolver()
|
||||||
|
|
||||||
acceptableDifficultyChanged = False
|
acceptableDifficultyChanged = False
|
||||||
|
|
||||||
|
@ -4547,18 +4573,43 @@ class settingsDialog(QtGui.QDialog):
|
||||||
self.ui.lineEditMaxAcceptableSmallMessageDifficulty.setText(str((float(BMConfigParser().getint(
|
self.ui.lineEditMaxAcceptableSmallMessageDifficulty.setText(str((float(BMConfigParser().getint(
|
||||||
'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes')) / defaults.networkDefaultPayloadLengthExtraBytes)))
|
'bitmessagesettings', 'maxacceptablepayloadlengthextrabytes')) / defaults.networkDefaultPayloadLengthExtraBytes)))
|
||||||
|
|
||||||
# OpenCL
|
if "forking" not in singleworker.workProver.availableSolvers:
|
||||||
if openclpow.openclAvailable():
|
self.ui.radioButtonForkingSolver.setEnabled(False)
|
||||||
self.ui.comboBoxOpenCL.setEnabled(True)
|
if "fast" not in singleworker.workProver.availableSolvers:
|
||||||
else:
|
self.ui.radioButtonFastSolver.setEnabled(False)
|
||||||
self.ui.comboBoxOpenCL.setEnabled(False)
|
if "gpu" not in singleworker.workProver.availableSolvers:
|
||||||
self.ui.comboBoxOpenCL.clear()
|
self.ui.radioButtonGPUSolver.setEnabled(False)
|
||||||
self.ui.comboBoxOpenCL.addItem("None")
|
|
||||||
self.ui.comboBoxOpenCL.addItems(openclpow.vendors)
|
solverName = BMConfigParser().safeGet("bitmessagesettings", "powsolver", "gpu")
|
||||||
self.ui.comboBoxOpenCL.setCurrentIndex(0)
|
forkingSolverParallelism = BMConfigParser().safeGetInt("bitmessagesettings", "processes")
|
||||||
for i in range(self.ui.comboBoxOpenCL.count()):
|
fastSolverParallelism = BMConfigParser().safeGetInt("bitmessagesettings", "threads")
|
||||||
if self.ui.comboBoxOpenCL.itemText(i) == BMConfigParser().safeGet('bitmessagesettings', 'opencl'):
|
GPUVendor = BMConfigParser().safeGet("bitmessagesettings", "opencl")
|
||||||
self.ui.comboBoxOpenCL.setCurrentIndex(i)
|
|
||||||
|
if solverName == "dumb":
|
||||||
|
self.ui.radioButtonDumbSolver.setChecked(True)
|
||||||
|
elif solverName == "forking":
|
||||||
|
self.ui.radioButtonForkingSolver.setChecked(True)
|
||||||
|
elif solverName == "fast":
|
||||||
|
self.ui.radioButtonFastSolver.setChecked(True)
|
||||||
|
elif solverName == "gpu":
|
||||||
|
self.ui.radioButtonGPUSolver.setChecked(True)
|
||||||
|
|
||||||
|
self.ui.spinBoxForkingSolverParallelism.setValue(forkingSolverParallelism)
|
||||||
|
self.ui.spinBoxFastSolverParallelism.setValue(fastSolverParallelism)
|
||||||
|
|
||||||
|
vendors = set(singleworker.workProver.availableSolvers["gpu"].vendors)
|
||||||
|
|
||||||
|
if GPUVendor is not None:
|
||||||
|
vendors.add(GPUVendor)
|
||||||
|
|
||||||
|
self.ui.comboBoxGPUVendor.clear()
|
||||||
|
self.ui.comboBoxGPUVendor.addItems(list(vendors))
|
||||||
|
self.ui.comboBoxGPUVendor.setCurrentIndex(0)
|
||||||
|
|
||||||
|
for i in range(self.ui.comboBoxGPUVendor.count()):
|
||||||
|
if self.ui.comboBoxGPUVendor.itemText(i) == GPUVendor:
|
||||||
|
self.ui.comboBoxGPUVendor.setCurrentIndex(i)
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
# Namecoin integration tab
|
# Namecoin integration tab
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>555</width>
|
<width>616</width>
|
||||||
<height>592</height>
|
<height>592</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
@ -14,16 +14,6 @@
|
||||||
<string>Settings</string>
|
<string>Settings</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="standardButtons">
|
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QTabWidget" name="tabWidgetSettings">
|
<widget class="QTabWidget" name="tabWidgetSettings">
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
|
@ -549,13 +539,13 @@
|
||||||
<string>Max acceptable difficulty</string>
|
<string>Max acceptable difficulty</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
<layout class="QGridLayout" name="gridLayout_7">
|
<layout class="QGridLayout" name="gridLayout_7">
|
||||||
<item row="0" column="0" colspan="3">
|
<item row="2" column="1">
|
||||||
<widget class="QLabel" name="label_15">
|
<widget class="QLabel" name="label_14">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Here you may set the maximum amount of work you are willing to do to send a message to another person. Setting these values to 0 means that any value is acceptable.</string>
|
<string>Maximum acceptable small message difficulty:</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="wordWrap">
|
<property name="alignment">
|
||||||
<bool>true</bool>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -585,6 +575,32 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="0" colspan="3">
|
||||||
|
<widget class="QLabel" name="label_15">
|
||||||
|
<property name="text">
|
||||||
|
<string>Here you may set the maximum amount of work you are willing to do to send a message to another person. Setting these values to 0 means that any value is acceptable.</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="2">
|
||||||
|
<widget class="QLineEdit" name="lineEditMaxAcceptableSmallMessageDifficulty">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>70</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="1" column="2">
|
<item row="1" column="2">
|
||||||
<widget class="QLineEdit" name="lineEditMaxAcceptableTotalDifficulty">
|
<widget class="QLineEdit" name="lineEditMaxAcceptableTotalDifficulty">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
|
@ -614,33 +630,142 @@
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="3" column="0" colspan="3">
|
||||||
<widget class="QLabel" name="label_14">
|
<widget class="QGroupBox" name="groupBoxSolvers">
|
||||||
<property name="text">
|
<property name="title">
|
||||||
<string>Maximum acceptable small message difficulty:</string>
|
<string>Proof of work solver</string>
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_10">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="labelSolvers">
|
||||||
|
<property name="text">
|
||||||
|
<string>There are several worker modules to solve POW:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0" colspan="2">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayoutForkingSolver">
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="radioButtonForkingSolver">
|
||||||
|
<property name="text">
|
||||||
|
<string>Forking solver using multiple processes:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="spinBoxForkingSolverParallelism">
|
||||||
|
<property name="minimum">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>4096</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacerForkingSolver">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0" colspan="2">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayoutFastSolver">
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="radioButtonFastSolver">
|
||||||
|
<property name="text">
|
||||||
|
<string>Fast solver in C with multiple threads:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="spinBoxFastSolverParallelism">
|
||||||
|
<property name="minimum">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>4096</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacerFastSolver">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0" colspan="2">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayoutDumbSolver">
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="radioButtonDumbSolver">
|
||||||
|
<property name="text">
|
||||||
|
<string>Dumb solver</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacerDumbSolver">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0" colspan="2">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayoutGPUSolver">
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="radioButtonGPUSolver">
|
||||||
|
<property name="text">
|
||||||
|
<string>GPU solver:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="comboBoxGPUVendor"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacerGPUSolver">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="2">
|
<item row="5" column="0" colspan="3">
|
||||||
<widget class="QLineEdit" name="lineEditMaxAcceptableSmallMessageDifficulty">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>70</width>
|
|
||||||
<height>16777215</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<spacer name="verticalSpacer_3">
|
<spacer name="verticalSpacer_3">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
|
@ -653,16 +778,6 @@
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0">
|
|
||||||
<widget class="QLabel" name="labelOpenCL">
|
|
||||||
<property name="text">
|
|
||||||
<string>Hardware GPU acceleration (OpenCL):</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
|
||||||
<widget class="QComboBox" name="comboBoxOpenCL"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="tabNamecoin">
|
<widget class="QWidget" name="tabNamecoin">
|
||||||
|
@ -981,6 +1096,16 @@
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
|
@ -998,6 +1123,7 @@
|
||||||
<tabstop>checkBoxSocksListen</tabstop>
|
<tabstop>checkBoxSocksListen</tabstop>
|
||||||
<tabstop>buttonBox</tabstop>
|
<tabstop>buttonBox</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
|
<resources/>
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
<connection>
|
||||||
<sender>buttonBox</sender>
|
<sender>buttonBox</sender>
|
||||||
|
|
|
@ -221,6 +221,66 @@ def disseminateObject(nonce, expiryTime, headlessPayload, objectType, stream, ta
|
||||||
|
|
||||||
return inventoryHash, payload
|
return inventoryHash, payload
|
||||||
|
|
||||||
|
workProver = workprover.WorkProver(
|
||||||
|
os.path.join(paths.codePath(), "workprover"),
|
||||||
|
helper_random.randomBytes(32),
|
||||||
|
lambda status: queues.UISignalQueue.put(("updateWorkProverStatus", status)),
|
||||||
|
queues.workerQueue
|
||||||
|
)
|
||||||
|
|
||||||
|
debug.logger.info("Availabe solvers: %s", str(workProver.availableSolvers.keys()))
|
||||||
|
|
||||||
|
if "fast" not in workProver.availableSolvers:
|
||||||
|
queues.UISignalQueue.put(("updateStatusBar", (
|
||||||
|
tr._translate(
|
||||||
|
"proofofwork",
|
||||||
|
"C PoW module unavailable. Please build it."
|
||||||
|
), 1
|
||||||
|
)))
|
||||||
|
|
||||||
|
def setBestSolver():
|
||||||
|
solverName = bmconfigparser.BMConfigParser().safeGet("bitmessagesettings", "powsolver", "gpu")
|
||||||
|
forkingSolverParallelism = bmconfigparser.BMConfigParser().safeGetInt("bitmessagesettings", "processes")
|
||||||
|
fastSolverParallelism = bmconfigparser.BMConfigParser().safeGetInt("bitmessagesettings", "threads")
|
||||||
|
GPUVendor = bmconfigparser.BMConfigParser().safeGet("bitmessagesettings", "opencl")
|
||||||
|
|
||||||
|
if forkingSolverParallelism < 1:
|
||||||
|
forkingSolverParallelism = workProver.defaultParallelism
|
||||||
|
|
||||||
|
if fastSolverParallelism < 1:
|
||||||
|
fastSolverParallelism = workProver.defaultParallelism
|
||||||
|
|
||||||
|
maxcores = bmconfigparser.BMConfigParser().safeGetInt("bitmessagesettings", "maxcores", None)
|
||||||
|
|
||||||
|
if maxcores is not None:
|
||||||
|
forkingSolverParallelism = min(maxcores, forkingSolverParallelism)
|
||||||
|
fastSolverParallelism = min(maxcores, fastSolverParallelism)
|
||||||
|
|
||||||
|
if solverName == "gpu" and GPUVendor is None:
|
||||||
|
solverName = "fast"
|
||||||
|
|
||||||
|
while solverName not in workProver.availableSolvers:
|
||||||
|
if solverName == "gpu":
|
||||||
|
solverName = "fast"
|
||||||
|
elif solverName == "fast":
|
||||||
|
solverName = "forking"
|
||||||
|
elif solverName == "forking":
|
||||||
|
solverName = "dumb"
|
||||||
|
|
||||||
|
bmconfigparser.BMConfigParser().set("bitmessagesettings", "powsolver", solverName)
|
||||||
|
bmconfigparser.BMConfigParser().set("bitmessagesettings", "processes", str(forkingSolverParallelism))
|
||||||
|
bmconfigparser.BMConfigParser().set("bitmessagesettings", "threads", str(fastSolverParallelism))
|
||||||
|
bmconfigparser.BMConfigParser().save()
|
||||||
|
|
||||||
|
if solverName in ["dumb", "gpu"]:
|
||||||
|
workProver.commandsQueue.put(("setSolver", solverName, None))
|
||||||
|
elif solverName == "forking":
|
||||||
|
workProver.commandsQueue.put(("setSolver", "forking", forkingSolverParallelism))
|
||||||
|
elif solverName == "fast":
|
||||||
|
workProver.commandsQueue.put(("setSolver", "fast", fastSolverParallelism))
|
||||||
|
|
||||||
|
setBestSolver()
|
||||||
|
|
||||||
class singleWorker(threading.Thread, helper_threading.StoppableThread):
|
class singleWorker(threading.Thread, helper_threading.StoppableThread):
|
||||||
name = "singleWorker"
|
name = "singleWorker"
|
||||||
|
|
||||||
|
@ -235,41 +295,7 @@ class singleWorker(threading.Thread, helper_threading.StoppableThread):
|
||||||
super(self.__class__, self).stopThread()
|
super(self.__class__, self).stopThread()
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
GPUVendor = bmconfigparser.BMConfigParser().safeGet("bitmessagesettings", "opencl")
|
workProver.start()
|
||||||
|
|
||||||
self.workProver = workprover.WorkProver(
|
|
||||||
os.path.join(paths.codePath(), "workprover"),
|
|
||||||
GPUVendor,
|
|
||||||
helper_random.randomBytes(32),
|
|
||||||
lambda status: queues.UISignalQueue.put(("updateWorkProverStatus", status)),
|
|
||||||
queues.workerQueue
|
|
||||||
)
|
|
||||||
|
|
||||||
self.workProver.start()
|
|
||||||
|
|
||||||
parallelism = bmconfigparser.BMConfigParser().safeGetInt("bitmessagesettings", "maxcores")
|
|
||||||
|
|
||||||
if parallelism < 1:
|
|
||||||
parallelism = self.workProver.defaultParallelism
|
|
||||||
|
|
||||||
debug.logger.info("Availabe solvers: %s", str(self.workProver.availableSolvers.keys()))
|
|
||||||
|
|
||||||
if "gpu" in self.workProver.availableSolvers and GPUVendor is not None:
|
|
||||||
self.workProver.commandsQueue.put(("setSolver", "gpu", None))
|
|
||||||
elif "fast" in self.workProver.availableSolvers:
|
|
||||||
self.workProver.commandsQueue.put(("setSolver", "fast", parallelism))
|
|
||||||
elif "forking" in self.workProver.availableSolvers:
|
|
||||||
self.workProver.commandsQueue.put(("setSolver", "forking", parallelism))
|
|
||||||
else:
|
|
||||||
self.workProver.commandsQueue.put(("setSolver", "dumb", None))
|
|
||||||
|
|
||||||
if "fast" not in self.workProver.availableSolvers:
|
|
||||||
queues.UISignalQueue.put(("updateStatusBar", (
|
|
||||||
tr._translate(
|
|
||||||
"proofofwork",
|
|
||||||
"C PoW module unavailable. Please build it."
|
|
||||||
), 1
|
|
||||||
)))
|
|
||||||
|
|
||||||
self.startedWorks = {}
|
self.startedWorks = {}
|
||||||
|
|
||||||
|
@ -299,16 +325,34 @@ class singleWorker(threading.Thread, helper_threading.StoppableThread):
|
||||||
self.requestPubkey(*arguments)
|
self.requestPubkey(*arguments)
|
||||||
elif command == "resetPoW":
|
elif command == "resetPoW":
|
||||||
pass
|
pass
|
||||||
|
elif command == "GPUError":
|
||||||
|
self.handleGPUError(*arguments)
|
||||||
elif command == "taskDone":
|
elif command == "taskDone":
|
||||||
self.workDone(*arguments)
|
self.workDone(*arguments)
|
||||||
elif command == "stopThread":
|
elif command == "stopThread":
|
||||||
self.workProver.commandsQueue.put(("shutdown", ))
|
workProver.commandsQueue.put(("shutdown", ))
|
||||||
self.workProver.join()
|
workProver.join()
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
debug.logger.info("Quitting...")
|
debug.logger.info("Quitting...")
|
||||||
|
|
||||||
|
def handleGPUError(self):
|
||||||
|
bmconfigparser.BMConfigParser().set("bitmessagesettings", "powsolver", "dumb")
|
||||||
|
|
||||||
|
workProver.commandsQueue.put(("setSolver", "dumb", None))
|
||||||
|
|
||||||
|
debug.logger.error(
|
||||||
|
"Your GPU(s) did not calculate correctly, disabling OpenCL. Please report to the developers"
|
||||||
|
)
|
||||||
|
|
||||||
|
queues.UISignalQueue.put(("updateStatusBar", (
|
||||||
|
tr._translate(
|
||||||
|
"MainWindow",
|
||||||
|
"Your GPU(s) did not calculate correctly, disabling OpenCL. Please report to the developers."
|
||||||
|
), 1
|
||||||
|
)))
|
||||||
|
|
||||||
def startWork(self, ID, headlessPayload, TTL, expiryTime, byteDifficulty, lengthExtension, logPrefix, callback):
|
def startWork(self, ID, headlessPayload, TTL, expiryTime, byteDifficulty, lengthExtension, logPrefix, callback):
|
||||||
debug.logger.info(
|
debug.logger.info(
|
||||||
"%s Starting work %s, payload length = %s, TTL = %s",
|
"%s Starting work %s, payload length = %s, TTL = %s",
|
||||||
|
@ -317,7 +361,7 @@ class singleWorker(threading.Thread, helper_threading.StoppableThread):
|
||||||
|
|
||||||
self.startedWorks[ID] = callback
|
self.startedWorks[ID] = callback
|
||||||
|
|
||||||
self.workProver.commandsQueue.put((
|
workProver.commandsQueue.put((
|
||||||
"addTask", ID, headlessPayload, TTL, expiryTime,
|
"addTask", ID, headlessPayload, TTL, expiryTime,
|
||||||
byteDifficulty, lengthExtension
|
byteDifficulty, lengthExtension
|
||||||
))
|
))
|
||||||
|
@ -588,7 +632,7 @@ class singleWorker(threading.Thread, helper_threading.StoppableThread):
|
||||||
if ID in self.startedWorks:
|
if ID in self.startedWorks:
|
||||||
del self.startedWorks[ID]
|
del self.startedWorks[ID]
|
||||||
|
|
||||||
self.workProver.commandsQueue.put(("cancelTask", ID))
|
workProver.commandsQueue.put(("cancelTask", ID))
|
||||||
|
|
||||||
helper_sql.sqlExecute("""
|
helper_sql.sqlExecute("""
|
||||||
UPDATE "sent" SET "status" = 'broadcastcanceled'
|
UPDATE "sent" SET "status" = 'broadcastcanceled'
|
||||||
|
@ -906,14 +950,14 @@ class singleWorker(threading.Thread, helper_threading.StoppableThread):
|
||||||
if ID in self.startedWorks:
|
if ID in self.startedWorks:
|
||||||
del self.startedWorks[ID]
|
del self.startedWorks[ID]
|
||||||
|
|
||||||
self.workProver.commandsQueue.put(("cancelTask", ID))
|
workProver.commandsQueue.put(("cancelTask", ID))
|
||||||
|
|
||||||
ID = "message", ackData
|
ID = "message", ackData
|
||||||
|
|
||||||
if ID in self.startedWorks:
|
if ID in self.startedWorks:
|
||||||
del self.startedWorks[ID]
|
del self.startedWorks[ID]
|
||||||
|
|
||||||
self.workProver.commandsQueue.put(("cancelTask", ID))
|
workProver.commandsQueue.put(("cancelTask", ID))
|
||||||
|
|
||||||
state.watchedAckData -= {ackData}
|
state.watchedAckData -= {ackData}
|
||||||
|
|
||||||
|
@ -933,7 +977,7 @@ class singleWorker(threading.Thread, helper_threading.StoppableThread):
|
||||||
if ID in self.startedWorks:
|
if ID in self.startedWorks:
|
||||||
del self.startedWorks[ID]
|
del self.startedWorks[ID]
|
||||||
|
|
||||||
self.workProver.commandsQueue.put(("cancelTask", ID))
|
workProver.commandsQueue.put(("cancelTask", ID))
|
||||||
|
|
||||||
status, version, stream, ripe = addresses.decodeAddress(destination)
|
status, version, stream, ripe = addresses.decodeAddress(destination)
|
||||||
|
|
||||||
|
|
|
@ -30,10 +30,12 @@ class Task(object):
|
||||||
|
|
||||||
Status = collections.namedtuple("Status", ["solverName", "solverStatus", "speed", "tasksCount", "difficulty"])
|
Status = collections.namedtuple("Status", ["solverName", "solverStatus", "speed", "tasksCount", "difficulty"])
|
||||||
|
|
||||||
|
# Only one instance allowed
|
||||||
|
|
||||||
class WorkProver(threading.Thread):
|
class WorkProver(threading.Thread):
|
||||||
# Seed must be 32 bytes
|
# Seed must be 32 bytes
|
||||||
|
|
||||||
def __init__(self, codePath, GPUVendor, seed, statusUpdated, resultsQueue):
|
def __init__(self, codePath, seed, statusUpdated, resultsQueue):
|
||||||
super(self.__class__, self).__init__()
|
super(self.__class__, self).__init__()
|
||||||
|
|
||||||
self.availableSolvers = {
|
self.availableSolvers = {
|
||||||
|
@ -56,7 +58,7 @@ class WorkProver(threading.Thread):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.availableSolvers["gpu"] = gpusolver.GPUSolver(codePath, GPUVendor)
|
self.availableSolvers["gpu"] = gpusolver.GPUSolver(codePath)
|
||||||
except gpusolver.GPUSolverError:
|
except gpusolver.GPUSolverError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -99,23 +101,29 @@ class WorkProver(threading.Thread):
|
||||||
self.statusUpdated(Status(self.solverName, status, self.speed, len(self.tasks), self.totalDifficulty))
|
self.statusUpdated(Status(self.solverName, status, self.speed, len(self.tasks), self.totalDifficulty))
|
||||||
|
|
||||||
def setSolver(self, name, configuration):
|
def setSolver(self, name, configuration):
|
||||||
if name is None and self.solverName is None:
|
try:
|
||||||
pass
|
if name is None and self.solverName is None:
|
||||||
elif name == self.solverName:
|
pass
|
||||||
self.solver.setConfiguration(configuration)
|
elif name == self.solverName:
|
||||||
else:
|
|
||||||
if self.solver is not None:
|
|
||||||
self.solver.setConfiguration(None)
|
|
||||||
self.solverName = None
|
|
||||||
self.solver = None
|
|
||||||
|
|
||||||
if name is not None:
|
|
||||||
if name not in self.availableSolvers:
|
|
||||||
name, configuration = "dumb", None
|
|
||||||
|
|
||||||
self.solverName = name
|
|
||||||
self.solver = self.availableSolvers[name]
|
|
||||||
self.solver.setConfiguration(configuration)
|
self.solver.setConfiguration(configuration)
|
||||||
|
else:
|
||||||
|
if self.solver is not None:
|
||||||
|
self.solver.setConfiguration(None)
|
||||||
|
self.solverName = None
|
||||||
|
self.solver = None
|
||||||
|
|
||||||
|
if name is not None:
|
||||||
|
if name not in self.availableSolvers:
|
||||||
|
name, configuration = "dumb", None
|
||||||
|
|
||||||
|
self.solverName = name
|
||||||
|
self.solver = self.availableSolvers[name]
|
||||||
|
self.solver.setConfiguration(configuration)
|
||||||
|
except GPUSolverError:
|
||||||
|
self.solverName = None
|
||||||
|
self.solver = None
|
||||||
|
|
||||||
|
self.resultsQueue.put(("GPUError", ))
|
||||||
|
|
||||||
self.notifyStatus()
|
self.notifyStatus()
|
||||||
|
|
||||||
|
@ -229,8 +237,9 @@ class WorkProver(threading.Thread):
|
||||||
try:
|
try:
|
||||||
nonce, iterationsCount = self.solver.search(initialHash, task.target, appendedSeed, timeout)
|
nonce, iterationsCount = self.solver.search(initialHash, task.target, appendedSeed, timeout)
|
||||||
except gpusolver.GPUSolverError:
|
except gpusolver.GPUSolverError:
|
||||||
self.setSolver("dumb", 1)
|
self.setSolver(None, None)
|
||||||
self.availableSolvers.pop("gpu")
|
|
||||||
|
self.resultsQueue.put(("GPUError", ))
|
||||||
|
|
||||||
nonce, iterationsCount = None, 0
|
nonce, iterationsCount = None, 0
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,8 @@ def loadFastSolver(codePath):
|
||||||
except:
|
except:
|
||||||
raise FastSolverError()
|
raise FastSolverError()
|
||||||
|
|
||||||
|
# Only one instance allowed
|
||||||
|
|
||||||
class FastSolver(object):
|
class FastSolver(object):
|
||||||
def __init__(self, codePath):
|
def __init__(self, codePath):
|
||||||
self.libfastsolver = loadFastSolver(codePath)
|
self.libfastsolver = loadFastSolver(codePath)
|
||||||
|
|
|
@ -11,7 +11,7 @@ class GPUSolverError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class GPUSolver(object):
|
class GPUSolver(object):
|
||||||
def __init__(self, codePath, vendor = None):
|
def __init__(self, codePath):
|
||||||
global pyopencl
|
global pyopencl
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -19,17 +19,15 @@ class GPUSolver(object):
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise GPUSolverError()
|
raise GPUSolverError()
|
||||||
|
|
||||||
for i in pyopencl.get_platforms():
|
self.vendors = {}
|
||||||
if vendor is not None and i.vendor != vendor:
|
|
||||||
continue
|
|
||||||
|
|
||||||
|
for i in pyopencl.get_platforms():
|
||||||
devices = i.get_devices(device_type = pyopencl.device_type.GPU)
|
devices = i.get_devices(device_type = pyopencl.device_type.GPU)
|
||||||
|
|
||||||
if len(devices) != 0:
|
if len(devices) != 0:
|
||||||
self.device = devices[0]
|
self.vendors[i.vendor] = devices[0]
|
||||||
|
|
||||||
break
|
if len(self.vendors) == 0:
|
||||||
else:
|
|
||||||
raise GPUSolverError()
|
raise GPUSolverError()
|
||||||
|
|
||||||
with open(os.path.join(codePath, "gpusolver.cl")) as file:
|
with open(os.path.join(codePath, "gpusolver.cl")) as file:
|
||||||
|
@ -88,14 +86,21 @@ class GPUSolver(object):
|
||||||
|
|
||||||
import numpy
|
import numpy
|
||||||
|
|
||||||
context = pyopencl.Context(devices = [self.device])
|
if configuration is None:
|
||||||
|
configuration = self.vendors.keys()[0]
|
||||||
|
|
||||||
computeUnitsCount = self.device.get_info(pyopencl.device_info.MAX_COMPUTE_UNITS)
|
if configuration not in self.vendors:
|
||||||
workGroupSize = self.device.get_info(pyopencl.device_info.MAX_WORK_GROUP_SIZE)
|
raise GPUSolverError()
|
||||||
|
|
||||||
|
device = self.vendors[configuration]
|
||||||
|
context = pyopencl.Context(devices = [device])
|
||||||
|
|
||||||
|
computeUnitsCount = device.get_info(pyopencl.device_info.MAX_COMPUTE_UNITS)
|
||||||
|
workGroupSize = device.get_info(pyopencl.device_info.MAX_WORK_GROUP_SIZE)
|
||||||
|
|
||||||
self.batchSize = workGroupSize * computeUnitsCount * 256
|
self.batchSize = workGroupSize * computeUnitsCount * 256
|
||||||
|
|
||||||
self.queue = pyopencl.CommandQueue(context, self.device)
|
self.queue = pyopencl.CommandQueue(context, device)
|
||||||
|
|
||||||
program = pyopencl.Program(context, self.source).build()
|
program = pyopencl.Program(context, self.source).build()
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,7 @@ class TestGPUSolver(TestSolver):
|
||||||
|
|
||||||
class TestWorkProver(unittest.TestCase):
|
class TestWorkProver(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.thread = __init__.WorkProver(codePath, None, seed, None, None)
|
self.thread = __init__.WorkProver(codePath, seed, None, None)
|
||||||
self.thread.start()
|
self.thread.start()
|
||||||
|
|
||||||
def checkTaskLinks(self):
|
def checkTaskLinks(self):
|
||||||
|
|
Reference in New Issue
Block a user